欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【Android】应用程序启动过程

程序员文章站 2022-03-31 08:35:45
1.Launcher请求ActivityManageService在 Android系统启动流程(四)Launcher启动过程与系统启动流程这篇文章我讲过Launcher启动后会将已安装应用程序的快捷图标显示到界面上,当我们点击应用程序的快捷图标时就会调用Launcher的startActivitySafely方法,如下所示。packages/apps/Launcher3/src/com/android/launcher3/Launcher.javajavapublic boolean...

1.Launcher请求ActivityManageService

Android系统启动流程(四)Launcher启动过程与系统启动流程这篇文章我讲过Launcher启动后会将已安装应用程序的快捷图标显示到界面上,当我们点击应用程序的快捷图标时就会调用Launcher的startActivitySafely方法,如下所示。
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

java

public boolean startActivitySafely(View v, Intent intent, Object tag) {
    ...
      try {
          success = startActivity(v, intent, tag);
      } catch (ActivityNotFoundException e) {
          Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
          Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
      }
      return success;
  }

startActivitySafely函数中主要就是调用了startActivity函数:
packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

java

private boolean startActivity(View v, Intent intent, Object tag) {
       intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//1
       try {
         ...
           if (user == null || user.equals(UserHandleCompat.myUserHandle())) {
               StrictMode.VmPolicy oldPolicy = StrictMode.getVmPolicy();
               try {            
                   StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll()
                           .penaltyLog().build());
                   startActivity(intent, optsBundle);//2
               } finally {
                   StrictMode.setVmPolicy(oldPolicy);
               }
           } else {
               launcherApps.startActivityForProfile(intent.getComponent(), user,
                       intent.getSourceBounds(), optsBundle);
           }
           return true;
       } catch (SecurityException e) {      
         ...
       }
       return false;
   }

在注释1处设置Flag为Intent.FLAG_ACTIVITY_NEW_TASK,这样根Activity会在新的任务栈中启动。在注释2处调用了startActivity函数:
frameworks/base/core/java/android/app/Activity.java

java

Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        startActivityForResult(intent, -1);
    }
}

startActivity会调用startActivityForResult函数,其中第二个参数为-1,表示Launcher不需要知道Activity启动的结果,startActivityForResult函数的代码如下所示。
frameworks/base/core/java/android/app/Activity.java

java

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
           @Nullable Bundle options) {
       if (mParent == null) {
           Instrumentation.ActivityResult ar =
               mInstrumentation.execStartActivity(
                   this, mMainThread.getApplicationThread(), mToken, this,
                   intent, requestCode, options);
        ...
       } else {
        ...
       }
   }

mParent是Activity类型的,表示当前Activity的父类。因为目前根Activity还没有创建出来,因此,mParent == null成立。接着调用Instrumentation的execStartActivity方法,Instrumentation主要用来监控应用程序和系统的交互,execStartActivity方法的代码如下所示。
frameworks/base/core/java/android/app/Instrumentation.java

java

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
      ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }

首先会调用ActivityManagerNative的getDefault来获取ActivityManageService(以后简称为AMS)的代理对象,接着调用它的startActivity方法。首先我们先来查看ActivityManagerNative的getDefault方法做了什么:
frameworks/base/core/java/android/app/ActivityManagerNative.java

java

  static public IActivityManager getDefault() {
        return gDefault.get();
    }

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");//1
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);//2
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
}

getDefault方法调用了gDefault的get方法,我们接着往下看,gDefault 是一个Singleton类。注释1处得到名为”activity”的Service引用,也就是IBinder类型的ActivityManagerService的引用。接着在注释2处将它封装成ActivityManagerProxy(以后简称为AMP)类型对象,并将它保存到gDefault中,此后调用ActivityManagerNative的getDefault方法就会直接获得AMS的代理AMP对象。
回到Instrumentation类的execStartActivity方法中,从上面得知就是调用AMP的startActivity,其中AMP是ActivityManagerNative的内部类,代码如下所示。
frameworks/base/core/java/android/app/ActivityManagerNative.java

java

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
           String resolvedType, IBinder resultTo, String resultWho, int requestCode,
           int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
       Parcel data = Parcel.obtain();
       Parcel reply = Parcel.obtain();
       data.writeInterfaceToken(IActivityManager.descriptor);
       data.writeStrongBinder(caller != null ? caller.asBinder() : null);
       data.writeString(callingPackage);
       intent.writeToParcel(data, 0);
       data.writeString(resolvedType);
       data.writeStrongBinder(resultTo);
       data.writeString(resultWho);
       data.writeInt(requestCode);
       data.writeInt(startFlags);
       if (profilerInfo != null) {
           data.writeInt(1);
           profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
       } else {
           data.writeInt(0);
       }
       if (options != null) {
           data.writeInt(1);
           options.writeToParcel(data, 0);
       } else {
           data.writeInt(0);
       }
       mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);//1
       reply.readException();
       int result = reply.readInt();
       reply.recycle();
       data.recycle();
       return result;
   }

首先会将传入的参数写入到Parcel类型的data中。在注释1处通过IBinder类型对象mRemote向AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务端AMS就会从Binder线程池中读取我们客户端发来的数据,最终会调用ActivityManagerNative的onTransact方法中执行,如下所示。
frameworks/base/core/java/android/app/ActivityManagerNative.java

java

@Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
           throws RemoteException {
       switch (code) {
       case START_ACTIVITY_TRANSACTION:
       {
   ...
           int result = startActivity(app, callingPackage, intent, resolvedType,
                   resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
           reply.writeNoException();
           reply.writeInt(result);
           return true;
       }
   }    

onTransact中会调用AMS的startActivity方法,如下所示。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

java

@Override
 public final int startActivity(IApplicationThread caller, String callingPackage,
         Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
         int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
     return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
             resultWho, requestCode, startFlags, profilerInfo, bOptions,
             UserHandle.getCallingUserId());
 }

为了便于理解,给出Launcher到AMS调用过程的时序图。
【Android】应用程序启动过程

文章作者: 刘望舒

本文地址:https://blog.csdn.net/xfb1989/article/details/109644946