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);
最后以一个序列图总结下:
第二部分:按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等都是由系统先处理
/** [email protected]} */ @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 继续处理,上面已经讲过了,这里就略写了。
- 1楼supersugar3126昨天 16:57
- 学习了,有时候学习方法真的很重要……