privateclassNavigationViewInfo( val hostRef: WeakReference<View>, val viewRef: WeakReference<View>, val rawBottom: Int, val onNavHeightChangeListener: (View, Int, Int) -> Unit )
privateval onApplyWindowInsetsListener = View.OnApplyWindowInsetsListener { v, insets -> val windowInsetsCompat = WindowInsetsCompat.toWindowInsetsCompat(insets, v) val navHeight = windowInsetsCompat.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom val it = navigationViewInfoList.iterator() while (it.hasNext()) { val info = it.next() val host = info.hostRef.get() val view = info.viewRef.get() if (host == null || view == null) { it.remove() continue }
privatefunfixSingleNavBarMargin(view: View) { val lp = view.layoutParams as? ViewGroup.MarginLayoutParams ?: return val rawBottomMargin = lp.bottomMargin
val viewForCalculate = getViewForCalculate(view)
if (viewForCalculate.isAttachedToWindow) { val realNavigationBarHeight = getRealNavigationBarHeight(viewForCalculate) lp.bottomMargin = rawBottomMargin + realNavigationBarHeight view.requestLayout() } //isAttachedToWindow方法并不能保证此时的WindowInsets是正确的,仍然需要添加监听 val hostRef = WeakReference(viewForCalculate) val viewRef = WeakReference(view) val info = NavigationViewInfo(hostRef, viewRef, rawBottomMargin, actionMarginNavigation) navigationViewInfoList.add(info) viewForCalculate.setOnApplyWindowInsetsListener(onApplyWindowInsetsListener) }
funpaddingByNavBar(view: View) { val rawBottomPadding = view.paddingBottom
val viewForCalculate = getViewForCalculate(view)
if (viewForCalculate.isAttachedToWindow) { val realNavigationBarHeight = getRealNavigationBarHeight(viewForCalculate) view.setPadding( view.paddingLeft, view.paddingTop, view.paddingRight, rawBottomPadding + realNavigationBarHeight ) }
//isAttachedToWindow方法并不能保证此时的WindowInsets是正确的,仍然需要添加监听 val hostRef = WeakReference(viewForCalculate) val viewRef = WeakReference(view) val info = NavigationViewInfo(hostRef, viewRef, rawBottomPadding, actionPaddingNavigation) navigationViewInfoList.add(info) viewForCalculate.setOnApplyWindowInsetsListener(onApplyWindowInsetsListener) }
privatebooleanattachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq){ ...
// See if the top visible activity is waiting to run in this process... //检查是否有Activity等待启动 if (normalMode) { try { didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); } catch (Exception e) { badApp = true; } }
//确保所有Activity都已暂停 if (!mRootWindowContainer.allPausedActivitiesComplete()) { // While there are activities pausing we skipping starting any new activities until // pauses are complete. NOTE: that we also do this for activities that are starting in // the paused state because they will first be resumed then paused on the client side. returnfalse; }
final Task task = r.getTask(); final ActivityStack stack = task.getStack();
// schedule launch ticks to collect information about slow apps. //收集启动缓慢信息 r.startLaunchTickingLocked();
r.setProcess(proc);
// Ensure activity is allowed to be resumed after process has set. //确保Activity允许被resume if (andResume && !r.canResumeByCompat()) { andResume = false; }
// Have the window manager re-evaluate the orientation of the screen based on the new // activity order. Note that as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, because the activity is // not currently running so we are just restarting it anyway. if (checkConfig) { // Deferring resume here because we're going to launch new activity shortly. // We don't want to perform a redundant launch of the same record while ensuring // configurations and trying to resume top activity of focused stack. //确保所有Activity的可见性、更新屏幕方向和配置 mRootWindowContainer.ensureVisibilityAndConfig(r, r.getDisplayId(), false/* markFrozenIfConfigChanged */, true/* deferResume */); }
//检查Activity是否在后台锁屏状态下启动 if (r.getRootTask().checkKeyguardVisibility(r, true/* shouldBeVisible */, true/* isTop */) && r.allowMoveToFront()) { // We only set the visibility to true if the activity is not being launched in // background, and is allowed to be visible based on keyguard state. This avoids // setting this into motion in window manager that is later cancelled due to later // calls to ensure visible activities that set visibility back to false. //只有Activity不是在后台启动,才将其可见性设置为true r.setVisibility(true); }
try { if (!proc.hasThread()) { thrownew RemoteException(); } List<ResultInfo> results = null; List<ReferrerIntent> newIntents = null; if (andResume) { // We don't need to deliver new intents and/or set results if activity is going // to pause immediately after launch. results = r.results; newIntents = r.newIntents; } //如果是ACTIVITY_TYPE_HOME类型的应用(Launcher) if (r.isActivityTypeHome()) { // Home process is the root process of the task. updateHomeProcess(task.getBottomMostActivity().app); } //信息记录 mService.getPackageManagerInternalLocked().notifyPackageUse( r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY); r.setSleeping(false); r.forceNewConfig = false; //如果有必要的话,显示一些App警告弹窗(不支持的CompileSdk、不支持的TargetSdk、不支持的显示大小) mService.getAppWarningsLocked().onStartActivity(r); //兼容性信息 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
// Because we could be starting an Activity in the system process this may not go // across a Binder interface which would create a new Configuration. Consequently // we have to always create a new Configuration here.
final MergedConfiguration mergedConfiguration = new MergedConfiguration( proc.getConfiguration(), r.getMergedOverrideConfiguration()); r.setLastReportedConfiguration(mergedConfiguration);
final DisplayContent dc = r.getDisplay().mDisplayContent; //添加一条Activity启动消息 clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent), System.identityHashCode(r), r.info, // TODO: Have this take the merged configuration instead of separate global // and override configs. mergedConfiguration.getGlobalConfiguration(), mergedConfiguration.getOverrideConfiguration(), r.compat, r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(), r.assistToken, r.createFixedRotationAdjustmentsIfNeeded()));
// Set desired final state. final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward()); } else { lifecycleItem = PauseActivityItem.obtain(); } //设置client执行事务后应处于的生命周期状态 clientTransaction.setLifecycleStateRequest(lifecycleItem);
//处理重量级进程 if ((proc.mInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 && mService.mHasHeavyWeightFeature) { // This may be a heavy-weight process! Note that the package manager will ensure // that only activity can run in the main process of the .apk, which is the only // thing that will be considered heavy-weight. if (proc.mName.equals(proc.mInfo.packageName)) { if (mService.mHeavyWeightProcess != null && mService.mHeavyWeightProcess != proc) { Slog.w(TAG, "Starting new heavy weight process " + proc + " when already running " + mService.mHeavyWeightProcess); } mService.setHeavyWeightProcess(r); } }
} catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity and give up. //第二次启动失败,finish掉Activity并放弃重试,直接返回false Slog.e(TAG, "Second failure launching " + r.intent.getComponent().flattenToShortString() + ", giving up", e); proc.appDied("2nd-crash"); r.finishIfPossible("2nd-crash", false/* oomAdj */); returnfalse; }
// This is the first time we failed -- restart process and // retry. //第一次启动失败,尝试重启进程并重试启动Activity r.launchFailed = true; proc.removeActivity(r); throw e; } } finally { endDeferResume(); }
r.launchFailed = false;
// TODO(lifecycler): Resume or pause requests are done as part of launch transaction, // so updating the state should be done accordingly. //更新生命周期状态 if (andResume && readyToResume()) { // As part of the process of launching, ActivityThread also performs // a resume. stack.minimalResumeActivityLocked(r); } else { // This activity is not starting in the resumed state... which should look like we asked // it to pause+stop (but remain visible), and it has done so and reported back the // current icicle and other state. r.setState(PAUSED, "realStartActivityLocked"); mRootWindowContainer.executeAppTransitionForAllDisplay(); } // Perform OOM scoring after the activity state is set, so the process can be updated with // the latest state. //更新进程oom adj,更新进程状态 proc.onStartActivity(mService.mTopProcessState, r.info);
// Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. if (mRootWindowContainer.isTopDisplayFocusedStack(stack)) { mService.getActivityStartController().startSetupActivity(); }
// Update any services we are bound to that might care about whether // their client may have activities. //更新进程绑定的所有服务 if (r.app != null) { r.app.updateServiceConnectionActivities(); }
voidscheduleTransaction(ClientTransaction transaction)throws RemoteException { final IApplicationThread client = transaction.getClient(); transaction.schedule(); if (!(client instanceof Binder)) { // If client is not an instance of Binder - it's a remote call and at this point it is // safe to recycle the object. All objects used for local calls will be recycled after // the transaction is executed on client in ActivityThread. transaction.recycle(); } }
publicvoidexecute(ClientTransaction transaction){ final IBinder token = transaction.getActivityToken(); //处理需要销毁的Activities if (token != null) { final Map<IBinder, ClientTransactionItem> activitiesToBeDestroyed = mTransactionHandler.getActivitiesToBeDestroyed(); final ClientTransactionItem destroyItem = activitiesToBeDestroyed.get(token); if (destroyItem != null) { if (transaction.getLifecycleStateRequest() == destroyItem) { // It is going to execute the transaction that will destroy activity with the // token, so the corresponding to-be-destroyed record can be removed. activitiesToBeDestroyed.remove(token); } if (mTransactionHandler.getActivityClient(token) == null) { // The activity has not been created but has been requested to destroy, so all // transactions for the token are just like being cancelled. //Activity尚未被创建就被请求destroy,直接取消整个事务 Slog.w(TAG, tId(transaction) + "Skip pre-destroyed transaction:\n" + transactionToString(transaction, mTransactionHandler)); return; } } }
public Activity handleLaunchActivity(ActivityClientRecord r, PendingTransactionActions pendingActions, Intent customIntent){ // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true;
if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); }
// Make sure we are running with the most recent config. //确保Configuration为最新 handleConfigurationChanged(null, null);
// Initialize before creating the activity //初始化硬件加速 if (!ThreadedRenderer.sRendererDisabled && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { HardwareRenderer.preload(); } //确保WMS被初始化 WindowManagerGlobal.initialize();
// Hint the GraphicsEnvironment that an activity is launching on the process. //通知有Activity启动 GraphicsEnvironment.hintActivityLaunch();
//执行启动Activity final Activity a = performLaunchActivity(r, customIntent);
if (a != null) { //设置Configuration r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); //设置一些延迟执行的动作(作用域到整个ClientTransaction结束) if (!r.activity.mFinished && pendingActions != null) { pendingActions.setOldState(r.state); //当Activity生命周期走到onStart前,会通过这里设置的值 //判断是否需要执行onRestoreInstanceState、onPostCreate pendingActions.setRestoreInstanceState(true); pendingActions.setCallOnPostCreate(true); } } else { // If there was an error, for any reason, tell the activity manager to stop us. //出现错误,停止启动Activity try { ActivityTaskManager.getService() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }
if (activity != null) { //Manifest中Activity标签下的label属性 CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); //准备Configuration Configuration config = new Configuration(mCompatConfiguration); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } Window window = null; //当relaunch Activity的时候mPreserveWindow才会为true(比如说调用Activity.recreate方法) if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; }
// Activity resources must be initialized with the same loaders as the // application context. //设置Activity Resource的Loaders与Application Resource的Loaders一致 appContext.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; //更新网络状态 checkAndBlockForNetworkAccess(); activity.mStartedActivity = false; //设置主题 int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); }
activity.mCalled = false; //调用Activity的onCreate方法 if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { //在执行完super.onCreate方法后,mCalled会被置为true //如果mCalled为false,说明没有执行super.onCreate方法 thrownew SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } r.activity = activity; mLastReportedWindowingMode.put(activity.getActivityToken(), config.windowConfiguration.getWindowingMode()); } //设置生命周期状态为onCreate r.setState(ON_CREATE);
// updatePendingActivityConfiguration() reads from mActivities to update // ActivityClientRecord which runs in a different thread. Protect modifications to // mActivities to avoid race. //将新建的ActivityClientRecord添加到mActivities中 synchronized (mResourcesManager) { mActivities.put(r.token, r); }
privatevoidexecuteLifecycleState(ClientTransaction transaction){ final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest(); if (lifecycleItem == null) { // No lifecycle request, return early. return; }
final IBinder token = transaction.getActivityToken(); final ActivityClientRecord r = mTransactionHandler.getActivityClient(token);
if (r == null) { // Ignore requests for non-existent client records for now. return; }
// Cycle to the state right before the final requested state. //excludeLastState为true的情况下,推进生命周期直到最终生命周期的上一个生命周期 //excludeLastState为false的情况下,推进生命周期直到最终生命周期 cycleToPath(r, lifecycleItem.getTargetState(), true/* excludeLastState */, transaction);
// Execute the final transition with proper parameters. //执行最终的生命周期事务 lifecycleItem.execute(mTransactionHandler, token, mPendingActions); lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions); }
public IntArray getLifecyclePath(int start, int finish, boolean excludeLastState){ ... //错误判断
mLifecycleSequence.clear(); if (finish >= start) { if (start == ON_START && finish == ON_STOP) { // A case when we from start to stop state soon, we don't need to go // through the resumed, paused state. mLifecycleSequence.add(ON_STOP); } else { // just go there //按顺序添加生命周期 for (int i = start + 1; i <= finish; i++) { mLifecycleSequence.add(i); } } } else { // finish < start, can't just cycle down if (start == ON_PAUSE && finish == ON_RESUME) { // Special case when we can just directly go to resumed state. mLifecycleSequence.add(ON_RESUME); } elseif (start <= ON_STOP && finish >= ON_START) { // Restart and go to required state.
// Go to stopped state first. for (int i = start + 1; i <= ON_STOP; i++) { mLifecycleSequence.add(i); } // Restart mLifecycleSequence.add(ON_RESTART); // Go to required state for (int i = ON_START; i <= finish; i++) { mLifecycleSequence.add(i); } } else { // Relaunch and go to required state
// Go to destroyed state first. for (int i = start + 1; i <= ON_DESTROY; i++) { mLifecycleSequence.add(i); } // Go to required state for (int i = ON_CREATE; i <= finish; i++) { mLifecycleSequence.add(i); } } }
// Remove last transition in case we want to perform it with some specific params. if (excludeLastState && mLifecycleSequence.size() != 0) { mLifecycleSequence.remove(mLifecycleSequence.size() - 1); }
publicvoidhandleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason){ // If we are getting ready to gc after going to the background, well // we are back active so skip it. unscheduleGcIdler(); mSomeActivitiesChanged = true;
// TODO Push resumeArgs into the activity for consideration //执行onResume生命周期 final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason); if (r == null) { // We didn't actually resume the activity, so skipping any follow-up actions. return; } //如果Activity将被destroy,那就没必要再执行resume了,直接返回 if (mActivitiesToBeDestroyed.containsKey(token)) { // Although the activity is resumed, it is going to be destroyed. So the following // UI operations are unnecessary and also prevents exception because its token may // be gone that window manager cannot recognize it. All necessary cleanup actions // performed below will be done while handling destruction. return; }
// If the window hasn't yet been added to the window manager, // and this guy didn't finish itself or start another activity, // then go ahead and add the window. boolean willBeVisible = !a.mStartedActivity; if (!willBeVisible) { try { willBeVisible = ActivityTaskManager.getService().willActivityBeVisible( a.getActivityToken()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } //设置Window if (r.window == null && !a.mFinished && willBeVisible) { r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); //DecorView暂时不可见 decor.setVisibility(View.INVISIBLE); ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); //给Activity的mDecor成员变量赋值 a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (r.mPreserveWindow) { a.mWindowAdded = true; r.mPreserveWindow = false; // Normally the ViewRoot sets up callbacks with the Activity // in addView->ViewRootImpl#setView. If we are instead reusing // the decor view we have to notify the view root that the // callbacks may have changed. ViewRootImpl impl = decor.getViewRootImpl(); if (impl != null) { impl.notifyChildRebuilt(); } } //如果DecorView尚未添加到WindowManager中,将其添加进去,否则更新Window属性 //Activity启动过程中,第一次resume时,DecorView还尚未添加至WindowManager,所以会走进上面这个case //由于我们之前将DecorView的Visibility设置成了INVISIBLE,所以此时界面还是不可见 if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true; wm.addView(decor, l); } else { // The activity will get a callback for this {@link LayoutParams} change // earlier. However, at that time the decor will not be set (this is set // in this method), so no action will be taken. This call ensures the // callback occurs with the decor set. a.onWindowAttributesChanged(l); } }
// If the window has already been added, but during resume // we started another activity, then don't yet make the // window visible. } elseif (!willBeVisible) { r.hideForNow = true; }
// Get rid of anything left hanging around. //清除遗留的东西 cleanUpPendingRemoveWindows(r, false/* force */);
// The window is now visible if it has been added, we are not // simply finishing, and we are not starting another activity. if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { //分发Configuration更新事件 if (r.newConfig != null) { performConfigurationChangedForActivity(r, r.newConfig); r.newConfig = null; } //当DecorView add进WindowManager后,ViewRootImpl被创建 ViewRootImpl impl = r.window.getDecorView().getViewRootImpl(); WindowManager.LayoutParams l = impl != null ? impl.mWindowAttributes : r.window.getAttributes();
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest, String reason){ final ActivityClientRecord r = mActivities.get(token);
mCalled = false; // mResumed is set by the instrumentation //执行Activity.onResume回调 mInstrumentation.callActivityOnResume(this); if (!mCalled) { //必须执行super.onResume方法 thrownew SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onResume()"); }
// invisible activities must be finished before onResume() completes ... //异常检查
// Now really resume, and install the current status bar and menu. mCalled = false;
//执行onPostResume回调 onPostResume(); if (!mCalled) { //必须要执行super.onPostResume thrownew SuperNotCalledException( "Activity " + mComponent.toShortString() + " did not call through to super.onPostResume()"); } //回调ActivityLifecycleCallbacks.onActivityPostResumed dispatchActivityPostResumed(); }
staticvoidactivityResumedLocked(IBinder token, boolean handleSplashScreenExit){ final ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r == null) { // If an app reports resumed after a long delay, the record on server side might have // been removed (e.g. destroy timeout), so the token could be null. return; } //SplashScreen r.setCustomizeSplashScreenExitAnimation(handleSplashScreenExit); //重置savedState Bundle r.setSavedState(null/* savedState */);
voidstartProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop, String hostingType){ try { ... // Post message to start process to avoid possible deadlock of calling into AMS with the // ATMS lock held. final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess, mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead, isTop, hostingType, activity.intent.getComponent()); mH.sendMessage(m); } finally { ... } }
@Override publicvoidstartProcess(String processName, ApplicationInfo info, boolean knownToBeDead, boolean isTop, String hostingType, ComponentName hostingName){ try { ... synchronized (ActivityManagerService.this) { // If the process is known as top app, set a hint so when the process is // started, the top priority can be applied immediately to avoid cpu being // preempted by other processes before attaching the process of top app. startProcessLocked(processName, info, knownToBeDead, 0/* intentFlags */, new HostingRecord(hostingType, hostingName, isTop), ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false/* allowWhileBooting */, false/* isolated */, true/* keepIfLarge */); } } finally { ... } }
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler){ long startTime = SystemClock.uptimeMillis(); ProcessRecord app; if (!isolated) { //先通过进程名和uid查找相应App的ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
//如果是由后台进程发起的 startProcess //判断启动进程是否为 bad process,如果是,直接启动失败返回 //这里 bad process 的定义为:短时间内连续崩溃两次以上的进程 if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { // If we are in the background, then check to see if this process // is bad. If so, we will just silently fail. if (mService.mAppErrors.isBadProcessLocked(info)) { returnnull; } } else { // When the user is explicitly starting a process, then clear its // crash count so that we won't make it bad until they see at // least one crash dialog again, and make the process good again // if it had been bad. //如果是用户显式的要求启动进程,则会清空启动进程的崩溃次数,将启动进程从 bad process 列表中移除 mService.mAppErrors.resetProcessCrashTimeLocked(info); if (mService.mAppErrors.isBadProcessLocked(info)) { EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, UserHandle.getUserId(info.uid), info.uid, info.processName); mService.mAppErrors.clearBadProcessLocked(info); if (app != null) { app.bad = false; } } } } else { // If this is an isolated process, it can't re-use an existing process. app = null; }
// We don't have to do anything more if: // (1) There is an existing application record; and // (2) The caller doesn't think it is dead, OR there is no thread // object attached to it so we know it couldn't have crashed; and // (3) There is a pid assigned to it, so it is either starting or // already running. ProcessRecord precedence = null; //如果已经存在了对应App的ProcessRecord,并且分配了pid if (app != null && app.pid > 0) { //如果进程没有死亡或者进程还未绑定binder线程,说明进程是正常运行状态或正在启动中 if ((!knownToBeDead && !app.killed) || app.thread == null) { // We already have the app running, or are waiting for it to // come up (we have a pid but not yet its thread), so keep it. // If this is a new package in the process, add the package to the list //将要启动的包信息记录在ProcessRecord中(Android多个App可以运行在同一个进程中) app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); return app; }
// An application record is attached to a previous process, // clean it up now. //App绑定在之前的一个进程上了,杀死并清理这个进程 ProcessList.killProcessGroup(app.uid, app.pid);
Slog.wtf(TAG_PROCESSES, app.toString() + " is attached to a previous process"); // We are not going to re-use the ProcessRecord, as we haven't dealt with the cleanup // routine of it yet, but we'd set it as the precedence of the new process. precedence = app; app = null; }
//没有找到对应的ProcessRecord if (app == null) { //新创建一个ProcessRecord对象 app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord); if (app == null) { Slog.w(TAG, "Failed making new process record for " + processName + "/" + info.uid + " isolated=" + isolated); returnnull; } app.crashHandler = crashHandler; app.isolatedEntryPoint = entryPoint; app.isolatedEntryPointArgs = entryPointArgs; if (precedence != null) { app.mPrecedence = precedence; precedence.mSuccessor = app; } } else { //存在对应的ProcessRecord,但进程尚未启动或已被清理 // If this is a new package in the process, add the package to the list //将要启动的包信息记录在ProcessRecord中 app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats); }
// If the system is not ready yet, then hold off on starting this // process until it is. //如果系统尚未准备好(开机中或system_server进程崩溃重启中),将其先添加到等待队列中 if (!mService.mProcessesReady && !mService.isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mService.mProcessesOnHold.contains(app)) { mService.mProcessesOnHold.add(app); } return app; }
// Remove any gids needed if the process has been denied permissions. // NOTE: eventually we should probably have the package manager pre-compute // this for us? //从刚刚过去的App申请权限中剔除进程所被拒绝的权限 if (app.processInfo != null && app.processInfo.deniedPermissions != null) { for (int i = app.processInfo.deniedPermissions.size() - 1; i >= 0; i--) { int[] denyGids = mService.mPackageManagerInt.getPermissionGids( app.processInfo.deniedPermissions.valueAt(i), app.userId); if (denyGids != null) { for (int gid : denyGids) { permGids = ArrayUtils.removeInt(permGids, gid); } } } }
//计算得出进程所应拥有的所有权限 gids = computeGidsForProcess(mountExternal, uid, permGids); } //设置挂载模式 app.mountMode = mountExternal; //工厂测试进程 if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) { uid = 0; } //进程启动参数(传递到Zygoto) int runtimeFlags = 0; //如果manifest中设置了android:debuggable if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP; runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE; // Also turn on CheckJNI for debuggable apps. It's quite // awkward to turn on otherwise. runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
// Check if the developer does not want ART verification if (android.provider.Settings.Global.getInt(mService.mContext.getContentResolver(), android.provider.Settings.Global.ART_VERIFIER_VERIFY_DEBUGGABLE, 1) == 0) { runtimeFlags |= Zygote.DISABLE_VERIFIER; Slog.w(TAG_PROCESSES, app + ": ART verification disabled"); } } ... //设置各种高进程启动参数
String invokeWith = null; //如果manifest中设置了android:debuggable //使用logwrapper工具捕获stdout信息 if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) { // Debuggable apps may include a wrapper script with their library directory. String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh"; StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { if (new File(wrapperFileName).exists()) { invokeWith = "/system/bin/logwrapper " + wrapperFileName; } } finally { StrictMode.setThreadPolicy(oldPolicy); } }
final String seInfo = app.info.seInfo + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser); // Start the process. It will either succeed and return a result containing // the PID of the new process, or else throw a RuntimeException. //重要:设置进程启动入口 final String entryPoint = "android.app.ActivityThread";
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime){ try { finalboolean isTopApp = hostingRecord.isTopApp(); if (isTopApp) { // Use has-foreground-activities as a temporary hint so the current scheduling // group won't be lost when the process is attaching. The actual state will be // refreshed when computing oom-adj. app.setHasForegroundActivities(true); }
// Get all packages belongs to the same shared uid. sharedPackages is empty array // if it doesn't have shared uid. final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked(); final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage( app.info.packageName, app.userId); final String[] targetPackagesList = sharedPackages.length == 0 ? new String[]{app.info.packageName} : sharedPackages;
pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid); if (pkgDataInfoMap == null) { // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a // tmp free pass. bindMountAppsData = false; }
// Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so // it won't be mounted twice. final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps); for (String pkg : targetPackagesList) { whitelistedApps.remove(pkg); }
whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt, whitelistedApps.toArray(new String[0]), uid); if (whitelistedAppDataInfoMap == null) { // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a // tmp free pass. bindMountAppsData = false; }
int userId = UserHandle.getUserId(uid); StorageManagerInternal storageManagerInternal = LocalServices.getService( StorageManagerInternal.class); if (needsStorageDataIsolation(storageManagerInternal, app)) { bindMountAppStorageDirs = true; if (pkgDataInfoMap == null || !storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(), app.processName)) { // Cannot prepare Android/app and Android/obb directory or inode == 0, // so we won't mount it in zygote, but resume the mount after unlocking device. app.bindMountPending = true; bindMountAppStorageDirs = false; } }
// If it's an isolated process, it should not even mount its own app data directories, // since it has no access to them anyway. if (app.isolated) { pkgDataInfoMap = null; whitelistedAppDataInfoMap = null; }
final Process.ProcessStartResult startResult; if (hostingRecord.usesWebviewZygote()) { startResult = startWebView(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } elseif (hostingRecord.usesAppZygote()) { final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
// --setgroups is a comma-separated list if (gids != null && gids.length > 0) { final StringBuilder sb = new StringBuilder(); sb.append("--setgroups=");
finalint sz = gids.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(gids[i]); }
argsForZygote.add(sb.toString()); }
if (niceName != null) { argsForZygote.add("--nice-name=" + niceName); }
if (seInfo != null) { argsForZygote.add("--seinfo=" + seInfo); }
if (instructionSet != null) { argsForZygote.add("--instruction-set=" + instructionSet); }
if (appDataDir != null) { argsForZygote.add("--app-data-dir=" + appDataDir); }
if (invokeWith != null) { argsForZygote.add("--invoke-with"); argsForZygote.add(invokeWith); }
if (startChildZygote) { argsForZygote.add("--start-child-zygote"); }
if (packageName != null) { argsForZygote.add("--package-name=" + packageName); }
if (isTopApp) { argsForZygote.add(Zygote.START_AS_TOP_APP_ARG); } if (pkgDataInfoMap != null && pkgDataInfoMap.size() > 0) { StringBuilder sb = new StringBuilder(); sb.append(Zygote.PKG_DATA_INFO_MAP); sb.append("="); boolean started = false; for (Map.Entry<String, Pair<String, Long>> entry : pkgDataInfoMap.entrySet()) { if (started) { sb.append(','); } started = true; sb.append(entry.getKey()); sb.append(','); sb.append(entry.getValue().first); sb.append(','); sb.append(entry.getValue().second); } argsForZygote.add(sb.toString()); } if (allowlistedDataInfoList != null && allowlistedDataInfoList.size() > 0) { StringBuilder sb = new StringBuilder(); sb.append(Zygote.ALLOWLISTED_DATA_INFO_MAP); sb.append("="); boolean started = false; for (Map.Entry<String, Pair<String, Long>> entry : allowlistedDataInfoList.entrySet()) { if (started) { sb.append(','); } started = true; sb.append(entry.getKey()); sb.append(','); sb.append(entry.getValue().first); sb.append(','); sb.append(entry.getValue().second); } argsForZygote.add(sb.toString()); }
if (bindMountAppStorageDirs) { argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS); }
if (bindMountAppsData) { argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS); }
if (disabledCompatChanges != null && disabledCompatChanges.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--disabled-compat-changes=");
int sz = disabledCompatChanges.length; for (int i = 0; i < sz; i++) { if (i != 0) { sb.append(','); } sb.append(disabledCompatChanges[i]); }
argsForZygote.add(sb.toString()); }
argsForZygote.add(processClass);
if (extraArgs != null) { Collections.addAll(argsForZygote, extraArgs); }
synchronized(mLock) { // The USAP pool can not be used if the application will not use the systems graphics // driver. If that driver is requested use the Zygote application start path. return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), zygotePolicyFlags, argsForZygote); } }
/* * See com.android.internal.os.ZygoteArguments.parseArgs() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ //构建出符合zygote解析规则的参数(argc + argv) String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";
//USAP机制 if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) { try { return attemptUsapSendArgsAndGetResult(zygoteState, msgStr); } catch (IOException ex) { // If there was an IOException using the USAP pool we will log the error and // attempt to start the process through the Zygote. Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - " + ex.getMessage()); } }
// Always read the entire result from the input stream to avoid leaving // bytes in the stream for future process starts to accidentally stumble // upon. Process.ProcessStartResult result = new Process.ProcessStartResult(); result.pid = zygoteInputStream.readInt(); result.usingWrapper = zygoteInputStream.readBoolean();
if (result.pid < 0) { thrownew ZygoteStartFailedEx("fork() failed"); }
// CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. //资源关闭检测器 CloseGuard.setEnabled(false);
//初始化用户环境 Environment.initForCurrentUser();
// Make sure TrustedCertificateStore looks in the right place for CA certificates //设置CA证书搜索位置 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir);
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line. // It will be in the format "seq=114" //查找startSeq参数 long startSeq = 0; if (args != null) { for (int i = args.length - 1; i >= 0; --i) { if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) { startSeq = Long.parseLong( args[i].substring(PROC_START_SEQ_IDENT.length())); } } } //创建App进程ActivityThread实例 ActivityThread thread = new ActivityThread(); thread.attach(false, startSeq);
//设置全局Handler if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); }
privatevoidattach(boolean system, long startSeq){ sCurrentActivityThread = this; mConfigurationController = new ConfigurationController(this); mSystemThread = system; if (!system) { //非系统ActivityThread //预设进程名 android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); //处理一些错误异常需要使用ActivityThread,将其传入 RuntimeInit.setApplicationObject(mAppThread.asBinder()); //AMS代理binder对象 final IActivityManager mgr = ActivityManager.getService(); try { //执行AMS.attachApplication方法 mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } // Watch for getting close to heap limit. //每次GC时检测内存,如果内存不足则会尝试释放部分不可见的Activity BinderInternal.addGcWatcher(new Runnable() { @Overridepublicvoidrun(){ if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024) + " total=" + (runtime.totalMemory()/1024) + " used=" + (dalvikUsed/1024)); mSomeActivitiesChanged = false; try { ActivityTaskManager.getService().releaseSomeActivities(mAppThread); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }); } else { //系统ActivityThread ... }
//处理ConfigChanged相关逻辑(屏幕旋转之类) ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> { synchronized (mResourcesManager) { // We need to apply this change to the resources immediately, because upon returning // the view hierarchy will be informed about it. if (mResourcesManager.applyConfigurationToResources(globalConfig, null/* compat */)) { mConfigurationController.updateLocaleListFromAppContext( mInitialApplication.getApplicationContext());
// This actually changed the resources! Tell everyone about it. final Configuration updatedConfig = mConfigurationController.updatePendingConfiguration(globalConfig); if (updatedConfig != null) { sendMessage(H.CONFIGURATION_CHANGED, globalConfig); mPendingConfiguration = updatedConfig; } } } }; ViewRootImpl.addConfigCallback(configChangedCallback); }
privatebooleanattachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq){
// Find the application record that is being attached... either via // the pid if we are running in multiple processes, or just pull the // next app record if we are emulating process with anonymous threads. ProcessRecord app; long startTime = SystemClock.uptimeMillis(); long bindApplicationTimeMillis; if (pid != MY_PID && pid >= 0) { //通过pid查找PidMap中存在的ProcessRecord //对应着handleProcessStartedLocked方法中执行的中的mService.addPidLocked方法 //在进程同步启动模式下,这里应该是必能取到的 synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } //如果此ProcessRecord对不上App的ProcessRecord,则将其清理掉 if (app != null && (app.startUid != callingUid || app.startSeq != startSeq)) { ... // If there is already an app occupying that pid that hasn't been cleaned up cleanUpApplicationRecordLocked(app, false, false, -1, true/*replacingPid*/); removePidLocked(app); app = null; } } else { app = null; }
// It's possible that process called attachApplication before we got a chance to // update the internal state. //在进程异步启动模式下,有可能尚未执行到handleProcessStartedLocked方法 //所以从PidMap中无法取到相应的ProcessRecord //这时候从ProcessList.mPendingStarts这个待启动列表中获取ProcessRecord if (app == null && startSeq > 0) { final ProcessRecord pending = mProcessList.mPendingStarts.get(startSeq); if (pending != null && pending.startUid == callingUid && pending.startSeq == startSeq && mProcessList.handleProcessStartedLocked(pending, pid, pending .isUsingWrapper(), startSeq, true)) { app = pending; } }
// If this application record is still attached to a previous // process, clean it up now. //如果ProcessRecord绑定了其他的ApplicationThread,则需要清理这个进程 if (app.thread != null) { handleAppDiedLocked(app, true, true); }
// We carefully use the same state that PackageManager uses for // filtering, since we use this flag to decide if we need to install // providers when user is unlocked later app.unlocked = StorageManager.isUserKeyUnlocked(app.userId);
// We deprecated Build.SERIAL and it is not accessible to // Instant Apps and target APIs higher than O MR1. Since access to the serial // is now behind a permission we push down the value. //序列号(Android 8.0后不可再通过Build.SERIAL获取序列号) final String buildSerial = (!appInfo.isInstantApp() && appInfo.targetSdkVersion < Build.VERSION_CODES.P) ? sTheRealBuildSerial : Build.UNKNOWN;
//自动化测试 final ActiveInstrumentation instr2 = app.getActiveInstrumentation(); if (mPlatformCompat != null) { mPlatformCompat.resetReporting(app.info); } final ProviderInfoList providerList = ProviderInfoList.fromList(providers); //调用ApplicationThread.bindApplication方法 if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } elseif (instr2 != null) { thread.bindApplication(processName, appInfo, providerList, instr2.mClass, profilerInfo, instr2.mArguments, instr2.mWatcher, instr2.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, autofillOptions, contentCaptureOptions, app.mDisabledCompatChanges); } else { thread.bindApplication(processName, appInfo, providerList, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, autofillOptions, contentCaptureOptions, app.mDisabledCompatChanges); } ...
// Make app active after binding application or client may be running requests (e.g // starting activities) before it is ready. //ProcessRecord保存ApplicationThread代理对象 app.makeActive(thread, mProcessStats); //更新进程使用情况 mProcessList.updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { //出现错误,杀死进程 app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); app.kill("error during bind", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true); handleAppDiedLocked(app, false, true); returnfalse; }
// Remove this record from the list of starting applications. //从persistent启动列表中移除此ProcessRecord //persistent是manifest中application标签下的一个属性 //设置了此属性代表此App会跟随系统启动而启动 mPersistentStartingProcesses.remove(app);
// See if the top visible activity is waiting to run in this process... //检查是否有Activity等待启动 if (normalMode) { try { didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); } catch (Exception e) { badApp = true; } }
// Find any services that should be running in this process... //检查是否有Services等待启动 if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { badApp = true; } }
// Check if a next-broadcast receiver is in this process... //检查是否有广播接收器需要启动 if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' badApp = true; } }
... //备份相关
//以上几步发生异常,杀死App进程 if (badApp) { app.kill("error during init", ApplicationExitInfo.REASON_INITIALIZATION_FAILURE, true); handleAppDiedLocked(app, false, true); returnfalse; }
if (!didSomething) { //更新进程OOM等级 updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN); }
privatevoidhandleBindApplication(AppBindData data){ // Register the UI Thread as a sensitive thread to the runtime. //将UI线程注册成JIT敏感线程 VMRuntime.registerSensitiveThread(); ...
mProfiler = new Profiler(); ... //性能分析相关
// send up app name; do this *before* waiting for debugger //设置进程名 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, data.appInfo.packageName, UserHandle.myUserId()); VMRuntime.setProcessPackageName(data.appInfo.packageName);
// Pass data directory path to ART. This is used for caching information and // should be set before any application code is loaded. //设置进程数据目录 VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);
//性能分析相关 if (mProfiler.profileFd != null) { mProfiler.startProfiling(); }
// If the app is Honeycomb MR1 or earlier, switch its AsyncTask // implementation to use the pool executor. Normally, we use the // serialized executor as the default. This has to happen in the // main thread so the main looper is set right. //当App的targetSdkVersion小于等于 3.1 (12) 时,AsyncTask使用线程池实现 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }
// Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier. //当App的targetSdkVersion大于等于 10 (29) 时,针对Android SDK提供的容器(SparseArray等) //如果index越界,会主动抛ArrayIndexOutOfBoundsException异常 //(之前数组越界的行为未被定义) UtilConfig.setThrowExceptionForUpperArrayOutOfBounds( data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);
// Prior to P, internal calls to decode Bitmaps used BitmapFactory, // which may scale up to account for density. In P, we switched to // ImageDecoder, which skips the upscale to save memory. ImageDecoder // needs to still scale up in older apps, in case they rely on the // size of the Bitmap without considering its density. ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;
/* * Before spawning a new process, reset the time zone to be the system time zone. * This needs to be done because the system time zone could have changed after the * the spawning of this process. Without doing this this process would have the incorrect * system time zone. */ //设置时区 TimeZone.setDefault(null);
/* * Set the LocaleList. This may change once we create the App Context. */ LocaleList.setDefault(data.config.getLocales());
//更新Configuration synchronized (mResourcesManager) { /* * Update the system configuration since its preloaded and might not * reflect configuration changes. The configuration object passed * in AppBindData can be safely assumed to be up to date */ mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi;
// This calls mResourcesManager so keep it within the synchronized block. applyCompatConfiguration(mCurDefaultDisplayDpi); }
//性能分析器代理JVM(JVMTI) if (agent != null) { handleAttachAgent(agent, data.info); }
/** * Switch this process to density compatibility mode if needed. */ //在manifest,supports-screens标签中设置了android:anyDensity //详见:https://developer.android.com/guide/topics/manifest/supports-screens-element#any if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { //指示App包含用于适应任何屏幕密度的资源 mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } //设置默认密度 updateDefaultDensity();
/* 设置 12/24 小时时间制 */ final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24); Boolean is24Hr = null; if (use24HourSetting != null) { is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE; } // null : use locale default for 12/24 hour formatting, // false : use 12 hour format, // true : use 24 hour format. DateFormat.set24HourTimePref(is24Hr);
//debug模式 if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) { // XXX should have option to change the port. Debug.changeDebugPort(8100); if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) { Slog.w(TAG, "Application " + data.info.getPackageName() + " is waiting for the debugger on port 8100...");
/** * Initialize the default http proxy in this process for the reasons we set the time zone. */ //设置默认HTTP代理 final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { // In pre-boot mode (doing initial launch to collect password), not // all system is up. This includes the connectivity service, so don't // crash if we can't get it. final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { Proxy.setHttpProxySystemProperty(service.getProxyForNetwork(null)); } catch (RemoteException e) { Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); throw e.rethrowFromSystemServer(); } }
// Instrumentation info affects the class loader, so load it before // setting up the app context. //准备自动化测试信息 final InstrumentationInfo ii; if (data.instrumentationName != null) { try { ii = new ApplicationPackageManager( null, getPackageManager(), getPermissionManager()) .getInstrumentationInfo(data.instrumentationName, 0); } catch (PackageManager.NameNotFoundException e) { thrownew RuntimeException( "Unable to find instrumentation info for: " + data.instrumentationName); }
// Install the Network Security Config Provider. This must happen before the application // code is loaded to prevent issues with instances of TLS objects being created before // the provider is installed. //网络安全设置 NetworkSecurityConfigProvider.install(appContext);
// Continue loading instrumentation. if (ii != null) { //如果设置了自动化测试,实例化指定的自动化测试类 ApplicationInfo instrApp; try { instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0, UserHandle.myUserId()); } catch (RemoteException e) { instrApp = null; } if (instrApp == null) { instrApp = new ApplicationInfo(); } ii.copyTo(instrApp); instrApp.initForUser(UserHandle.myUserId()); final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false);
// The test context's op package name == the target app's op package name, because // the app ops manager checks the op package name against the real calling UID, // which is what the target package name is associated with. final ContextImpl instrContext = ContextImpl.createAppContext(this, pi, appContext.getOpPackageName());
final ComponentName component = new ComponentName(ii.packageName, ii.name); mInstrumentation.init(this, instrContext, appContext, component, data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
if (mProfiler.profileFile != null && !ii.handleProfiling && mProfiler.profileFd == null) { mProfiler.handlingProfiling = true; final File file = new File(mProfiler.profileFile); file.getParentFile().mkdirs(); Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); } } else { //直接实例化Instrumentation mInstrumentation = new Instrumentation(); mInstrumentation.basicInit(this); }
//调整应用可用内存上限 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); }
// Allow disk access during application and provider setup. This could // block processing ordered broadcasts, but later processing would // probably end up doing the same disk access. Application app; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy(); try { // 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);
// Propagate autofill compat state //设置自动填充功能 app.setAutofillOptions(data.autofillOptions);
// don't bring up providers in restricted mode; they may depend on the // app's custom Application class //在非受限模式下启动ContentProvider if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } }
// Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. //执行onCreate方法(默认Instrumentation实现为空方法) try { mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { ... } //执行Application的onCreate方法 try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { ... } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } }
// Preload fonts resources //预加载字体资源 FontsContract.setApplicationContextForResources(appContext); if (!Process.isIsolated()) { try { final ApplicationInfo info = getPackageManager().getApplicationInfo( data.appInfo.packageName, PackageManager.GET_META_DATA /*flags*/, UserHandle.myUserId()); if (info.metaData != null) { finalint preloadedFontsResource = info.metaData.getInt( ApplicationInfo.METADATA_PRELOADED_FONTS, 0); if (preloadedFontsResource != 0) { data.info.getResources().preloadFonts(preloadedFontsResource); } } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
try { //初始化ContextClassLoader final java.lang.ClassLoader cl = getClassLoader(); if (!mPackageName.equals("android")) { initializeJavaContextClassLoader(); }
// Rewrite the R 'constants' for all library apks. //Android共享库资源ID动态映射 SparseArray<String> packageIdentifiers = getAssets().getAssignedPackageIdentifiers( false, false); for (int i = 0, n = packageIdentifiers.size(); i < n; i++) { finalint id = packageIdentifiers.keyAt(i); if (id == 0x01 || id == 0x7f) { continue; }
这个版本是从原x264镜像仓库的stable分支切出的,版本为0.164。想知道x264版本的话,可以运行其目录下的version.sh脚本,它会输出三串数字,前面的164是在x264.h中定义的X264_BUILD,第二个3095+4表示master分支的提交数 + master分支到HEAD的提交数,最后的一串数字表示当前分支最新的commit id
echo "Select arch:" select arch in "armeabi-v7a" "arm64-v8a" "x86" "x86-64" do echo "Select build static or shared libs:" select type in "static" "shared" do if [[ $type == "static" ]]; then BUILD_SHARED_LIBS=OFF elif [[ $type == "shared" ]]; then BUILD_SHARED_LIBS=ON else BUILD_SHARED_LIBS=OFF fi break done build $arch break done
其中的message(FATAL_ERROR "FFMPEG: test check build log:\n${TRY_OUT}")原本是被注释了的,我强烈建议各位将其打开,这样如果哪里有误,一开始就可以报错并附带详细信息,免得到时候编到一半才报错,浪费时间
到这里,我本以为万事大吉了,于是开始编译,这里我使用了BUILD_SHARED_LIBS=ON选项编译动态库,armeabi-v7a顺利编译通过,但当arm64-v8a编译到一半时突然报错,提示libz.so, needed by ../../lib/arm64-v8a/libopencv_core.so, not found (try using -rpath or -rpath-link)
Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml’s <instrumentation> tag.
intexecute(){ try { // Refuse possible leaked file descriptors //校验Intent,不允许其携带fd if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) { thrownew IllegalArgumentException("File descriptors passed in Intent"); }
final LaunchingState launchingState; synchronized (mService.mGlobalLock) { //通过Token获取调用方ActivityRecord final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo); //记录启动状态 launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching( mRequest.intent, caller); }
// If the caller hasn't already resolved the activity, we're willing // to do so here. If the caller is already holding the WM lock here, // and we need to check dynamic Uri permissions, then we're forced // to assume those permissions are denied to avoid deadlocking. //通过Intent解析Activity信息 if (mRequest.activityInfo == null) { mRequest.resolveActivity(mSupervisor); }
int res; synchronized (mService.mGlobalLock) { ... //处理Configuration
// Notify ActivityMetricsLogger that the activity has launched. // ActivityMetricsLogger will then wait for the windows to be drawn and populate // WaitResult. //记录启动状态 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res, mLastStartActivityRecord); //返回启动结果 return getExternalResult(mRequest.waitResult == null ? res : waitForResult(res, mLastStartActivityRecord)); } } finally { //清理回收工作 onExecutionComplete(); } }
/** * Executing activity start request and starts the journey of starting an activity. Here * begins with performing several preliminary checks. The normally activity launch flow will * go through {@link #startActivityUnchecked} to {@link #startActivityInner}. */ privateintexecuteRequest(Request request){ if (TextUtils.isEmpty(request.reason)) { thrownew IllegalArgumentException("Need to specify a reason."); } mLastStartReason = request.reason; mLastStartActivityTimeMs = System.currentTimeMillis(); mLastStartActivityRecord = null;
int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null;
//找不到可以处理此Intent的组件 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { // We couldn't find a class that can handle the given Intent. // That's the end of that! err = ActivityManager.START_INTENT_NOT_RESOLVED; }
//Intent中解析不出相应的Activity信息 if (err == ActivityManager.START_SUCCESS && aInfo == null) { // We couldn't find the specific class specified in the Intent. // Also the end of the line. err = ActivityManager.START_CLASS_NOT_FOUND; }
// Merge the two options bundles, while realCallerOptions takes precedence. //过渡动画相关 ActivityOptions checkedOptions = options != null ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null; if (request.allowPendingRemoteAnimationRegistryLookup) { checkedOptions = mService.getActivityStartController() .getPendingRemoteAnimationRegistry() .overrideOptionsIfNeeded(callingPackage, checkedOptions); } if (mService.mController != null) { try { // The Intent we give to the watcher has the extra data stripped off, since it // can contain private information. Intent watchIntent = intent.cloneFilter(); //这个方法似乎只打印了一些日志,恒返回true,即abort |= false abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { mService.mController = null; } }
//初始化ActivityStartInterceptor mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage, callingFeatureId); if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid, checkedOptions)) { // activity start was intercepted, e.g. because the target user is currently in quiet // mode (turn off work) or the target application is suspended //拦截并转化成其他的启动模式 intent = mInterceptor.mIntent; rInfo = mInterceptor.mRInfo; aInfo = mInterceptor.mAInfo; resolvedType = mInterceptor.mResolvedType; inTask = mInterceptor.mInTask; callingPid = mInterceptor.mCallingPid; callingUid = mInterceptor.mCallingUid; checkedOptions = mInterceptor.mActivityOptions;
// The interception target shouldn't get any permission grants // intended for the original destination intentGrants = null; }
if (abort) { //回调给调用方Activity结果 if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED, null/* data */, null/* dataGrants */); } // We pretend to the caller that it was really started, but they will just get a // cancel result. ActivityOptions.abort(checkedOptions); return START_ABORTED; }
// If permissions need a review before any of the app components can run, we // launch the review activity and pass a pending intent to start the activity // we are to launching now after the review is completed. if (aInfo != null) { //如果启动的Activity没有相应权限,则需要用户手动确认允许权限后,再进行启动工作 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired( aInfo.packageName, userId)) { //将原来的Intent包装在新的Intent中,用这个确认权限的新Intent继续后面的启动工作 final IIntentSender target = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingFeatureId, callingUid, userId, null, null, 0, new Intent[]{intent}, new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
int flags = intent.getFlags(); flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
/* * Prevent reuse of review activity: Each app needs their own review activity. By * default activities launched with NEW_TASK or NEW_DOCUMENT try to reuse activities * with the same launch parameters (extras are ignored). Hence to avoid possible * reuse force a new activity via the MULTIPLE_TASK flag. * * Activities that are not launched with NEW_TASK or NEW_DOCUMENT are not re-used, * hence no need to add the flag in this case. */ if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) { flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK; } newIntent.setFlags(flags);
newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); if (resultRecord != null) { newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true); } intent = newIntent;
// The permissions review target shouldn't get any permission // grants intended for the original destination intentGrants = null;
// If we have an ephemeral app, abort the process of launching the resolved intent. // Instead, launch the ephemeral installer. Once the installer is finished, it // starts either the intent we resolved here [on install error] or the ephemeral // app [on install success]. if (rInfo != null && rInfo.auxiliaryInfo != null) { ... //Instant App相关 }
//创建启动Activity的ActivityRecord final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, callingFeatureId, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); mLastStartActivityRecord = r;
if (r.appTimeTracker == null && sourceRecord != null) { // If the caller didn't specify an explicit time tracker, we want to continue // tracking under any it has. r.appTimeTracker = sourceRecord.appTimeTracker; }
//获取顶层焦点的Acticity栈 final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
// If we are starting an activity that is not from the same uid as the currently resumed // one, check whether app switches are allowed. //当此时栈顶Activity UID != 调用方 UID的时候(比如悬浮窗) if (voiceSession == null && stack != null && (stack.getResumedActivity() == null || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) { //检查是否可以直接切换应用 // 1. 设置的 mAppSwitchesAllowedTime < 当前系统时间(stopAppSwitches) // 2. 调用方在最近任务中 // 3. 调用方具有 STOP_APP_SWITCHES 权限 // ... if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { //加入到延时启动列表中 if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) { mController.addPendingActivityLaunch(new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp, intentGrants)); } ActivityOptions.abort(checkedOptions); return ActivityManager.START_SWITCHES_CANCELED; } }
/** * Start an activity while most of preliminary checks has been done and caller has been * confirmed that holds necessary permissions to do so. * Here also ensures that the starting activity is removed if the start wasn't successful. */ privateintstartActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants){ int result = START_CANCELED; final ActivityStack startedActivityStack; try { //暂停布局工作,避免重复刷新 mService.deferWindowLayout(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); //接着把启动Activity工作交给这个方法 result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); //进行一些更新Configuration,清理栈等收尾工作 startedActivityStack = handleStartResult(r, result); //恢复布局工作 mService.continueWindowLayout(); }
/** * Start an activity and determine if the activity should be adding to the top of an existing * task or delivered new intent to an existing activity. Also manipulating the activity task * onto requested or valid stack/display. * * Note: This method should only be called from {@link #startActivityUnchecked}. */
// TODO(b/152429287): Make it easier to exercise code paths through startActivityInner @VisibleForTesting intstartActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants){ //设置初始化参数 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor, restrictedBgActivity); //计算处理Activity启动模式 computeLaunchingTaskFlags(); //计算调用方Activity任务栈 computeSourceStack();
//查找是否有可复用的Task final Task reusedTask = getReusableTask();
// If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid) && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) { mFrozeTaskList = true; mSupervisor.mRecentTasks.setFreezeTaskListReordering(); }
// Compute if there is an existing task that should be used for. //计算是否存在可使用的现有Task final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask(); finalboolean newTask = targetTask == null; mTargetTask = targetTask;
// Check if starting activity on given task or on a new task is allowed. //检查是否允许在targetTask上或者新建Task启动 int startResult = isAllowedToStart(r, newTask, targetTask); if (startResult != START_SUCCESS) { return startResult; }
//获得栈顶未finish的ActivityRecord final ActivityRecord targetTaskTop = newTask ? null : targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null) { // Recycle the target task for this launch. //回收,准备复用这个Task startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } else { mAddingToTask = true; }
// If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. //处理singleTop启动模式 final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack(); if (topStack != null) { startResult = deliverToCurrentTopIfNeeded(topStack, intentGrants); if (startResult != START_SUCCESS) { return startResult; } }
if (!mAvoidMoveToFront && mDoResume) { mTargetStack.getStack().moveToFront("reuseOrNewTask", targetTask); if (mOptions != null) { if (mOptions.getTaskAlwaysOnTop()) { mTargetStack.setAlwaysOnTop(true); } } if (!mTargetStack.isTopStackInDisplayArea() && mService.mInternal.isDreaming()) { // Launching underneath dream activity (fullscreen, always-on-top). Run the launch- // -behind transition so the Activity gets created and starts in visible state. mLaunchTaskBehind = true; r.mLaunchTaskBehind = true; } }
//将Task移到ActivityStack容器顶部 mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(), newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); //启动的Activity不可获得焦点,无法恢复它 if (!mTargetStack.isTopActivityFocusable() || (topTaskActivity != null && topTaskActivity.isTaskOverlay() && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. // Passing {@code null} as the start parameter ensures all activities are made // visible. mTargetStack.ensureActivitiesVisible(null/* starting */, 0/* configChanges */, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isTopActivityFocusable() && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityInner"); } //重点:恢复栈顶Activities mRootWindowContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions); } } mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack);
// Update the recent tasks list immediately when the activity starts //当Activity启动后立刻更新最近任务列表 mSupervisor.mRecentTasks.add(mStartActivity.getTask()); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack);
if (!mStackSupervisor.readyToResume()) { returnfalse; }
boolean result = false; //目标栈在栈顶显示区域 if (targetStack != null && (targetStack.isTopStackInDisplayArea() || getTopDisplayFocusedStack() == targetStack)) { //使用目标栈进行恢复 result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); }
//可能存在多显示设备(投屏等) for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { boolean resumedOnDisplay = false; final DisplayContent display = getChildAt(displayNdx); for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) { final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx); for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { final ActivityStack stack = taskDisplayArea.getStackAt(sNdx); final ActivityRecord topRunningActivity = stack.topRunningActivity(); if (!stack.isFocusableAndVisible() || topRunningActivity == null) { continue; } if (stack == targetStack) { //如果进入到这里,代表着targetStack在上面已经恢复过了,此时只需要记录结果即可 resumedOnDisplay |= result; continue; } if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) { //执行切换效果 stack.executeAppTransition(targetOptions); } else { //使顶部显示的Activity执行Resume、Pause或Start生命周期 resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target); } } } if (!resumedOnDisplay) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home // activity is started and resumed, and no recursion occurs. //当没有任何有效的Activity的时候(设备刚启动或Launcher崩溃),可能没有任何东西可被恢复 //这时候使用DisplayContent中的焦点栈进行恢复 //如果连存在焦点的栈都没有,则恢复Launcher的Activity final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } elseif (targetStack == null) { result |= resumeHomeActivity(null/* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); } } }
booleanresumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options){ if (mInResumeTopActivity) { // Don't even start recursing. //防止递归 returnfalse; }
boolean result = false; try { // Protect against recursion. //防止递归 mInResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options);
// When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here // to ensure any necessary pause logic occurs. In the case where the Activity will be // shown regardless of the lock screen, the call to // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. final ActivityRecord next = topRunningActivity(true/* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { //准备休眠 checkReadyForSleep(); } } finally { mInResumeTopActivity = false; }
privatebooleanresumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options){ if (!mAtmService.isBooting() && !mAtmService.isBooted()) { // Not ready yet! //ATMS服务尚未准备好 returnfalse; }
// Find the next top-most activity to resume in this stack that is not finishing and is // focusable. If it is not focusable, we will fall into the case below to resume the // top activity in the next focusable task. //在之前我们已经把要启动的ActivityRecord加到了栈顶 ActivityRecord next = topRunningActivity(true/* focusableOnly */);
finalboolean hasRunningActivity = next != null;
...
if (!hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); }
next.delayedResume = false; final TaskDisplayArea taskDisplayArea = getDisplayArea();
// If the top activity is the resumed one, nothing to do. //如果需要Resume的已在顶部且状态为Resume,不需要做任何事 //启动Activity不会碰到这种case if (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { ... returnfalse; }
if (!next.canResumeByCompat()) { returnfalse; }
// If we are currently pausing an activity, then don't do anything until that is done. //如果有正在Pause的Activity,在它Pause完成前不要做任何事 finalboolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete(); if (!allPausedComplete) { returnfalse; }
...
// Make sure that the user who owns this activity is started. If not, // we will just leave it as is because someone should be bringing // another user's activities to the top of the stack. //确保拥有此Activity的用户已启动 if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) { returnfalse; }
// The activity may be waiting for stop, but that is no longer // appropriate for it. mStackSupervisor.mStoppingActivities.remove(next); next.setSleeping(false);
//这里似乎重复检查了,我去查看了一下master分支的代码,已经没有这一段了 if (!mRootWindowContainer.allPausedActivitiesComplete()) { returnfalse; }
//Pause掉其他ActivityStack中的栈顶状态为Resume的Activity boolean pausing = taskDisplayArea.pauseBackStacks(userLeaving, next); //Pause掉当前ActivityStack中的栈顶状态为Resume的Activity if (mResumedActivity != null) { pausing |= startPausingLocked(userLeaving, false/* uiSleeping */, next); } if (pausing) { //有Activity执行了Pause // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.attachedToProcess()) { //将启动的Activity进程信息移至lru列表的头部 //因为很快就会使用它启动Activity next.app.updateProcessInfo(false/* updateServiceConnectionActivities */, true/* activityChange */, false/* updateOomAdj */, false/* addPendingTopUid */); } elseif (!next.isProcessRunning()) { //App进程未启动 // Since the start-process is asynchronous, if we already know the process of next // activity isn't running, we can start the process earlier to save the time to wait // for the current activity to be paused. finalboolean isTop = this == taskDisplayArea.getFocusedStack(); //启动App进程 mAtmService.startProcessAsync(next, false/* knownToBeDead */, isTop, isTop ? "pre-top-activity" : "pre-activity"); } ... //这里会先结束掉启动Activity的流程,等待onPause生命周期走完后 //再重新调用这个方法执行下一步操作,避免Activity生命周期紊乱 returntrue; } elseif (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { // It is possible for the activity to be resumed when we paused back stacks above if the // next activity doesn't have to wait for pause to complete. // So, nothing else to-do except: // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. //不需要等待其他的Activity onPause完成 //执行完切换效果后就没有什么其他需要做的了 executeAppTransition(options); returntrue; }
...
//启动Activity流程不会进入这个case if (prev != null && prev != next && next.nowVisible) { if (prev.finishing) { prev.setVisibility(false); } }
try { final ClientTransaction transaction = ClientTransaction.obtain(next.app.getThread(), next.appToken); // Deliver all pending results. ArrayList<ResultInfo> a = next.results; if (a != null) { finalint N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a); transaction.addCallback(ActivityResultItem.obtain(a)); } }
// From this point on, if something goes wrong there is no way // to recover the activity. try { //更新信息 next.completeResumeLocked(); } catch (Exception e) { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); next.finishIfPossible("resume-exception", true/* oomAdj */); returntrue; } } else { //尚未绑定Process // Whoops, need to restart this activity! if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { next.showStartingWindow(null/* prev */, false/* newTask */, false/* taskSwich */); } } //启动Activity mStackSupervisor.startSpecificActivity(next, true, true); }
sp<ProcessState> ProcessState::initWithDriver(constchar* driver) { Mutex::Autolock _l(gProcessMutex); if (gProcess != nullptr) { // Allow for initWithDriver to be called repeatedly with the same // driver. //如果已经被初始化过了,并且传入的driver参数和已初始化的驱动名一样,直接返回之前初始化的单例 if (!strcmp(gProcess->getDriverName().c_str(), driver)) { return gProcess; } //否则异常退出 LOG_ALWAYS_FATAL("ProcessState was already initialized."); }
//判断指定的driver是否存在并可读 if (access(driver, R_OK) == -1) { ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver); //回滚默认binder驱动 driver = "/dev/binder"; }
gProcess = new ProcessState(driver); return gProcess; }
int binder_fd = -1; //向binder驱动发送BC_ENTER_LOOPER事务请求,并获得binder设备的文件描述符 IPCThreadState::self()->setupPolling(&binder_fd); LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);
// Flush after setupPolling(), to make sure the binder driver // knows about this thread handling commands. IPCThreadState::self()->flushCommands();
//监听binder文件描述符 int ret = looper->addFd(binder_fd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr/*data*/); LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");
Parcel reply; status_t error; //对于ServiceManager的binder节点来说,是没有ptr的 if (tr.target.ptr) { // We only have a weak reference on the target object, so we must first try to // safely acquire a strong reference before doing anything else with it. //对于其他binder服务端来说,tr.cookie为本地BBinder对象指针 if (reinterpret_cast<RefBase::weakref_type*>( tr.target.ptr)->attemptIncStrong(this)) { error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this); } else { error = UNKNOWN_TRANSACTION; }
// In case this is being transacted on in the same process. if (reply != nullptr) { //设置数据指针偏移为0,这样后续读取数据便会从头开始 reply->setDataPosition(0); if (reply->dataSize() > LOG_REPLIES_OVER_SIZE) { ALOGW("Large reply transaction of %zu bytes, interface descriptor %s, code %d", reply->dataSize(), String8(getInterfaceDescriptor()).c_str(), code); } }
Status ServiceManager::getService(conststd::string& name, sp<IBinder>* outBinder){ *outBinder = tryGetService(name, true); // returns ok regardless of result for legacy reasons return Status::ok(); }
sp<IBinder> ServiceManager::tryGetService(conststd::string& name, bool startIfNotFound){ auto ctx = mAccess->getCallingContext();
//返回值 sp<IBinder> out; Service* service = nullptr; //从map中寻找相应的服务 if (auto it = mNameToService.find(name); it != mNameToService.end()) { service = &(it->second);
if (isIsolated) { returnnullptr; } } //返回值指向对应service的binder对象 out = service->binder; }
if (!mAccess->canFind(ctx, name)) { returnnullptr; }
if (!out && startIfNotFound) { tryStartService(name); }
if (out) { // Setting this guarantee each time we hand out a binder ensures that the client-checking // loop knows about the event even if the client immediately drops the service service->guaranteeClient = true; }
if (context == nullptr) { ALOGW("Not able to get context object on %s.", mDriverName.c_str()); }
// The root object is special since we get it directly from the driver, it is never // written by Parcell::writeStrongBinder. internal::Stability::tryMarkCompilationUnit(context.get());
// If the argument is a JavaBBinder, return the Java object that was used to create it. // Otherwise return a BinderProxy for the IBinder. If a previous call was passed the // same IBinder, and the original BinderProxy is still alive, return the same BinderProxy. jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) { if (val == NULL) returnNULL;
//JavaBBinder返回true,其他类均返回flase if (val->checkSubclass(&gBinderOffsets)) { // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object. jobject object = static_cast<JavaBBinder*>(val.get())->object(); return object; }
BinderProxyNativeData* nativeData = new BinderProxyNativeData(); nativeData->mOrgue = new DeathRecipientList; nativeData->mObject = val;
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get()); if (env->ExceptionCheck()) { // In the exception case, getInstance still took ownership of nativeData. returnNULL; } BinderProxyNativeData* actualNativeData = getBPNativeData(env, object); //如果object是刚刚新建出来的BinderProxy if (actualNativeData == nativeData) { //处理proxy计数 ... } else { delete nativeData; }
//JavaBBinder返回true,其他类均返回flase if (val->checkSubclass(&gBinderOffsets)) { // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object. jobject object = static_cast<JavaBBinder*>(val.get())->object(); return object; } ... }
// ServiceManager is never local returnnew ServiceManagerProxy(obj); }
ServiceManagerProxy
从名字就能听出来,ServiceManagerProxy其实是一个代理类,它其实是IServiceManager.Stub.Proxy的代理,实际上是没有什么必要的,可以发现作者也在注释中标注了This class should be deleted and replaced with IServiceManager.Stub whenever mRemote is no longer used,我们看一下它的构造方法
status_tBpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { // Once a binder has died, it will never come back to life. //判断binder服务是否存活 if (mAlive) { ... status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0;
IPCThreadState* IPCThreadState::self() { //不是初次调用的情况 if (gHaveTLS.load(std::memory_order_acquire)) { restart: //初次调用,生成线程私有变量key后 constpthread_key_t k = gTLS; //先从线程本地储存空间中尝试获取值 IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); if (st) return st; //没有的话就实例化一个 returnnew IPCThreadState; }
//IPCThreadState shutdown后不能再获取 if (gShutdown.load(std::memory_order_relaxed)) { ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n"); returnnullptr; }
//首次获取时gHaveTLS为false,会先走这里 pthread_mutex_lock(&gTLSMutex); if (!gHaveTLS.load(std::memory_order_relaxed)) { //创建一个key,作为存放线程本地变量的key int key_create_value = pthread_key_create(&gTLS, threadDestructor); if (key_create_value != 0) { pthread_mutex_unlock(&gTLSMutex); ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n", strerror(key_create_value)); returnnullptr; } //创建完毕,gHaveTLS置为true gHaveTLS.store(true, std::memory_order_release); } pthread_mutex_unlock(&gTLSMutex); //回到gHaveTLS为true的case goto restart; }
status_tIPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { LOG_ALWAYS_FATAL_IF(data.isForRpc(), "Parcel constructed for RPC, but being used with binder.");
switch (cmd) { case BR_ONEWAY_SPAM_SUSPECT: ... case BR_TRANSACTION_COMPLETE: //当TF_ONE_WAY模式下收到BR_TRANSACTION_COMPLETE直接返回,本次binder通信结束 if (!reply && !acquireResult) goto finish; break; case BR_DEAD_REPLY: ... case BR_FAILED_REPLY: ... case BR_FROZEN_REPLY: ... case BR_ACQUIRE_RESULT: ... case BR_REPLY: { binder_transaction_data tr; err = mIn.read(&tr, sizeof(tr)); ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); //失败直接返回 if (err != NO_ERROR) goto finish;
// Is the read buffer empty? //dataPosition >= dataSize说明上一次读取到的数据已经消费完 constbool needRead = mIn.dataPosition() >= mIn.dataSize();
// We don't want to write anything if we are still reading // from data left in the input buffer and the caller // has requested to read the next data. //需要写的数据大小,这里的doReceive默认为true,如果上一次的数据还没读完,则不会写入任何内容 constsize_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
<TextView android:id="@+id/hello_world" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello from XML layout" />
/* * The asmlinkage stub is aliased to a function named __se_sys_*() which * sign-extends 32-bit ints to longs whenever needed. The actual work is * done within __do_sys_*(). */ #ifndef __SYSCALL_DEFINEx #define __SYSCALL_DEFINEx(x, name, ...) \ __diag_push(); \ __diag_ignore(GCC, 8, "-Wattribute-alias", \ "Type aliasing is used to sanitize syscall arguments");\ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ __attribute__((alias(__stringify(__se_sys##name)))); \ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \ staticinlinelong __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__));\ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \ asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \ { \ long ret = __do_sys##name(__MAP(x,__SC_CAST,__VA_ARGS__));\ __MAP(x,__SC_TEST,__VA_ARGS__); \ __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \ return ret; \ } \ __diag_pop(); \ staticinlinelong __do_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) #endif/* __SYSCALL_DEFINEx */
/** * sys_kill - send a signal to a process * @pid: the PID of the process * @sig: signal to be sent */ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) { structkernel_siginfoinfo; prepare_kill_siginfo(sig, &info); return kill_something_info(sig, &info, pid); }
__visible noinstr voiddo_syscall_64(struct pt_regs *regs, int nr) { add_random_kstack_offset(); nr = syscall_enter_from_user_mode(regs, nr);
instrumentation_begin();
if (!do_syscall_x64(regs, nr) && !do_syscall_x32(regs, nr) && nr != -1) { /* Invalid system call, but still a system call. */ regs->ax = __x64_sys_ni_syscall(regs); }
if (has_signal && get_signal(&ksig)) { handle_signal(&ksig, regs); return; } //如果该进程没有对这个信号设置处理程序,这里会自动重启这个系统调用 /* Did we come from a system call? */ if (syscall_get_nr(current, regs) != -1) { /* Restart the system call - no handlers present */ switch (syscall_get_error(current, regs)) { case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: regs->ax = regs->orig_ax; regs->ip -= 2; break;
/* Set up to return from userspace. If provided, use a stub already in userspace. */ //设置执行完信号处理函数后,要跳回的地址,即sa_restorer unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault); //将原本的pt_regs备份保存至frame.uc.uc_mcontext中 unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault); unsafe_put_sigmask(set, frame, Efault); user_access_end();
if (ksig->ka.sa.sa_flags & SA_SIGINFO) { if (copy_siginfo_to_user(&frame->info, &ksig->info)) return -EFAULT; }
//信号处理函数的第1个参数 regs->di = sig; /* In case the signal handler was declared without prototypes */ regs->ax = 0;