安卓高手之路之 应用篇

xiaoxiao2021-02-28  94

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就与新创建的进程进行了关联。

 

 

 

大小: 903 Bytes 查看图片附件
转载请注明原文地址: https://www.6miu.com/read-77225.html

最新回复(0)