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

来源:互联网 发布:mp3电路图 不用单片机 编辑:程序博客网 时间:2024/04/30 04:32
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跳到如下:

[java] view plaincopyprint?
  1. Slog.i(TAG, "Activity Manager");  
  2.  context = ActivityManagerService.main(factoryTest);  
  3.    
  4.   public static final Context main(int factoryTest) {  
  5.       AThread thr = new AThread();  
  6.       thr.start();  
  7.   
  8.       synchronized (thr) {  
  9.           while (thr.mService == null) {  
  10.               try {  
  11.                   thr.wait();  
  12.               } catch (InterruptedException e) {  
  13.               }  
  14.           }  
  15.       }  
  16.   
  17.       ActivityManagerService m = thr.mService;  
  18.       mSelf = m;  
  19.       ActivityThread at = ActivityThread.systemMain();  
  20.       mSystemThread = at;  
  21.       Context context = at.getSystemContext();  
  22.       context.setTheme(android.R.style.Theme_Holo);  
  23.       m.mContext = context;  
  24.       m.mFactoryTest = factoryTest;  
  25.       m.mMainStack = new ActivityStack(m, context, true);  
  26.         
  27.       m.mBatteryStatsService.publish(context);  
  28.       m.mUsageStatsService.publish(context);  
  29.         
  30.       synchronized (thr) {  
  31.           thr.mReady = true;  
  32.           thr.notifyAll();  
  33.       }  
  34.   
  35.       m.startRunning(nullnullnullnull);  
  36.         
  37.       return context;  
  38.   }  
  39.     


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


AThread 线程启动代码如下:

[java] view plaincopyprint?
  1. AThread thr = new AThread();  
  2. thr.start();  
  3.      
  4. static class AThread extends Thread {  
  5.     ActivityManagerService mService;  
  6.     boolean mReady = false;  
  7.   
  8.     public AThread() {  
  9.         super("ActivityManager");  
  10.     }  
  11.   
  12.     public void run() {  
  13.         Looper.prepare();  
  14.   
  15.         android.os.Process.setThreadPriority(  
  16.                 android.os.Process.THREAD_PRIORITY_FOREGROUND);  
  17.         android.os.Process.setCanSelfBackground(false);  
  18.   
  19.         ActivityManagerService m = new ActivityManagerService();  
  20.   
  21.         synchronized (this) {  
  22.             mService = m;  
  23.             notifyAll();  
  24.         }  
  25.   
  26.         synchronized (this) {  
  27.             while (!mReady) {  
  28.                 try {  
  29.                     wait();  
  30.                 } catch (InterruptedException e) {  
  31.                 }  
  32.             }  
  33.         }  
  34.     ...  
  35. }     

3、ActivityManagerService.systemReady


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

[java] view plaincopyprint?
  1. SystemService.java:  
  2.   
  3.     // We now tell the activity manager it is okay to run third party  
  4.     // code.  It will call back into us once it has gotten to the state  
  5.     // where third party code can really run (but before it has actually  
  6.     // started launching the initial applications), for us to complete our  
  7.     // initialization.  
  8.     ActivityManagerService.self().systemReady(new Runnable() {  
  9.         public void run() {  
  10.             Slog.i(TAG, "Making services ready");  

核心代码如下:

[java] view plaincopyprint?
  1. public final class ActivityManagerService extends ActivityManagerNative    
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {    
  3.     ......    
  4.     public void systemReady(final Runnable goingCallback) {    
  5.         ......    
  6.         synchronized (this) {    
  7.             ......    
  8.             mMainStack.resumeTopActivityLocked(null);    
  9.         }    
  10.     }    
  11.     ......    
  12. }  

4、ActivityStack.resumeTopActivityLocked

[java] view plaincopyprint?
  1. final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {  
  2.     // Find the first activity that is not finishing.  
  3.     ActivityRecord next = topRunningActivityLocked(null);  
  4.   
  5.     // Remember how we'll process this pause/resume situation, and ensure  
  6.     // that the state is reset however we wind up proceeding.  
  7.     final boolean userLeaving = mUserLeaving;  
  8.     mUserLeaving = false;  
  9.   
  10.     if (next == null) {  
  11.         // There are no more activities!  Let's just start up the  
  12.         // Launcher...  
  13.         if (mMainStack) {  
  14.             ActivityOptions.abort(options);  
  15.             return mService.startHomeActivityLocked(mCurrentUser);  
  16.         }  
  17.     }  
  18.       
  19.     ...  
  20.  }  

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

5、startHomeActivityLocked

[java] view plaincopyprint?
  1. boolean startHomeActivityLocked(int userId) {  
  2.     ...  
  3.     Intent intent = new Intent(  
  4.           mTopAction,  
  5.           mTopData != null ? Uri.parse(mTopData) : null);  
  6.       intent.setComponent(mTopComponent);  
  7.       if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {  
  8.           intent.addCategory(Intent.CATEGORY_HOME);  
  9.       }  
  10.       ActivityInfo aInfo =  
  11.           resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);  
  12.       if (aInfo != null) {  
  13.           intent.setComponent(new ComponentName(  
  14.                   aInfo.applicationInfo.packageName, aInfo.name));  
  15.           // Don't do this if the home app is currently being  
  16.           // instrumented.  
  17.           aInfo = new ActivityInfo(aInfo);  
  18.           aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);  
  19.           ProcessRecord app = getProcessRecordLocked(aInfo.processName,  
  20.                   aInfo.applicationInfo.uid);  
  21.           if (app == null || app.instrumentationClass == null) {  
  22.               intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);  
  23.               mMainStack.startActivityLocked(null, intent, null, aInfo,  
  24.                       nullnull0000nullfalsenull);  
  25.           }  
  26.       }  
  27.   
  28.       return true;  
  29.   }  
  30.     

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

[html] view plaincopyprint?
  1. <activity    
  2.         android:name="com.android.launcher2.Launcher"    
  3.         android:launchMode="singleTask"    
  4.         android:clearTaskOnLaunch="true"    
  5.         android:stateNotNeeded="true"    
  6.         android:theme="@style/Theme"    
  7.         android:screenOrientation="nosensor"    
  8.         android:windowSoftInputMode="stateUnspecified|adjustPan">    
  9.         <intent-filter>    
  10.             <action android:name="android.intent.action.MAIN" />    
  11.             <category android:name="android.intent.category.HOME" />    
  12.             <category android:name="android.intent.category.DEFAULT" />    
  13.             <category android:name="android.intent.category.MONKEY"/>    
  14.             </intent-filter>    
  15. </activity>  

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


[java] view plaincopyprint?
  1. /** 
  2.  * This activity is displayed when the system attempts to start an Intent for 
  3.  * which there is more than one matching activity, allowing the user to decide 
  4.  * which to go to.  It is not normally used directly by application developers. 
  5.  */  
  6. public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {  

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

[java] view plaincopyprint?
  1. mCurrentResolveList = mPm.queryIntentActivities(  
  2.         mIntent, PackageManager.MATCH_DEFAULT_ONLY);  

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


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


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


[java] view plaincopyprint?
  1. /** 
  2.  * WindowManagerPolicy implementation for the Android phone UI.  This 
  3.  * introduces a new method suffix, Lp, for an internal lock of the 
  4.  * PhoneWindowManager.  This is used to protect some internal state, and 
  5.  * can be acquired with either thw Lw and Li lock held, so has the restrictions 
  6.  * of both of those when held. 
  7.  */  
  8. public class PhoneWindowManager implements WindowManagerPolicy   

PhoneWindowManager 实现 Android UI


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


[java] view plaincopyprint?
  1. /** {@inheritDoc} */  
  2. @Override  
  3. public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {  
  4. ...  
  5.     // First we always handle the home key here, so applications  
  6.     // can never break it, although if keyguard is on, we do let  
  7.     // it handle it, because that gives us the correct 5 second  
  8.     // timeout.  
  9.     if (keyCode == KeyEvent.KEYCODE_HOME) {  
  10.         ...  
  11.         //单击home处理    
  12.       launchHomeFromHotKey();    
  13.     }  
  14.       
  15.     ...  
  16. }  

下面就是处理home键的功能


[java] view plaincopyprint?
  1. /** 
  2.  * A home key -> launch home action was detected.  Take the appropriate action 
  3.  * given the situation with the keyguard. 
  4.  */  
  5. void launchHomeFromHotKey() {  
  6.     if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {  
  7.         // don't launch home if keyguard showing  
  8.     } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {  
  9.         // when in keyguard restricted mode, must first verify unlock  
  10.         // before launching home  
  11.         mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {  
  12.             public void onKeyguardExitResult(boolean success) {  
  13.                 if (success) {  
  14.                     try {  
  15.                         ActivityManagerNative.getDefault().stopAppSwitches();  
  16.                     } catch (RemoteException e) {  
  17.                     }  
  18.                     sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);  
  19.                     startDockOrHome();  
  20.                 }  
  21.             }  
  22.         });  
  23.     } else {  
  24.         // no keyguard stuff to worry about, just launch home!  
  25.         try {  
  26.             ActivityManagerNative.getDefault().stopAppSwitches();  
  27.         } catch (RemoteException e) {  
  28.         }  
  29.         sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);  
  30.         startDockOrHome();  
  31.     }  
  32. }  

发送home intent出去:


[java] view plaincopyprint?
  1. void startDockOrHome() {  
  2.     // We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.  
  3.     mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);  
  4. }    

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


[java] view plaincopyprint?
  1. mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);  
  2. mHomeIntent.addCategory(Intent.CATEGORY_HOME);  
  3. mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK  
  4.         | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);         

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

0 0
原创粉丝点击