android - home键及launcher启动流程分析

时间:2021-09-08 16:42:15
android - home键及launcher启动流程分析


launcher,也就是android的桌面应用程序,开机启动的第一个应用程序及按home键进入的都是这个程序。
如果需要修改启动流程或者制作一个新的launcher,都有必要了解一下这个流程。


第一部分:系统默认Home应用程序(launcher)启动流程


1、frameworks/base/services/java/com/android/server/SystemServer.java
   
   一直以来大家都记得"hello world"程序就是写一个main函数,那么我们这里也从main函数开始:
   
   public static void main(String[] args) 
   
   这里分为两个过程:
   SystemServer.init1
   启动几个重要navtive service,比如 SurfaceFlinger、SensorService
   
   SystemServer.init2
   启动java service,比如 ContentService、PowerManagerService、MountService、WindowManagerService 等等
   
2、frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java
启动 ActivityManagerService跳到如下:

 Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);

public static final Context main(int factoryTest) {
AThread thr = new AThread();
thr.start();

synchronized (thr) {
while (thr.mService == null) {
try {
thr.wait();
} catch (InterruptedException e) {
}
}
}

ActivityManagerService m = thr.mService;
mSelf = m;
ActivityThread at = ActivityThread.systemMain();
mSystemThread = at;
Context context = at.getSystemContext();
context.setTheme(android.R.style.Theme_Holo);
m.mContext = context;
m.mFactoryTest = factoryTest;
m.mMainStack = new ActivityStack(m, context, true);

m.mBatteryStatsService.publish(context);
m.mUsageStatsService.publish(context);

synchronized (thr) {
thr.mReady = true;
thr.notifyAll();
}

m.startRunning(null, null, null, null);

return context;
}


这个函数首先通过AThread线程对象来内部创建了一个ActivityManagerService实例,然后将这个实例保存其成员变量
mService中,接着又把这个ActivityManagerService实例保存在ActivityManagerService类的静态成员变量mSelf中,
最后初始化其它成员变量,就结束了。


AThread 线程启动代码如下:

    AThread thr = new AThread();
thr.start();

static class AThread extends Thread {
ActivityManagerService mService;
boolean mReady = false;

public AThread() {
super("ActivityManager");
}

public void run() {
Looper.prepare();

android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);

ActivityManagerService m = new ActivityManagerService();

synchronized (this) {
mService = m;
notifyAll();
}

synchronized (this) {
while (!mReady) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
...
}

3、ActivityManagerService.systemReady


ServerThread.run函数在将系统中的一系列服务都初始化完毕之后才调用

SystemService.java:

// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
Slog.i(TAG, "Making services ready");

核心代码如下:

public final class ActivityManagerService extends ActivityManagerNative  
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
......
public void systemReady(final Runnable goingCallback) {
......
synchronized (this) {
......
mMainStack.resumeTopActivityLocked(null);
}
}
......
}

4、ActivityStack.resumeTopActivityLocked

    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);

// Remember how we'll process this pause/resume situation, and ensure
// that the state is reset however we wind up proceeding.
final boolean userLeaving = mUserLeaving;
mUserLeaving = false;

if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
ActivityOptions.abort(options);
return mService.startHomeActivityLocked(mCurrentUser);
}
}

...
}

    这里调用函数topRunningActivityLocked返回的是当前系统Activity堆栈最顶端的Activity,由于此时还没有
   Activity被启动过,因此,返回值为null,即next变量的值为null,于是就调用mService.startHomeActivityLocked函数

5、startHomeActivityLocked

boolean startHomeActivityLocked(int userId) {
...
Intent intent = new Intent(
mTopAction,
mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
ActivityInfo aInfo =
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid);
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mMainStack.startActivityLocked(null, intent, null, aInfo,
null, null, 0, 0, 0, 0, null, false, null);
}
}

return true;
}

    函数首先创建一个CATEGORY_HOME类型的Intent,然后通过Intent.resolveActivityInfo函数向PackageManagerService
    查询Category类型为HOME的Activity,即 packages/apps/Launcher2/AndroidManifest.xml文件中所示:
    这里就是将拼装好的 home intent 发送出去即可
    

    <activity  
android:name="com.android.launcher2.Launcher"
android:launchMode="singleTask"
android:clearTaskOnLaunch="true"
android:stateNotNeeded="true"
android:theme="@style/Theme"
android:screenOrientation="nosensor"
android:windowSoftInputMode="stateUnspecified|adjustPan">
<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>

6、ResolverActivity.java
frameworks\base\core\java\com\android\internal\app\ResolverActivity.java


/**
* This activity is displayed when the system attempts to start an Intent for
* which there is more than one matching activity, allowing the user to decide
* which to go to. It is not normally used directly by application developers.
*/
public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {

这是应用程序就是查找匹配的intent-filter应用程序,多于一个时则列表提示用户选择,默认或者只有一个则直接进入。

    mCurrentResolveList = mPm.queryIntentActivities(
mIntent, PackageManager.MATCH_DEFAULT_ONLY);

最后以一个序列图总结下:

android - home键及launcher启动流程分析

第二部分:按home键启动Home应用


既然是按键,这里就简要说明一下按键事件处理流程:
1、InputManager负责读取事件并把事件送到frameworks的java层
2、WindowManagerService里会有一个InputMonitor类来监听事件变化并做相应的分发处理。
3、在WindowManagerService会有一个WindowManagerPolicy来做消息拦截处理。
4、WindowManagerService会把消息发给最上面运行的窗口接收
5、这里最上面窗口就是 PhoneWindowManager 


/**
* WindowManagerPolicy implementation for the Android phone UI. This
* introduces a new method suffix, Lp, for an internal lock of the
* PhoneWindowManager. This is used to protect some internal state, and
* can be acquired with either thw Lw and Li lock held, so has the restrictions
* of both of those when held.
*/
public class PhoneWindowManager implements WindowManagerPolicy

PhoneWindowManager 实现 Android UI


interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags)
这个方法就是预先处理按键消息的,即由系统处理,一般 HOME、MUTE、POWER等都是由系统先处理


    /** {@inheritDoc} */
@Override
public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
...
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
// timeout.
if (keyCode == KeyEvent.KEYCODE_HOME) {
...
//单击home处理
launchHomeFromHotKey();
}

...
}

下面就是处理home键的功能


    /**
* A home key -> launch home action was detected. Take the appropriate action
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
public void onKeyguardExitResult(boolean success) {
if (success) {
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}
});
} else {
// no keyguard stuff to worry about, just launch home!
try {
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
startDockOrHome();
}
}

发送home intent出去:


    void startDockOrHome() {
// We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.
mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
}

其中 mHomeIntent 是由init()函数初始化完成的


    mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

最后也是由 ResolverActivity 继续处理,上面已经讲过了,这里就略写了。