本文基于android13-release源码阅读整理
系统源码地址:init.h - Android Code Search
1.前言
紧接上篇[Android系统Launcher启动流程)]我们继续看看Launcher是如何运行并加载所有桌面应用,继而探究用户在launcher桌面点击App图标启动应用整体流程
2.Launcher运行及生命周期方法
熟悉Android开发的同学在启动模拟器显示桌面后,我们可以直观看到模拟器顶部搜索框,时间日历小部件,可拖拽应用区域,底部导航指示条以及快捷启动图标,应用文件夹等,基于系统UI层级展示方式,我们通过源码逐步探寻其工作方式.下面我们从onCreate()函数开始
源码位置:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java
2.1 Launcher.onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取LauncherAppState实例,主要处理IconCache,IconCacheProvider、LauncherModel对象初始化及开放对外调用方法
LauncherAppState app = LauncherAppState.getInstance(this);
mOldConfig = new Configuration(getResources().getConfiguration());
//LauncherAppState中定义对外调用方法
mModel = app.getModel();
mRotationHelper = new RotationHelper(this);
//根据屏幕宽高读取最接近设备文件信息,用于桌面图标大小,行列数配置
InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
initDeviceProfile(idp);
idp.addOnChangeListener(this);
//存储库SharePreferences
mSharedPrefs = Utilities.getPrefs(this);
mIconCache = app.getIconCache();
mAccessibilityDelegate = createAccessibilityDelegate();
//初始化拖拽布局控制器
mDragController = new LauncherDragController(this);
//处理所有app在桌面拖拽图标时的动画
mAllAppsController = new AllAppsTransitionController(this);
mStateManager = new StateManager < >(this, NORMAL);
//关联存储库SharePreferences
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs);
//小部件管理helper
mAppWidgetManager = new WidgetManagerHelper(this);
mAppWidgetHost = createAppWidgetHost();
mAppWidgetHost.startListening();
//加载launcher xml
inflateRootView(R.layout.launcher);
//设置所有apps view,放在下面小节单独分析
setupViews();
//淡入淡出动画
crossFadeWithPreviousAppearance();
//设置监听NotificationListener,PopupDataProvider主要处理长按app图标显示内容
mPopupDataProvider = new PopupDataProvider(this: :updateNotificationDots);
//状态处理相关
boolean internalStateHandled = ACTIVITY_TRACKER.handleCreate(this);
if (internalStateHandled) {
if (savedInstanceState != null) {
// InternalStateHandler has already set the appropriate state.
// We dont need to do anything.
savedInstanceState.remove(RUNTIME_STATE);
}
}
restoreState(savedInstanceState);
mStateManager.reapplyState();
if (savedInstanceState != null) {
int[] pageIds = savedInstanceState.getIntArray(RUNTIME_STATE_CURRENT_SCREEN_IDS);
if (pageIds != null) {
mPagesToBindSynchronously = IntSet.wrap(pageIds);
}
}
//LoaderTask相关操作,放在下面小节单独分析
if (!mModel.addCallbacksAndLoad(this)) {
if (!internalStateHandled) {
Log.d(BAD_STATE, "Launcher onCreate not binding sync, prevent drawing");
// If we are not binding synchronously, pause drawing until initial bind complete,
// so that the system could continue to show the device loading prompt
mOnInitialBindListener = Boolean.FALSE: :booleanValue;
}
}
// For handling default keys
setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
//设置页面布局
setContentView(getRootView());
if (mOnInitialBindListener != null) {
getRootView().getViewTreeObserver().addOnPreDrawListener(mOnInitialBindListener);
}
getRootView().dispatchInsets();
//注册屏幕关闭广播监听
registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF));
//更新UiState、Theme(Dark/Light)
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
//hook生命周期方法
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
}
mOverlayManager = getDefaultOverlay();
PluginManagerWrapper.INSTANCE.get(this).addPluginListener(this, LauncherOverlayPlugin.class, false
/* allowedMultiple */
);
//屏幕旋转切换配置初始化
mRotationHelper.initialize();
TraceHelper.INSTANCE.endSection(traceToken);
mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener(() - >getStateManager().goToState(NORMAL));
if (Utilities.ATLEAST_R) {
getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
}
setTitle(R.string.home_screen);
}
launcher类中onCreate()会初始化LauncherAppState实例,用于获取Icon/LauncherModel对象,读取设备文件信息以匹配桌面图标及行列数,初始化SharedPreferences,布局拖拽控制器,设置布局xml,apps view,以及LoaderTask相关操作,设置页面布局及其它配置信息,下面我们来看看源码中setupViews()方法
2.2 Launcher.setupViews()
protected void setupViews() {
//加载根布局
inflateRootView(R.layout.launcher);
mDragLayer = findViewById(R.id.drag_layer);
mFocusHandler = mDragLayer.getFocusIndicatorHelper();
mWorkspace = mDragLayer.findViewById(R.id.workspace);
//初始化PageIndicator
mWorkspace.initParentViews(mDragLayer);
mOverviewPanel = findViewById(R.id.overview_panel);
mHotseat = findViewById(R.id.hotseat);
//设置快捷启动图标工作区
mHotseat.setWorkspace(mWorkspace);
// Setup the drag layer
mDragLayer.setup(mDragController, mWorkspace);
//初始化DragController,更新layer type属性
mWorkspace.setup(mDragController);
//绑定工作区之前锁定壁纸默认状态
mWorkspace.lockWallpaperToDefaultPage();
//初始化第一页并绑定,此处会以CellLayout承载页面,其本身继承于ViewGroup,支持对item拖入拖出操作
mWorkspace.bindAndInitFirstWorkspaceScreen();
//拖拽监听
mDragController.addDragListener(mWorkspace);
// Get the search/delete/uninstall bar
mDropTargetBar = mDragLayer.findViewById(R.id.drop_target_bar);
// Setup Apps
mAppsView = findViewById(R.id.apps_view);
// Setup Scrim
mScrimView = findViewById(R.id.scrim_view);
// Setup the drag controller (drop targets have to be added in reverse order in priority)
mDropTargetBar.setup(mDragController);
//mAppsView设置mScrimView
mAllAppsController.setupViews(mScrimView, mAppsView);
}
以上方法初始化相关views并设置监听,下面我们再看LoaderTask数据加载是如何进行的
源码路径:packages/apps/Launcher3/src/com/android/launcher3/LauncherModel.java
2.3 LoaderTask
public boolean addCallbacksAndLoad(@NonNull final Callbacks callbacks) {
synchronized(mLock) {
addCallbacks(callbacks);
return startLoader(new Callbacks[] {
callbacks
});
}
}
private boolean startLoader(@NonNull final Callbacks[] newCallbacks) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
ItemInstallQueue.INSTANCE.get(mApp.getContext()).pauseModelPush(ItemInstallQueue.FLAG_LOADER_RUNNING);
synchronized(mLock) {
//停止LoaderTask工作线程
boolean wasRunning = stopLoader();
//设置相关标记
boolean bindDirectly = mModelLoaded && !mIsLoaderTaskRunning;
boolean bindAllCallbacks = wasRunning || !bindDirectly || newCallbacks.length == 0;
final Callbacks[] callbacksList = bindAllCallbacks ? getCallbacks() : newCallbacks;
if (callbacksList.length > 0) {
//同步任务执行时清除任意挂起绑定操作
for (Callbacks cb: callbacksList) {
MAIN_EXECUTOR.execute(cb: :clearPendingBinds);
}
//构建loaderResults
LoaderResults loaderResults = new LoaderResults(mApp, mBgDataModel, mBgAllAppsList, callbacksList);
if (bindDirectly) {
// Divide the set of loaded items into those that we are binding synchronously,
// and everything else that is to be bound normally (asynchronously).
loaderResults.bindWorkspace(bindAllCallbacks);
// For now, continue posting the binding of AllApps as there are other
// issues that arise from that.
loaderResults.bindAllApps();
loaderResults.bindDeepShortcuts();
loaderResults.bindWidgets();
return true;
} else {
stopLoader();
//构建LoaderTask任务并准备执行
mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults);
// Always post the loader task, instead of running directly
// (even on same thread) so that we exit any nested synchronized blocks
//通过handler发布mLoaderTask,但不以內联方式运行
MODEL_EXECUTOR.post(mLoaderTask);
}
}
}
return false;
}
通过上面代码调用链,此时mLoaderTask已经发布,我们看下LoaderTask.run()具体执行内容有哪些
public void run() {
...
...
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List < ShortcutInfo > allShortcuts = new ArrayList < >();
try {
//加载工作区
loadWorkspace(allShortcuts, memoryLogger);
} finally {
Trace.endSection();
}
...
//绑定工作区
mResults.bindWorkspace(true /* incrementBindId */);
mModelDelegate.workspaceLoadComplete();
//发送首屏广播通知,通知软件安装包在首屏有效安装
sendFirstScreenActiveInstallsBroadcast();
//等待workspace加载完成
waitForIdle();
...
List < LauncherActivityInfo > allActivityList;
try {
//加载所有apps,从缓存读取user profiles,清空应用列表,根据profile读取所有LauncherActivityInfo,最终添加进缓存集合
allActivityList = loadAllApps();
} finally {
Trace.endSection();
}
...
//绑定所有apps
mResults.bindAllApps();
...
//获取处理图标缓存更新handler
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
setIgnorePackages(updateHandler);
updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel() : :onPackageIconsUpdated);
...
//缓存allShortcuts
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), mApp.getModel() : :onPackageIconsUpdated);
//等待上述步骤操作完成
waitForIdle();
...
//加载应用程序快捷方式
List < ShortcutInfo > allDeepShortcuts = loadDeepShortcuts();
...
//绑定应用快捷启动方式
mResults.bindDeepShortcuts();
...
//缓存allDeepShortcuts
updateHandler.updateIcons(allDeepShortcuts, new ShortcutCachingLogic(), (pkgs, user) - >{});
//等待上述步骤操作完成
waitForIdle();
...
//加载桌面小部件allWidgetsList
List < ComponentWithLabelAndIcon > allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null);
...
//绑定桌面小部件
mResults.bindWidgets();
...
//缓存小部件图标
updateHandler.updateIcons(allWidgetsList, new ComponentWithIconCachingLogic(mApp.getContext(), true), mApp.getModel() : :onWidgetLabelsUpdated);
...
//加载桌面文件夹名称
loadFolderNames();
...
//处理完成
updateHandler.finish();
mModelDelegate.modelLoadComplete();
transaction.commit();
memoryLogger.clearLogs();
} catch(CancellationException e) {
// Loader stopped, ignore
logASplit(logger, "Cancelled");
} catch(Exception e) {
memoryLogger.printLogs();
throw e;
} finally {
logger.dumpToLog();
}
TraceHelper.INSTANCE.endSection(traceToken);
}
在LoaderTask.run()中可以清晰看到加载数据的每一步操作,基于此launcher桌面应用相关信息基本加载完成,Launcher类本身继承于StatefulActivity,其生命周期方法与常规Activity基本一致,感兴趣的可继续在源码里面查看相关方法具体处理内容
3.点击桌面图标启动App
3.1 bindWorkspace与createShortcut
上述步骤中在loadWorkspace()之后紧接着调用bindWorkpsace(),用于将所有加载数据绑定到主线程上的实际视图
public void bindWorkspace(boolean incrementBindId) {
...
...
for (Callbacks cb: mCallbacksList) {
new WorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId, workspaceItems, appWidgets, extraItems, orderedScreenIds).bind();
}
}
主要看下bind()方法,会继续调用bindWorkspaceItems(),用于最终callback调用bindItems,此处callback对象为launcher实例,Launcher中定义了bindItems()
//该方法中会循环调用view = createShortcut(info)创建view,createShortcut()也同样定义在Launcher类中,
private void bindWorkspaceItems(final ArrayList < ItemInfo > workspaceItems, final Executor executor) {
// Bind the workspace items
int count = workspaceItems.size();
for (int i = 0; i < count; i += ITEMS_CHUNK) {
final int start = i;
final int chunkSize = (i + ITEMS_CHUNK <= count) ? ITEMS_CHUNK: (count - i);
executeCallbacksTask(c - >c.bindItems(workspaceItems.subList(start, start + chunkSize), false), executor);
}
}
//创建shortcut
public View createShortcut(ViewGroup parent, WorkspaceItemInfo info) {
BubbleTextView favorite = (BubbleTextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.app_icon, parent, false);
favorite.applyFromWorkspaceItem(info);
//设置图标点击事件,ItemClickHandler用于处理对工作区和所有应用点击响应
favorite.setOnClickListener(ItemClickHandler.INSTANCE);
favorite.setOnFocusChangeListener(mFocusHandler);
return favorite;
}
//点击事件响应
private static void onClick(View v) {
...
...
Object tag = v.getTag();
//来源来为WorkspaceItemInfo,
if (tag instanceof WorkspaceItemInfo) {
//继续调用startAppShortcutOrInfoActivity(v, shortcut, launcher)用于启动activity
onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher);
}
...
...
}
//启动activity
private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher) {
//构建intent
Intent intent;
if (item instanceof ItemInfoWithIcon
&& (((ItemInfoWithIcon) item).runtimeStatusFlags
& ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
ItemInfoWithIcon appInfo = (ItemInfoWithIcon) item;
intent = new PackageManagerHelper(launcher)
.getMarketIntent(appInfo.getTargetComponent().getPackageName());
} else {
intent = item.getIntent();
}
...
if (item instanceof WorkspaceItemInfo) {
WorkspaceItemInfo si = (WorkspaceItemInfo) item;
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)
&& Intent.ACTION_VIEW.equals(intent.getAction())) {the
// web ui. This only works though if the package isn't set
intent = new Intent(intent);
intent.setPackage(null);
}
if ((si.options & WorkspaceItemInfo.FLAG_START_FOR_RESULT) != 0) {
launcher.startActivityForResult(item.getIntent(), 0);
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
launcher.logAppLaunch(launcher.getStatsLogManager(), item, instanceId);
return;
}
}
...
//启动activity
launcher.startActivitySafely(v, intent, item);
}
}
通过startActivitySafely启动activity,我们需要看下Launcher继承关系,
Launcher->StatefulActivity->BaseDraggingActivity->BaseActivity implements AppLauncher,
所以launcher.startActivitySafely最终是调用AppLauncher接口中的同名方法,该方法会构建应用启动需要的显示
的宽高参数、animation、displayId,封装到Bundle对象中,最后调用startShortcut(),方法源码如下:
3.2 startShortcut
default void startShortcut(String packageName, String id, Rect sourceBounds, Bundle startActivityOptions, UserHandle user) {
if (GO_DISABLE_WIDGETS) {
return;
}
try {
((Context) this).getSystemService(LauncherApps.class).startShortcut(packageName, id, sourceBounds, startActivityOptions, user);
} catch(SecurityException | IllegalStateException e) {
Log.e(TAG, "Failed to start shortcut", e);
}
}
//通过一系列参数处理最终走到LauncherApps.java中,源码位置:frameworks/base/core/java/android/content/pm/LauncherApps.java
@UnsupportedAppUsage
private void startShortcut(@NonNull String packageName, @NonNull String shortcutId, @Nullable Rect sourceBounds, @Nullable Bundle startActivityOptions, int userId) {
try {
//此处mService对应LauncherAppsImpl实现类,通过aidl定义实现用于跨进程通信
final boolean success = mService.startShortcut(mContext.getPackageName(), packageName, null
/* default featureId */
, shortcutId, sourceBounds, startActivityOptions, userId);
if (!success) {
throw new ActivityNotFoundException("Shortcut could not be started");
}
} catch(RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@SystemService(Context.LAUNCHER_APPS_SERVICE)通过注解标记系统服务,当作用于类是可便捷获取其服务实例,此处LAUNCHER_APPS_SERVICE对应实例类LauncherAppService.java类
在被注解的LauncherApps类可通过context.getSystemService获取,具体代码位于该类构造函数中;LauncherAppsService构造函数初始化了LauncherAppsImpl实例,在onStart启动服务方法中发布了LAUNCHER_APPS_SERVICE标记服务
LauncherAppsImpl实例中定义了startShortcut()方法,最终调用startShortcutInner()验证调用包,用户是否有权限访问配置文件以及异步创建快捷方式启动intent,并配置intent启动标记,源边界及Splash theme,最后调用startShortcutIntentsAsPublisher()启动activity,
3.3 startShortcutInner
其源码如下
//源码位置:/frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.java
private boolean startShortcutInner(int callerUid, int callerPid, int callingUserId, String callingPackage, String packageName, String featureId, String shortcutId, Rect sourceBounds, Bundle startActivityOptions, int targetUserId) {
verifyCallingPackage(callingPackage, callerUid);
if (!canAccessProfile(targetUserId, "Cannot start activity")) {
return false;
}
if (!mShortcutServiceInternal.isPinnedByCaller(callingUserId, callingPackage, packageName, shortcutId, targetUserId)) {
ensureShortcutPermission(callerUid, callerPid, callingPackage);
}
final AndroidFuture < Intent[] > ret = new AndroidFuture < >();
Intent[] intents;
mShortcutServiceInternal.createShortcutIntentsAsync(getCallingUserId(), callingPackage, packageName, shortcutId, targetUserId, injectBinderCallingPid(), injectBinderCallingUid(), ret);
try {
intents = ret.get();
} catch(InterruptedException | ExecutionException e) {
return false;
}
if (intents == null || intents.length == 0) {
return false;
}
ActivityOptions options = ActivityOptions.fromBundle(startActivityOptions);
if (options != null && options.isApplyActivityFlagsForBubbles()) {
// Flag for bubble to make behaviour match documentLaunchMode=always.
intents[0].addFlags(FLAG_ACTIVITY_NEW_DOCUMENT);
intents[0].addFlags(FLAG_ACTIVITY_MULTIPLE_TASK);
}
intents[0].addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intents[0].setSourceBounds(sourceBounds);
final String splashScreenThemeResName = mShortcutServiceInternal.getShortcutStartingThemeResName(callingUserId, callingPackage, packageName, shortcutId, targetUserId);
if (splashScreenThemeResName != null && !splashScreenThemeResName.isEmpty()) {
if (startActivityOptions == null) {
startActivityOptions = new Bundle();
}
startActivityOptions.putString(KEY_SPLASH_SCREEN_THEME, splashScreenThemeResName);
}
return startShortcutIntentsAsPublisher(intents, packageName, featureId, startActivityOptions, targetUserId);
}
private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents, @NonNull String publisherPackage, @Nullable String publishedFeatureId, Bundle startActivityOptions, int userId) {
final int code;
try {
//mActivityTaskManagerInternal - ActivityTaskManagerService的内部抽象类
code = mActivityTaskManagerInternal.startActivitiesAsPackage(publisherPackage, publishedFeatureId, userId, intents, startActivityOptions);
if (ActivityManager.isStartResultSuccessful(code)) {
return true; // Success
} else {
Log.e(TAG, "Couldn't start activity, code=" + code);
}
return false;
} catch(SecurityException e) {
if (DEBUG) {
Slog.d(TAG, "SecurityException while launching intent", e);
}
return false;
}
}
在LauncherAppsImpl构造函数中,会通过LocalServices.getService(ActivityTaskManagerInternal.class)获取ActivityTaskManagerInternal实例
那该实例何时被添加进去的呢,这个就需要看ActivityTaskManagerService中的start()方法,其中定义了内部类LocalService继承于ActivityTaskManagerInternal抽象类,最终调用
startActivitiesAsPackage()
//源码位置:/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@Override public int startActivitiesAsPackage(String packageName, @Nullable String featureId, int userId, Intent[] intents, Bundle bOptions) {
Objects.requireNonNull(intents, "intents");
final String[] resolvedTypes = new String[intents.length];
// UID of the package on user userId.
// "= 0" is needed because otherwise catch(RemoteException) would make it look like
// packageUid may not be initialized.
int packageUid = 0;
final long ident = Binder.clearCallingIdentity();
try {
for (int i = 0; i < intents.length; i++) {
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(mContext.getContentResolver());
}
packageUid = AppGlobals.getPackageManager().getPackageUid(packageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
} catch(RemoteException e) {
// Shouldn't happen.
} finally {
Binder.restoreCallingIdentity(ident);
}
return getActivityStartController().startActivitiesInPackage(packageUid, packageName, featureId, intents, resolvedTypes, null
/* resultTo */
, SafeActivityOptions.fromBundle(bOptions), userId, false
/* validateIncomingUser */
, null
/* originatingPendingIntent */
, false
/* allowBackgroundActivityStart */
);
}
可以看到最重要的一行:getActivityStartController().startActivitiesInPackage()交由ActivityStartController管理启动activity相关操作,在上一篇博文中
7.AMS.systemReady方法启动Launcher也会涉及ActivityStartController执行executeRequest,
3.4 startActivitiesInPackage
我们继续看下调用方法源码,
//源码位置:/frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
final String reason = "startActivityInPackage";
//校验目标用户id,并保证不是特殊用户
userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), Binder.getCallingUid(), reason);
//准备启动
return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage, callingFeatureId, intents, resolvedTypes, resultTo, options, userId, reason, originatingPendingIntent, allowBackgroundActivityStart);
}
//最终调用启动方法
int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage, @Nullable String callingFeatureId, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason, PendingIntentRecord originatingPendingIntent, boolean allowBackgroundActivityStart) {
...
...
try {
intents = ArrayUtils.filterNotNull(intents, Intent[] : :new);
...
...
final IBinder sourceResultTo = resultTo;
final ActivityRecord[] outActivity = new ActivityRecord[1];
// Lock the loop to ensure the activities launched in a sequence.
synchronized(mService.mGlobalLock) {
mService.deferWindowLayout();
// To avoid creating multiple starting window when creating starting multiples
// activities, we defer the creation of the starting window once all start request
// are processed
mService.mWindowManager.mStartingSurfaceController.beginDeferAddStartingWindow();
try {
for (int i = 0; i < starters.length; i++) {
final int startResult = starters[i].setResultTo(resultTo).setOutActivity(outActivity).execute();
if (startResult < START_SUCCESS) {
// Abort by error result and recycle unused starters.
for (int j = i + 1; j < starters.length; j++) {
mFactory.recycle(starters[j]);
}
return startResult;
}
final ActivityRecord started = outActivity[0];
if (started != null && started.getUid() == filterCallingUid) {
// Only the started activity which has the same uid as the source caller
// can be the caller of next activity.
resultTo = started.token;
} else {
resultTo = sourceResultTo;
// Different apps not adjacent to the caller are forced to be new task.
if (i < starters.length - 1) {
starters[i + 1].getIntent().addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}
}
} finally {
mService.mWindowManager.mStartingSurfaceController.endDeferAddStartingWindow(options != null ? options.getOriginalOptions() : null);
mService.continueWindowLayout();
}
}
} finally {
Binder.restoreCallingIdentity(origId);
}
return START_SUCCESS;
}
在上面方法中通过对ActivityStarter数组循环执行启动activity请求,execute()最终调用该类int execute()方法,后续调用流程就跟startHomeActivity()一致,详细说明参见上一篇博文中
7.AMS.systemReady方法以及后续章节源码说明
4.应用内启动startActivity()
以Activity.startActivity()为例,
//启动activity
public void startActivity(Intent intent, @Nullable Bundle options) {
if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN) && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
if (TextUtils.equals(getPackageName(), intent.resolveActivity(getPackageManager()).getPackageName())) {
// Apply Autofill restore mechanism on the started activity by startActivity()
final IBinder token = mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
// Remove restore ability from current activity
mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
// Put restore token
intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
}
}
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
//startActivityForResult
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
options = transferSpringboardActivityOptions(options);
//Instrumentation.execStartActivity
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options);
...
...
} else {
...
...
}
}
//Instrumentation.execStartActivity
public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) {
...
//参数及监控相关处理
...
try {
...
//此处getService 返回IActivityTaskManager抽象类,实际被ActivityTaskManagerService实现
int result = ActivityTaskManager.getService().startActivity(whoThread, who.getBasePackageName(), who.getAttributionTag(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID: null, requestCode, 0, null, options);
//校验启动结果是否成功
checkStartActivityResult(result, intent);
} catch(RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
//ActivityTaskManagerService.startActivity
//源码位置:/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@Override public final int startActivity(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId());
}
//startActivityAsUser
private int startActivityAsUser(IApplicationThread caller, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
...
...
//此处getActivityStartController()返回ActivityStartController对象,调用obtainStarter实际调用ActivityStarter,通过execute()执行启动请求
return getActivityStartController().obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setCallingFeatureId(callingFeatureId).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setUserId(userId).execute();
}
//调用execute()最终执行executeRequest()启动,源码路径:
/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
- execute()方法处理Activity启动请求,进入到
- executeRequest(mRequest);执行执行一系列权限检查,进入到
- startActivityUnchecked()校验初步权限检查是否完成,进入到
- startActivityInner()启动 Activity,并确定是否将activity添加到栈顶,进入到
- startActivityLocked()判断当前activity是否可见以及是否需要为其新建Task,并将ActivityRecord加入到Task栈顶中,进入到
- resumeFocusedTasksTopActivities() - RootWindowContainer.java ,主要判断targetRootTask是否处于栈顶,同时判断task是否处于暂停状态,进入到
- resumeTopActivityUncheckedLocked() - Task.java,递归调用该方法并查找栈顶可显示activity以及状态是否暂停,进入到
- resumeTopActivityInnerLocked() - Task.java,该方法主要处理ActivityRecord、设置resume状态、准备启动activity,进入到
- resumeTopActivity() - TaskFragment.java,查找栈顶activity是否处于running,检查所有暂停操作是否完成,进入到
- startSpecificActivity() - ActivityTaskSupervisor.java,如果activity已运行则直接启动,未运行则启动目标Activity,开启启动新进程,进入到
realStartActivityLocked() - ActivityTaskManagerService.java,因为Activity.startActivity()在调用前进程已创建,所以分支走到这里
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc, boolean andResume, boolean checkConfig) throws RemoteException { ... try { ... try { ... //创建activity启动事务 final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token); //判断activity是否是前向转换,即从一个Activity转换到另一个Activity,后者在任务栈中的位置比前者更靠前 final boolean isTransitionForward = r.isTransitionForward(); //获取IBinder对象 final IBinder fragmentToken = r.getTaskFragment().getFragmentToken(); //将包含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.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, r.takeOptions(), isTransitionForward, proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController, r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken)); //设置生命周期状态请求 final ActivityLifecycleItem lifecycleItem; if (andResume) { lifecycleItem = ResumeActivityItem.obtain(isTransitionForward); } else { lifecycleItem = PauseActivityItem.obtain(); } clientTransaction.setLifecycleStateRequest(lifecycleItem); //获取ClientLifecycleManager对象,执行事务 mService.getLifecycleManager().scheduleTransaction(clientTransaction); } ... } ... }
ClientLifecycleManager.scheduleTransaction()最终调用ClientTransaction.java中的shedule()方法
该方法将客户端事务加入到系统事务队列中,并按顺序执行preExecute完成前置工作,发送事务message,调用TransactionExecutor.execute()执行所有回调及生命周期转换
mClient对象为IApplicationThread,这是aidl接口,其实际执行对象为ActivityThread,继承于ClientTransactionHandler,内部也实例化TransactionExecutor对象,
public void schedule() throws RemoteException {
mClient.scheduleTransaction(this);
}
//最终调用ActivityThread.scheduleTransaction(),重写了父类ClientTransactionHandler.scheduleTransaction(),执行transaction操作
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
void scheduleTransaction(ClientTransaction transaction) {
transaction.preExecute(this);
//发送handle message
sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}
我们接着看下ActivityThread handleMessage() - case EXECUTE_TRANSACTION
case EXECUTE_TRANSACTION:
//获取message
final ClientTransaction transaction = (ClientTransaction) msg.obj;
//执行
mTransactionExecutor.execute(transaction);
if (isSystem()) {
//系统进程內的事务在客户端回收掉
transaction.recycle();
}
// TODO(lifecycler): Recycle locally scheduled transactions.
break;
//TransactionExecutor.execute()
public void execute(ClientTransaction transaction) {
...
//循环执行回调请求
executeCallbacks(transaction);
//执行生命周期回调
executeLifecycleState(transaction);
...
}
- executeLifecycleState()会调用cycleToPath()用于在状态之间转换客户端, 进入到
- performLifecycleSequence() ,通过之前初始化的状态转换客户端,此时状态走到ON_CREATE,进入到
- handleLaunchActivity() - ClientTransactionHandler.java,该类为抽象类,具体实现在ActivityThread中,
- ActivityThread.handleLaunchActivity() ,准备执行启动,进入到
performLaunchActivity() , 启动activity的核心实现方法,主要处理检查包信息,组件名称,Context,组装classLoader,调用mInstrumentation.newActivity()
//启动activity核心实现方法 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ActivityInfo aInfo = r.activityInfo; //校验包信息 if (r.packageInfo == null) { r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo, Context.CONTEXT_INCLUDE_CODE); } //校验启动组件信息 ComponentName component = r.intent.getComponent(); if (component == null) { component = r.intent.resolveActivity(mInitialApplication.getPackageManager()); r.intent.setComponent(component); } if (r.activityInfo.targetActivity != null) { component = new ComponentName(r.activityInfo.packageName, r.activityInfo.targetActivity); } //创建context ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; try { //获取ClassLoader - /frameworks/base/core/java/android/app/ContextImpl.java java.lang.ClassLoader cl = appContext.getClassLoader(); //实例化activity,反射生成 activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); StrictMode.incrementExpectedActivityCount(activity.getClass()); r.intent.setExtrasClassLoader(cl); r.intent.prepareToEnterProcess(isProtectedComponent(r.activityInfo), appContext.getAttributionSource()); if (r.state != null) { r.state.setClassLoader(cl); } } catch(Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException("Unable to instantiate activity " + component + ": " + e.toString(), e); } } try { //获取Application,默认从缓存获取,不存在通过Instrumentation.newApplication()创建新的返回,同时回调Application.onCreate() Application app = r.packageInfo.makeApplicationInner(false, mInstrumentation); if (localLOGV) Slog.v(TAG, "Performing launch of " + r); if (localLOGV) Slog.v(TAG, r + ": app=" + app + ", appName=" + app.getPackageName() + ", pkg=" + r.packageInfo.getPackageName() + ", comp=" + r.intent.getComponent().toShortString() + ", dir=" + r.packageInfo.getAppDir()); // updatePendingActivityConfiguration() reads from mActivities to update // ActivityClientRecord which runs in a different thread. Protect modifications to // mActivities to avoid race. synchronized(mResourcesManager) { mActivities.put(r.token, r); } if (activity != null) { CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager()); Configuration config = new Configuration(mConfigurationController.getCompatConfiguration()); if (r.overrideConfig != null) { config.updateFrom(r.overrideConfig); } if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity " + r.activityInfo.name + " with config " + config); //设置Window Window window = null; if (r.mPendingRemoveWindow != null && r.mPreserveWindow) { window = r.mPendingRemoveWindow; r.mPendingRemoveWindow = null; r.mPendingRemoveWindowManager = null; } //初始化Activity resources // Activity resources must be initialized with the same loaders as the // application context. appContext.getResources().addLoaders(app.getResources().getLoaders().toArray(new ResourcesLoader[0])); //设置当前context appContext.setOuterContext(activity); //调用activity attach方法 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.activityConfigCallback, r.assistToken, r.shareableActivityToken); //设置activity intent if (customIntent != null) { activity.mIntent = customIntent; } r.lastNonConfigurationInstances = null; //等待网络规则更新 - ActivityManagerService.waitForNetworkStateUpdate() checkAndBlockForNetworkAccess(); activity.mStartedActivity = false; //设置主题theme int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } if (r.mActivityOptions != null) { activity.mPendingOptions = r.mActivityOptions; r.mActivityOptions = null; } activity.mLaunchedFromBubble = r.mLaunchedFromBubble; activity.mCalled = false; // Assigning the activity to the record before calling onCreate() allows // ActivityThread#getActivity() lookup for the callbacks triggered from // ActivityLifecycleCallbacks#onActivityCreated() or // ActivityLifecycleCallback#onActivityPostCreated(). r.activity = activity; //开始回调activity.onCreate() if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } if (!activity.mCalled) { throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()"); } mLastReportedWindowingMode.put(activity.getActivityToken(), config.windowConfiguration.getWindowingMode()); } r.setState(ON_CREATE); } catch(SuperNotCalledException e) { throw e; } catch(Exception e) { if (!mInstrumentation.onException(activity, e)) { throw new RuntimeException("Unable to start activity " + component + ": " + e.toString(), e); } } //返回activity实例 return activity; }
5.小结
在startActivity()调用启动中,Instrumentation类扮演十分重要的角色,该类中定义了一系列call方法,监控着activity生命周期方法以及application.onCreate()、execStartActivity()等,用来处理应用和系统进程所有交互,在Android插件化相关处理中,也可以看到hook instrumentation相关操作,了解源码调用流程也能帮助我们找到合适的切入点
6.文档说明
由于源码流程较长,整体调用链非常繁杂,可能存在错漏的地方,欢迎在阅读时提出问题和不足
参考文档: