android - home键及launcher启动流程分析
来源:互联网 发布:mp3电路图 不用单片机 编辑:程序博客网 时间:2024/04/30 04:32
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等都是由系统先处理
- /** {@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 继续处理,上面已经讲过了,这里就略写了。
- android - home键及launcher启动流程分析
- android - home键及launcher启动流程分析
- home键及launcher启动流程分析
- Android启动流程——Home Launcher
- android 启动launcher流程
- android home键流程分析
- Android Home启动流程
- Android应用Home键后Launcher重复启动问题
- Android应用Home键后Launcher重复启动问题
- Android中ICS4.0源码Launcher启动流程分析
- [Android]从Launcher开始启动App流程源码分析
- Android系统默认HOME(Launcher)应用程序启动
- Android—launcher 启动流程
- Android MTK 设置开机启动自定义Launcher Home键换出Launcher切换
- Android中ICS4.0源码Launcher启动流程分析【android源码Launcher系列一】
- Android中ICS4.0源码Launcher启动流程分析【android源码Launcher系列一】
- Android中ICS4.0源码Launcher启动流程分析【android源码Launcher系列一】
- Android中ICS4.0源码Launcher启动流程分析【android源码Launcher系列一】
- buffer busy waits
- SIFT、SURF及相关特征描述子概述
- 我有一个char * 型指针正巧指向一些int 型变量, 我想跳过它们。为什么如下的代码((int *)p)++; 不行?
- C++ Primer笔记6_STL之泛型算法
- 源代码
- android - home键及launcher启动流程分析
- 数据库查询报错:选择列表中的列 '字段' 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
- pgsql 排序
- shell编程awk
- 我原来的百度博客,用了七、八年了
- CodeIgniter的源码解读
- 判断字符串的编码格式
- 教你怎么使用Makefile编译工程代码
- flv文件AVCDecoderConfigurationRecord以及AudioSpecificConfig结构