zoukankan      html  css  js  c++  java
  • 安卓高手之路之 应用篇

    安卓高手之路之 应用篇 - 修补C++ - ITeye技术网站

    1. 安装应用流程:

         PackageManagerService的installPackage 调用 InstallArgs的copyAPK完成了安装。如果在SD卡中,那么调用SdInstallArgs的copyApk完成安装。

    2. 应用启动流程:

      首先,直接从ActivityManagerService入手,首先调用startActivity这个函数:

         public final int startActivity(IApplicationThread caller,
                Intent intent, String resolvedType, Uri[] grantedUriPermissions,
                int grantedMode, IBinder resultTo,
                String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
                String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
            return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
                    grantedUriPermissions, grantedMode, resultTo, resultWho,
                    requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
                    null, null);
        }

    下面看AcitivityStack,

      final int startActivityMayWait(IApplicationThread caller, int callingUid,
                Intent intent, String resolvedType, Uri[] grantedUriPermissions,
                int grantedMode, IBinder resultTo,
                String resultWho, int requestCode, boolean onlyIfNeeded,
                boolean debug, String profileFile, ParcelFileDescriptor profileFd,
                boolean autoStopProfiler, WaitResult outResult, Configuration config) {

    这个函数比较长,下面只看关键部位:

      
            // Collect information about the target of the Intent.
            ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
                    profileFile, profileFd, autoStopProfiler);

     这个调到了PackageManager里面的resolveActivity方法里面。这里既暂时不说了。后面再讨论。

      往下继续看:

     看到一个重量级app的含义,经分析,这样的app会在状态栏,发送一个如下的图标:

        

     

    所以那段代码直接忽略。往下看,看到如下一句话:

     int res = startActivityLocked(caller, intent, resolvedType,
                        grantedUriPermissions, grantedMode, aInfo,
                        resultTo, resultWho, requestCode, callingPid, callingUid,
                        onlyIfNeeded, componentSpecified, null);

    这个方法比较长,要有耐性:

      ProcessRecord callerApp = null;
            if (caller != null) {
                callerApp = mService.getRecordForAppLocked(caller);
                if (callerApp != null) {
                    callingPid = callerApp.pid;
                    callingUid = callerApp.info.uid;
                } else {
                    Slog.w(TAG, "Unable to find app for caller " + caller
                          + " (pid=" + callingPid + ") when starting: "
                          + intent.toString());
                    err = START_PERMISSION_DENIED;
                }
            }
    这段话找出调用者的ProcessRecord

            ActivityRecord sourceRecord = null;
            ActivityRecord resultRecord = null;
            if (resultTo != null) {
                int index = indexOfTokenLocked(resultTo);
                if (DEBUG_RESULTS) Slog.v(
                    TAG, "Will send result to " + resultTo + " (index " + index + ")");
                if (index >= 0) {
                    sourceRecord = mHistory.get(index);
                    if (requestCode >= 0 && !sourceRecord.finishing) {
                        resultRecord = sourceRecord;
                    }
                }
            }

    这段话,找出一个resultRecord。

     然后是这句话

     final int perm = mService.checkComponentPermission(aInfo.permission, callingPid,
                    callingUid, aInfo.applicationInfo.uid, aInfo.exported); 这个是权限检测,后面再说。

    下面这句话

      if (mMainStack) {
                if (mService.mController != null) {
                    boolean abort = false;
                    try {
                        // The Intent we give to the watcher has the extra data
                        // stripped off, since it can contain private information.
                        Intent watchIntent = intent.cloneFilter();
                        abort = !mService.mController.activityStarting(watchIntent,
                                aInfo.applicationInfo.packageName);
                    } catch (RemoteException e) {
                        mService.mController = null;
                    }
       
                    if (abort) {
                        if (resultRecord != null) {
                            sendActivityResultLocked(-1,
                                resultRecord, resultWho, requestCode,
                                Activity.RESULT_CANCELED, null);
                        }
                        // We pretend to the caller that it was really started, but
                        // they will just get a cancel result.
                        mDismissKeyguardOnNextActivity = false;
                        return START_SUCCESS;
                    }
                }
            }

     有时候可以设置一个Controller到AcitivytManagerservice中。具体AM.java文件中有引用。例如,从命令行启动Acitivity。

        ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
                    intent, resolvedType, aInfo, mService.mConfiguration,
                    resultRecord, resultWho, requestCode, componentSpecified);
            if (outActivity != null) {
                outActivity[0] = r;
            }

            if (mMainStack) {
                if (mResumedActivity == null
                        || mResumedActivity.info.applicationInfo.uid != callingUid) {
                    if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
                        PendingActivityLaunch pal = new PendingActivityLaunch();
                        pal.r = r;
                        pal.sourceRecord = sourceRecord;
                        pal.grantedUriPermissions = grantedUriPermissions;
                        pal.grantedMode = grantedMode;
                        pal.onlyIfNeeded = onlyIfNeeded;
                        mService.mPendingActivityLaunches.add(pal);
                        mDismissKeyguardOnNextActivity = false;
                        return START_SWITCHES_CANCELED;
                    }
                }
           
                if (mService.mDidAppSwitch) {
                    // This is the second allowed switch since we stopped switches,
                    // so now just generally allow switches.  Use case: user presses
                    // home (switches disabled, switch to home, mDidAppSwitch now true);
                    // user taps a home icon (coming from home so allowed, we hit here
                    // and now allow anyone to switch again).
                    mService.mAppSwitchesAllowedTime = 0;
                } else {
                    mService.mDidAppSwitch = true;
                }
            
                mService.doPendingActivityLaunchesLocked(false);
            }

    关键是红色标注的那一句话。

        final int N = mPendingActivityLaunches.size();
            if (N <= 0) {
                return;
            }
            for (int i=0; i<N; i++) {
                PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
                mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
                        pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
                        doResume && i == (N-1));
            }
            mPendingActivityLaunches.clear();

    把3PendingLaunch的进行启动。

      最终进入:

     err = startActivityUncheckedLocked(r, sourceRecord,
                    grantedUriPermissions, grantedMode, onlyIfNeeded, true);
            if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
                // Someone asked to have the keyguard dismissed on the next
                // activity start, but we are not actually doing an activity
                // switch...  just dismiss the keyguard now, because we
                // probably want to see whatever is behind it.
                mDismissKeyguardOnNextActivity = false;
                mService.mWindowManager.dismissKeyguard();
            }
            return err;

     err = startActivityUncheckedLocked(r, sourceRecord,
                    grantedUriPermissions, grantedMode, onlyIfNeeded, true);
            if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
                // Someone asked to have the keyguard dismissed on the next
                // activity start, but we are not actually doing an activity
                // switch...  just dismiss the keyguard now, because we
                // probably want to see whatever is behind it.
                mDismissKeyguardOnNextActivity = false;
                mService.mWindowManager.dismissKeyguard();
            }
            return err;

    startActivityUncheckedLocked 这个方法也是很长。

     其中FLAG_ACTIVITY_PREVIOUS_IS_TOP 说的是current不是top,之前的是top。也就是说,r不算是top。

       ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
                    != 0 ? r : null;

      if (sourceRecord == null) {
                // This activity is not being started from another...  in this
                // case we -always- start a new task.
                if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
                    Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
                          + intent);
                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
                }
           

    不是从Acitivity启动的话,就要加一个newTask标志。这也可以说是同一个task的一个条件吧。

      if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
                // The original activity who is starting us is running as a single
                // instance...  this new activity it is starting must go on its
                // own task.
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;

    这个说的是如果sourceActivity是一个singleton,那么也启动一个newtask。

    else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
                // The activity being started is a single instance...  it always
                // gets launched into its own task.
                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
            }

    或者说,自己是一个singletatask或者singleinstance。那么也是newtask。

     LAUNCH_SINGLE_INSTANCE 一定是.LAUNCH_SINGLE_TASK,.LAUNCH_SINGLE_TASK 不一定是

    LAUNCH_SINGLE_INSTANCE

    既然是singletask,那么无法退出结果给 resultTo:

            if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
                // For whatever reason this activity is being launched into a new
                // task...  yet the caller has requested a result back.  Well, that
                // is pretty messed up, so instead immediately send back a cancel
                // and let the new task continue launched as normal without a
                // dependency on its originator.
                Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
                sendActivityResultLocked(-1,
                        r.resultTo, r.resultWho, r.requestCode,
                    Activity.RESULT_CANCELED, null);
                r.resultTo = null;
            }

    下面判断很有意思,如果是一个newTask

    if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
                    (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
                    || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE)

    找到top的task

      ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
                            ? findTaskLocked(intent, r.info)
                            : findActivityLocked(intent, r.info);

     如果是LAUNCH_SINGLE_INSTANCE,那么就全找。否则,过滤掉LAUNCH_SINGLE_INSTANCE的activity。并且,找到一个task与此相同的。也就是说是new——task,并且不是singleton,这种情况下,找所有task的顶层activity。看是否满足条件。

                        ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
                        if (curTop != null && curTop.task != taskTop.task) {
                            r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
                            boolean callerAtFront = sourceRecord == null
                                    || curTop.task == sourceRecord.task;
                            if (callerAtFront) {
                                // We really do want to push this one into the
                                // user's face, right now.
                                moveHomeToFrontFromLaunchLocked(launchFlags);
                                moveTaskToFrontLocked(taskTop.task, r);
                            }
                        }

    新任务与当前的topTask不同的时候,先把home加到前面,然后把当前的加到前面。考虑的时候,排除notTop。

     if (onlyIfNeeded) {
                            // We don't need to start a new activity, and
                            // the client said not to do anything if that
                            // is the case, so this is it!  And for paranoia, make
                            // sure we have correctly resumed the top activity.
                            if (doResume) {
                                resumeTopActivityLocked(null);
                            }
                            return START_RETURN_INTENT_TO_CALLER;
                        }

    不需要启动activity。只是resumetop。

     if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                                    && taskTop.realActivity.equals(r.realActivity)) {
                                logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
                                if (taskTop.frontOfTask) {
                                    taskTop.task.setIntent(r.intent, r.info);
                                }
                                taskTop.deliverNewIntentLocked(callingUid, r.intent);
                            }

     调用onNewInent。如果已经在top,那么就不再启动新的activity。

    if (!addingToTask && reuseTask == null) {
                            // We didn't do anything...  but it was needed (a.k.a., client
                            // don't use that intent!)  And for paranoia, make
                            // sure we have correctly resumed the top activity.
                            if (doResume) {
                                resumeTopActivityLocked(null);
                            }
                            return START_TASK_TO_FRONT;
                        }

    不添加新的task,也不用旧的task,就什么都不干。

    以上全是处理的newtask,singletask,singleinstance的东西。

     if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
                                logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
                                // For paranoia, make sure we have correctly
                                // resumed the top activity.
                                if (doResume) {
                                    resumeTopActivityLocked(null);
                                }
                                if (onlyIfNeeded) {
                                    // We don't need to start a new activity, and
                                    // the client said not to do anything if that
                                    // is the case, so this is it!
                                    return START_RETURN_INTENT_TO_CALLER;
                                }
                                top.deliverNewIntentLocked(callingUid, r.intent);
                                return START_DELIVERED_TO_TOP;

    如果是singletop,singletask,并且有一个在top,就直接onNewIntent。

    最终进入ActivityStack的

    startActivityLocked

    最终进入:

        private final void startActivityLocked(ActivityRecord r, boolean newTask,
                boolean doResume, boolean keepCurTransition) {

    放入activity堆栈后,调用resumeTopActivityLocked
        final boolean resumeTopActivityLocked(ActivityRecord prev)

    然后调用

     startSpecificActivityLocked(next, true, true);

     这个就是如下代码


        private final void startSpecificActivityLocked(ActivityRecord r,
                boolean andResume, boolean checkConfig) {
            // Is this activity's application already running?
            ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                    r.info.applicationInfo.uid);
           
            if (r.launchTime == 0) {
                r.launchTime = SystemClock.uptimeMillis();
                if (mInitialStartTime == 0) {
                    mInitialStartTime = r.launchTime;
                }
            } else if (mInitialStartTime == 0) {
                mInitialStartTime = SystemClock.uptimeMillis();
            }
           
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.info.packageName);
                    realStartActivityLocked(r, app, andResume, checkConfig);
                    return;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting activity "
                            + r.intent.getComponent().flattenToShortString(), e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }

            mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                    "activity", r.intent.getComponent(), false);
        }

    要么调用 realStartActivityLocked(r, app, andResume, checkConfig);

    要么调用 startProcessLocked

    realStartActivityLocked  调用 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                        new Configuration(mService.mConfiguration),
                        r.compat, r.icicle, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profileFile, profileFd,
                        profileAutoStop);

    而 startProcessLocked调用

        private final void startProcessLocked(ProcessRecord app,
                String hostingType, String hostingNameStr) {

    下面是一些dbug开关。

                if ("1".equals(SystemProperties.get("debug.checkjni"))) {
                    debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
                }
                if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
                    debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
                }
                if ("1".equals(SystemProperties.get("debug.assert"))) {
                    debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
                }

    调用如下来启动进程:

      // Start the process.  It will either succeed and return a result containing
                // the PID of the new process, or else throw a RuntimeException.
                Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                        app.processName, uid, uid, gids, debugFlags,
                        app.info.targetSdkVersion, null);

      然后掉到ActivityThread的:

     private void attach(boolean system) 方法中

    对于非系统进程就这几句话:

     ViewRootImpl.addFirstDrawHandler(new Runnable() {
                    public void run() {
                        ensureJitEnabled();
                    }
                });
                android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
                RuntimeInit.setApplicationObject(mAppThread.asBinder());
                IActivityManager mgr = ActivityManagerNative.getDefault();
                try {
                    mgr.attachApplication(mAppThread);
                } catch (RemoteException ex) {
                    // Ignore
                }

    调用到


        public final void attachApplication(IApplicationThread thread) {
            synchronized (this) {
                int callingPid = Binder.getCallingPid();
                final long origId = Binder.clearCallingIdentity();
                attachApplicationLocked(thread, callingPid);
                Binder.restoreCallingIdentity(origId);
            }
        }

    最终回调到ActivityThread的

    private void handleBindApplication(AppBindData data)

    等待调试的地方在这个地方:

     if (data.debugMode != IApplicationThread.DEBUG_OFF) {
                // XXX should have option to change the port.
                Debug.changeDebugPort(8100);
                if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
                    Slog.w(TAG, "Application " + data.info.getPackageName()
                          + " is waiting for the debugger on port 8100...");

                    IActivityManager mgr = ActivityManagerNative.getDefault();
                    try {
                        mgr.showWaitingForDebugger(mAppThread, true);
                    } catch (RemoteException ex) {
                    }

                    Debug.waitForDebugger();

                    try {
                        mgr.showWaitingForDebugger(mAppThread, false);
                    } catch (RemoteException ex) {
                    }

                } else {
                    Slog.w(TAG, "Application " + data.info.getPackageName()
                          + " can be debugged on port 8100...");
                }
            }

     初始化context

      ContextImpl appContext = new ContextImpl();
                appContext.init(data.info, null, this);
                InstrumentationInfo ii = null;

     获得apk的信息。
                ApplicationInfo instrApp = new ApplicationInfo();
                instrApp.packageName = ii.packageName;
                instrApp.sourceDir = ii.sourceDir;
                instrApp.publicSourceDir = ii.publicSourceDir;
                instrApp.dataDir = ii.dataDir;
                instrApp.nativeLibraryDir = ii.nativeLibraryDir;
                LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true);

    ContextImpl instrContext = new ContextImpl();
                instrContext.init(pi, null, this);

    初始化instrContext

    如果没有instrument则

     mInstrumentation = new Instrumentation();

      // If the app is being launched for full backup or restore, bring it up in
            // a restricted environment with the base application class.
            Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode){
                List<ProviderInfo> providers = data.providers;
                if (providers != null) {
                    installContentProviders(app, providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            try {
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }

    创造一个应用,并且调用app的 onCreate方法。

    下面进入app的onCreate方法

    然后

     // See if the top visible activity is waiting to run in this process...
            ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
            if (hr != null && normalMode) {
                if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
                        && processName.equals(hr.processName)) {
                    try {
                        if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                            didSomething = true;
                        }
                    } catch (Exception e) {
                        Slog.w(TAG, "Exception in new application when starting activity "
                              + hr.intent.getComponent().flattenToShortString(), e);
                        badApp = true;
                    }
                } else {
                    mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
                }
            }

    找到toplevel Activity进行启动。这个toplevelActivity就是刚才要启动的activity。这样activity就与新创建的进程进行了关联。

  • 相关阅读:
    backtrace、backtrace_symbols、backtrace_symbols_fd-support for application self-debugging
    基于linux与busybox的reboot命令流程分析
    Ubuntu Linux 查看、编辑、比较二进制文件
    SecureCRT中的vim出现1H特殊字符
    单例模式和静态方法
    linux ls命令按时间显示文件
    Shallow Heap & Retained Heap
    jedis连接池的参数配置
    jvm参数设置和性能调优
    并发和并行的区别
  • 原文地址:https://www.cnblogs.com/seven1979/p/4369591.html
Copyright © 2011-2022 走看看