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

来源:互联网 发布:mac安装农行安全控件 编辑:程序博客网 时间:2024/04/30 02:40
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等都是由系统先处理


    /** {@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 继续处理,上面已经讲过了,这里就略写了。


原创粉丝点击