Android 源码分析 (二) Launcher 启动

 

通过进阶解密学习 记录 Launcher 启动过程,记录加深理解后续其他Android版本的启动流程

 

系统启动的最后一步时启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序就叫做Launcher。Launcher在启动过程中会请求PackageManagerService返回系统中已经安装的应用程序的信息,并将这些信息封装成一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序。

时序图如下 

KDsaIP.png

Launcher的启动过程

 Launcher 的入口为 AMS 的 systemRead 函数,它在 SystemServer 的 startOtherServices 函数中被调用

//com.android.server SystemServer.java

public void startOtherServices(){
  ...
 
  mActivityManagerService.systemReady(() -> {
  ...
  }     
}

在AMS 的 systemRead 函数实现

//com.android.server.am ActivityManagerService.java

  public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
        ...
        synchronized(this) {
            ...
			1. 
            mStackSupervisor.resumeFocusedStackTopActivityLocked();
            mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
            
        }
    }

    //package com.android.server.am; ActivityStackSupervisor.java
    
	boolean resumeFocusedStackTopActivityLocked() {
        return resumeFocusedStackTopActivityLocked(null, null, null);
    }

    boolean resumeFocusedStackTopActivityLocked(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
         需要启动的目标栈不为空,并且启动的栈跟需要启动栈一样就执行
        if (targetStack != null && isFocusedStack(targetStack)) {
            
              2 
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
        }
        ...
        return false;
    }
//com.android.server.am ActivityStack.java
    boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
        if (mStackSupervisor.inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            mStackSupervisor.inResumeTopActivity = true;
            3 
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            mStackSupervisor.inResumeTopActivity = false;
        }
        
        mStackSupervisor.checkReadyForSleepLocked();

        return result;
    }
//com.android.server.am; ActivityStack.java

    private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...
      
     return isOnHomeDisplay() &&
                        4
                        mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
            }
    ...
      
    }

//com.android.server.am; ActivityStackSupervisor.java

    boolean resumeHomeStackTask(ActivityRecord prev, String reason) {
        ...

        if (prev != null) {
            prev.getTask().setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
        }
        
        mHomeStack.moveHomeStackTaskToTop();
        获取 HomeActivity
         
        ActivityRecord r = getHomeActivity();
        final String myReason = reason + " resumeHomeStackTask";

        // Only resume home activity if isn't finishing.
        if (r != null && !r.finishing) {
            moveFocusableActivityStackToFrontLocked(r, myReason);
            return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
        }
        //调用 AMS startHomeActivityLocked 函数
               5
        return mService.startHomeActivityLocked(mCurrentUser, myReason);
    }

从上述的代码中主要 通过中AMS 的 systemRead .调resumeFocusedStackTopActivityLocked(); 1至5 处 层层调用,最后通过ActivityManagerService 创建Laucncher启动的所需的Intent

//com.android.server.am; ActivityManagerService.java

    boolean startHomeActivityLocked(int userId, String reason) {
         1 判断mFactoryTest的工厂模式 和mTopAction  的值
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            return false;
        }
        
         2.  创建 Launcher 所需要的 Intent
        Intent intent = getHomeIntent();
        ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
          
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
    
            if (app == null || app.instr == null) { 3
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
                // For ANR debugging to verify if the user activity is the one that actually
                // launched.
                final String myReason = reason + ":" + userId + ":" + resolvedUserId;
                4  启动的应用程序就是 Launcher,
                mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
            }
        } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
        }

        return true;
    }


 上面代码主要做了一下几件事:

1  FactoryTest: 代表启动的运行模式:非工厂模式、低级工厂模式、高级工厂模式 ,         mTopAction: 则描述第一个被启动 Activity 组件的 Action,默认是 Intent.ACTION_MAIN.

判断当前FactoryTest 为低级工厂模式  并且 mTopAction 为空的时候 返回 false 

2 创建 Launcher 所需要的 Intent

3  判断符合 action 为 Intent.ACTION_MAIN、Category 为 Intent.CATEGORY_HOME 的应用程序是否已经启动

4 如果没有启动,则启动应用

回头在看 getHomeIntent() 怎么设置 Launcher 的 Intent

//com.android.server.am; ActivityManagerService.java

    Intent getHomeIntent() {
        //传入第一个启动的 action 和 启动的 mTopData
        Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
      	
        intent.setComponent(mTopComponent);
      	
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
      	//设置主页面
        if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
            intent.addCategory(Intent.CATEGORY_HOME);
        }
        return intent;
    }

getHomeIntent() 获取到的就是 Launcher.java 启动 Intent

//android-8.0.0_r1/packages/apps/Launcher3/AndroidManifest.xml

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.launcher3">
    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21"/>
   ....
      		1. 手机启动的主页面
           <activity
            android:name="com.android.launcher3.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:windowSoftInputMode="adjustPan|stateUnchanged"
            android:screenOrientation="nosensor"
            android:configChanges="keyboard|keyboardHidden|navigation"
            android:resizeableActivity="true"
            android:resumeWhilePausing="true"
            android:taskAffinity=""
            android:enabled="true">

            2. 设置了 android.intent.action.MAIN 属性就是主启动
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            </intent-filter>
        </activity>   
   ...
  
 </manifest>

这里看到清单文件中 Launcher 中 intent-filter action配置android.intent.action.MAIN 属性,这样Launcher 的 Activity 也就成了主 Activity

接着上述代码中  ActivityManagerService中startHomeActivityLocked函数标记4处

调用 startActivityLocked 来启动 Launcher Activity

//com.android.server.am; ActivityStarter.java
    void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
      
       
        mSupervisor.moveHomeStackTaskToTop(reason);
        
         1  Launcher 的 onCreate 函数
         
        mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent,
                null /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/,
                null /*voiceSession*/, null /*voiceInteractor*/, null /*resultTo*/,
                null /*resultWho*/, 0 /*requestCode*/, 0 /*callingPid*/, 0 /*callingUid*/,
                null /*callingPackage*/, 0 /*realCallingPid*/, 0 /*realCallingUid*/,
                0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/,
                false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/,
                null /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
        if (mSupervisor.inResumeTopActivity) {
            mSupervisor.scheduleResumeTopActivities();
        }
    }
// package com.android.launcher3; Launcher.java

public class Launcher extends BaseActivity implements LauncherExterns, View.OnClickListener, OnLongClickListener,LauncherModel.Callbacks, View.OnTouchListener, LauncherProviderChangeListener, AccessibilityManager.AccessibilityStateChangeListener {
                     

  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
      
      ...
      1 加载布局 R.layout.launcher 
      mLauncherView = getLayoutInflater().inflate(R.layout.launcher, null);
      ...
      2 设置布局底层解析 
      setContentView(mLauncherView); 
      ...
    }
                     
}

至此startActivityLocked 来启动 Launcher Activity,Activity 启动,终进入到 Launcher 的 onCreate 生命周期函数中.

Launcher 应用图标显示

Launcher onCreate 生命周期函数

//com.android.launcher3; Launcher.java

public class Launcher extends BaseActivity
        implements LauncherExterns, View.OnClickListener, OnLongClickListener,
                   LauncherModel.Callbacks, View.OnTouchListener, LauncherProviderChangeListener,
                   AccessibilityManager.AccessibilityStateChangeListener {
                     
                     
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
				...

        super.onCreate(savedInstanceState);

        1 获取 LauncherAppState 实例
        LauncherAppState app = LauncherAppState.getInstance(this);

       
        2 将 Launcer 与 LauncherAppState 对象绑定
        mModel = app.setLauncher(this);
 
        ... 
        mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);

        mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
        mAppWidgetHost.startListening();

 
        mPaused = false;
		
        mLauncherView = getLayoutInflater().inflate(R.layout.launcher, null);

         .....

        lockAllApps();

      
       3 调用 LauncherModel 的 startLoader 函数
        if (!mModel.startLoader(currentScreen)) {
            mDragLayer.setAlpha(0);
        } else {
        
           ...
        }

  
	    
        setContentView(mLauncherView);
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.onCreate(savedInstanceState);
        }
    }                    
                                   
}

我们先来看 LauncherAppState 的 setLauncher 方法实现

//com.android.launcher3; LauncherAppState.java

    LauncherModel setLauncher(Launcher launcher) {
        getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
      	LauncherModel initialize 初始化工作
        mModel.initialize(launcher);
        return mModel;
    }

LauncherModel initialize 具体实现

//com.android.launcher3; LauncherModel.java
    public void initialize(Callbacks callbacks) {
        synchronized (mLock) {
            Preconditions.assertUIThread();
            // Remove any queued UI runnables
         
            mHandler.cancelAll();
            1  Callbacks ,也就是传入的 Launcher
            mCallbacks = new WeakReference<>(callbacks);
        }
    }

我们得知 mCallBack 的成员变量指的就是封装成弱引用对象 Launcher 这个mCallback会在Launcher 的onCreate 3 处调用 ,我们看注释 3 的 LauncherModel 调用 startLoader 函数实现:

//com.android.launcher3; LauncherModel.java

public class LauncherModel extends BroadcastReceiver
        implements LauncherAppsCompat.OnAppsChangedCallbackCompat {
 
1. 创建了消息循环的线程
    @Thunk static final HandlerThread sWorkerThread = new HandlerThread("launcher-loader");
    static {
        //启动
        sWorkerThread.start();
    }

   2.创建 Hander并且传入HanderThread的Looper
    @Thunk static final Handler sWorker = new Handler(sWorkerThread.getLooper());       
        
    //Launcher 的弱引用
    @Thunk WeakReference<Callbacks> mCallbacks;   
    

    
    public boolean startLoader(int synchronousBindPage) {
        InstallShortcutReceiver.enableInstallQueue();
        synchronized (mLock) {
            if (mCallbacks != null && mCallbacks.get() != null) {
                final Callbacks oldCallbacks = mCallbacks.get();
                
                runOnMainThread(new Runnable() {
                    public void run() {
                        oldCallbacks.clearPendingBinds();
                    }
                });

                // If there is already one running, tell it to stop.
                stopLoaderLocked();
                3. 创建 LoaderTask
                mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage);
                if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
                        && mModelLoaded && !mIsLoaderTaskRunning) {
                    mLoaderTask.runBindSynchronousPage(synchronousBindPage);
                    return true;
                } else {
                    sWorkerThread.setPriority(Thread.NORM_PRIORITY);
                    4.  将mLoaderTask 作为消息发送给 HandlerThread
                    sWorker.post(mLoaderTask);
                }
            }
        }
        return false;
    }
    
    ...//省略部分代码
        
}

由上LauncherModel可知做了如下操作

1 创建具有消息循环的线程HanderThread的对象

2 创建Hander并且传入了HandlerThread的Looper,Hander向HandlerThread发消息

3 创建 LoaderTask 实例,它实现了 Runnable 接口

4 LoaderTask 作为消息发送给了 HandlerThread 的 Looper 来处理,最后 在 LoaderTask 的 run 函数回调

看下 LoaderTask run的 方法

private class LoaderTask implements Runnable {
  
...
  
          public void run() {
            synchronized (mLock) {
                if (mStopped) {
                    return;
                }
                mIsLoaderTaskRunning = true;
            }

            try {
                if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
                // Set to false in bindWorkspace()
                mIsLoadingAndBindingWorkspace = true;

               
                1. 加载工作区信息
                loadWorkspace();
                2. 绑定工作区信息

                bindWorkspace(mPageToBindFirst);

								...

                3. 加载系统以及安装额应用程序信息
                loadAllApps();

         
       					...
            } catch (CancellationException e) {
             
            }
  
							...
  
  
}

Launcher 是工作区的形式来显示系统安装的应用程序的快捷图标的,每一个工作区都是用来描述一个抽象桌面的,它有 n 个屏幕组成,每一个屏幕又分为 n 个单元格,每个单元格用来显示一个应用程序的快捷图标。在 1 、2 处分别调用了 bindWorkspace 函数来加载和绑定工作区信息。

我们看下3处的实现

//com.android.launcher3 LauncherModel.java

        private void loadAllApps() {
          ...
            mHandler.post(new Runnable() {
                public void run() {

                    final long bindTime = SystemClock.uptimeMillis();
                    final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
                    if (callbacks != null) {
                        1.callbacks 实际指向的 Launcher 的,
                        callbacks.bindAllApplications(added);
                        if (DEBUG_LOADERS) {
                            Log.d(TAG, "bound " + added.size() + " apps in "
                                    + (SystemClock.uptimeMillis() - bindTime) + "ms");
                        }
                    } else {
                        Log.i(TAG, "not binding apps: no Launcher activity");
                    }
                }
            });
           ...
        }

在一处 callbacks 实际指向的 Launcher 的,所以 Launcher.java 类中看它具体实现 bindAllApplications

//com.android.launcher3; Launcher.java

    public void bindAllApplications(final ArrayList<AppInfo> apps) {
        if (waitUntilResume(mBindAllApplicationsRunnable, true)) {
            mTmpAppsList = apps;
            return;
        }

        if (mAppsView != null) {
           1. 将包含应用信息的列表 apps 传入 mAppsView 中
            mAppsView.setApps(apps);
        }
        if (mLauncherCallbacks != null) {
            mLauncherCallbacks.bindAllApplications(apps);
        }
    }
//com.android.launcher3.allapps; AllAppsContainerView.java
    public void setApps(List<AppInfo> apps) {
        mApps.setApps(apps);
    }

mApps 成员变量是 AlphabeticalAppsList 里面的函数,接着在跟

//com.android.launcher3.allapps; AlphabeticalAppsList.java
    public void setApps(List<AppInfo> apps) {
        mComponentToAppMap.clear();
        1. 添加 APP
        addApps(apps);
    }

    public void addApps(List<AppInfo> apps) {
      	2. 更新 APP
        updateApps(apps);
    }

    /**
     * Updates existing apps in the list
     */
    public void updateApps(List<AppInfo> apps) {
      
        for (AppInfo app : apps) {
            mComponentToAppMap.put(app.toComponentKey(), app);
        }
        onAppsUpdated();
    }

     private void updateAdapterItems() {
        refillAdapterItems();
        refreshRecyclerView();
    }

    private void refreshRecyclerView() {
        if (mAdapter != null) {
          //刷新 RecyclerView.Adapter 
            mAdapter.notifyDataSetChanged();
        }
    }

   }

我们在看初始化Adapter的地方在 就在 AllAppsContainerView 布局对象加载完成之后的回调 onFinishInflate 中

//com.android.launcher3.allapps; AllAppsContainerView.java
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
				....
        
        mAppsRecyclerView = (AllAppsRecyclerView) findViewById(R.id.apps_list_view);
      
        mAppsRecyclerView.setApps(mApps);
        mAppsRecyclerView.setLayoutManager(mLayoutManager);
         得到RecyclerView并且设置加载适配器
        mAppsRecyclerView.setAdapter(mAdapter);
        mAppsRecyclerView.setHasFixedSize(true);
        mAppsRecyclerView.addOnScrollListener(mElevationController);
        mAppsRecyclerView.setElevationController(mElevationController);


    }

launcher 启动流程分析完了,我们来总结一下

Android系统启动流程总结
1 启动电源及系统启动。当电源按下时引导芯片代码从预定义的地方(固化在ROM)开始执行。加载引导程序BootLoader到RAM,然后执行;
2 引导程序BootLoader。引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把OS拉起来并运行;
3 Linux内核启动。当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc文件,并启动init进程;
4 init进程启动。初始化合启动属性服务,并且启动Zygote进程;
5 Zygote进程启动。创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务端Socket,启动SystemServer进程;
6 SystemServer进程启动。启动Binder线程池和SystemServiceManager,并且启动各种系统服务;
7  Launcher启动。被SystemServer进程启动的AMS会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值