关于android:Android-桌面App启动与startActivity流程

3次阅读

共计 32212 个字符,预计需要花费 81 分钟才能阅读完成。

本文基于 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. 文档阐明

因为源码流程较长,整体调用链十分繁冗,可能存在错漏的中央,欢送在浏览时提出问题和有余

参考文档:

Android Code Search

/ – OpenGrok cross reference for / (aospxref.com)

正文完
 0