源码标准:API : 29「Android 10.0」
补充知识点:
上一篇讲了Android开机流程,就是Zygote开始fork出SystemServer进程。
在SystemServer中会创建一个socket接口来监听请求以及初始化AMS。
根据请求,Zygote会基于自身,预先加载的虚拟机来创建一个新的虚拟机,创建一个新的进程,来管理新的App进程。

为什么点击手机屏幕上的图标就能打开app?

屏幕本质上就是一个程序app,当我们安装好app后就会出现一个图标。

/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

/**
 * Default launcher application.
 * 也就是桌面
 */
public class Launcher extends BaseDraggingActivity implements LauncherExterns,
        LauncherModel.Callbacks, LauncherProviderChangeListener, UserEventDelegate,
        InvariantDeviceProfile.OnIDPChangeListener {
    public static final String TAG = "Launcher";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null);
          setContentView(mLauncherView);
    }

}

Launcher「桌面」 进程通过 Binder ICP 机制,通知ActivityManagerService「AMS」来创建新的进程。
也就是ActivityThread「UI线程」(Activity运行在ActivityThread实例中)。

ActivityThread通过 Binder ICP 机制将Binder对象传递给AMS,彼此进行通信。

当点击app图标。

   /**
     * Creates a view representing a shortcut inflated from the specified resource.
     *
     * @param parent The group the shortcut belongs to.
     * @param info The data structure describing the shortcut.
     * @return A View inflated from layoutResId.
     */
    public View createShortcut(ViewGroup parent, WorkspaceItemInfo info) {
        BubbleTextView favorite = (BubbleTextView) LayoutInflater.from(parent.getContext())
                .inflate(R.layout.app_icon, parent, false);
        favorite.applyFromWorkspaceItem(info);
        favorite.setOnClickListener(ItemClickHandler.INSTANCE);
        favorite.setOnFocusChangeListener(mFocusHandler);
        return favorite;
    }

这里定位到具体的点击holder类。

/packages/apps/Launcher3/src/com/android/launcher3/touch/ItemClickHandler.java

/**
 * Class for handling clicks on workspace and all-apps items
 */
public class ItemClickHandler {

private static void onClick(View v, String sourceContainer) {
     
        Launcher launcher = Launcher.getLauncher(v.getContext());
        Object tag = v.getTag();
        if (tag instanceof WorkspaceItemInfo) {
            onClickAppShortcut(v, (WorkspaceItemInfo) tag, launcher, sourceContainer);
        } else if (tag instanceof FolderInfo) {
            if (v instanceof FolderIcon) {
                onClickFolderIcon(v);
            }
        } else if (tag instanceof AppInfo) {
            //app类型点击
            startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher,
                    sourceContainer == null ? CONTAINER_ALL_APPS: sourceContainer);
        } else if (tag instanceof LauncherAppWidgetInfo) {
            if (v instanceof PendingAppWidgetHostView) {
                onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
            }
        }
    }

   /**
     * Event handler for an app shortcut click.
     * @param v The view that was clicked. Must be a tagged with a {@link WorkspaceItemInfo}.
     */
    public static void onClickAppShortcut(View v, WorkspaceItemInfo shortcut, Launcher launcher,
            @Nullable String sourceContainer) {
        // Check for abandoned promise
        if ((v instanceof BubbleTextView) && shortcut.hasPromiseIconUi()) {
            String packageName = shortcut.intent.getComponent() != null ?
                    shortcut.intent.getComponent().getPackageName() : shortcut.intent.getPackage();
            if (!TextUtils.isEmpty(packageName)) {
                onClickPendingAppItem(v, launcher, packageName,
                        shortcut.hasStatusFlag(WorkspaceItemInfo.FLAG_INSTALL_SESSION_ACTIVE));
                return;
            }
        }
        // Start activities
        startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer);
    }

    private static void startAppShortcutOrInfoActivity(View v, ItemInfo item, Launcher launcher,
            @Nullable String sourceContainer) {
        Intent intent;
        if (item instanceof PromiseAppInfo) {
            PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
            intent = promiseAppInfo.getMarketIntent(launcher);
        } 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())) {
                intent = new Intent(intent);
                intent.setPackage(null);
            }
        }
        if (v != null && launcher.getAppTransitionManager().supportsAdaptiveIconAnimation()) {
            // Preload the icon to reduce latency b/w swapping the floating view with the original.
            FloatingIconView.fetchIcon(launcher, v, item, true /* isOpening */);
        }
        launcher.startActivitySafely(v, intent, item, sourceContainer);
    }
}

真是从里寻他千百度,我快进入死循环里出不来了,多少有点费劲。
最后通过startActivitySafely方法,在新的Task中启动MainActivity。

posted on 2022-02-10 13:46  翻滚的咸鱼  阅读(742)  评论(0编辑  收藏  举报