图片 1

源码分析-Activity的启动流程

先前掌握Android的多语言完结很简短,能够在分裂的语言境况下采纳不相同的财富,就抓实对应的语言适配就好,但是一贯未曾实际应用过。
方今供销合作社的品类要用到多国语言切换,並且照旧和手提式有线电话机上系统安装里面包车型客车言语切换功用相似,于是就上网查了下资料。平时都以在应用类达成多国语言切换,那个是相当的轻易。而自身想切换整个种类的言语。由于Google从不把系统设置里面包车型大巴接口给开放出来,所以就只能去查看它的源码了~

1.前言

在前面Activity运维进程及分界面绘制流程深入分析开篇和Android
异步音讯管理机制两篇小说中详尽介绍了Activity运转过程中常用的七个知识点,binder机制甚至android异步新闻机制。在有了那一个基本功之后,我们毕竟能够进去activity运转流程的读书了。

笔者们知道android系统在开发银行进度中会实施这样的逻辑:
Zygote进程 –> SystemServer进度 –> 各个系统服务 –> 应用进度
应用程序是由Launcher运转起来的,而Launcher本人也是一个应用程序,其余的应用程序安装后,就能够Launcher的分界面上面世二个应和的Logo,点击那一个Logo时,Launcher就能够相应的应用程序运转起来。
(Zygote和Launcher下篇继续:)

android语言切换是在:

2.Activity运行相关进程介绍
  • zygote进程
    zygote从字面上来讲是受精卵的乐趣,用来孵化后代。在android源码中也确实是这些职能,zygote进度是java层全体程序进度的父进度,它是android空间程序的照蛋器,android空间有所程序都以由zygote进度运营的,我们平常和睦写的应用程序进度当然也是由zygote孵化,前面会有介绍。

  • system_server进程
    system_server进度是binder
    service所在的进度,该进程之中运营了非常多binder
    service。举例下文要提到到的ActivityManagerService及平时平常使用的WindowManagerService和PackageManagerService等binder服务。

  • 应用程序进度
    应用程序进度平时正是我们付出中动用所在的长河。activity实例运营在这里个进度。

图片 1

packages/apps/Settings/com/android/settings/LocalePicker.java
3.Activity起动具体流程

万般大家运维一个activity是经过Activity的startActivity方法,如下:

    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

直接调用Activity的八个参数的startActivity方法:

//options这个参数,Activity这个方法的注释是怎样启动activity,不去讨论
//平时调用的时候options为空
public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

无论是五个参数依旧八个参数的startActivityForResult方法都会调到activity的3个参数的startActivityForResult方法中,下边来看3个参数的startActivityForResult方法。

//requestCode启动activity是否需要返回值,默认为-1,不需要返回值
 public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
        if (mParent == null) {
            //通过Instrumentation的execStartActivity来启动activity
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            ......
        } else {
            ......
    }

在startActivityForResult中调用了Instrumentation的execStartActivity方法来一而再下一个手续。Instrumentation从字面上来看是仪器的乐趣,具体到程序中是处理activity的多少个工具类,activity的生命周期方法都以由Instrumentation这些仪器来决定,叁个进度中只用一个Instrumentation实例。再来看Instrumentation的execStartActivity方法:

/**
     * Execute a startActivity call made by the application.  The default 
     * implementation takes care of updating any active {@link ActivityMonitor}
     * objects and dispatches this call to the system activity manager; you can
     * override this to watch for the application to start an activity, and 
     * modify what happens when it does. 
     * @param who The Context from which the activity is being started.
     * @param contextThread The main thread of the Context from which the activity
     *                      is being started.
     * @param token Internal token identifying to the system who is starting 
     *              the activity; may be null.
     * @param target Which activity is performing the start (and thus receiving 
     *               any result); may be null if this call is not being made
     *               from an activity.
     * @param intent The actual Intent to start.
     * @param requestCode Identifier for this request's result; less than zero 
     *                    if the caller is not expecting a result.
     * @param options Addition options.
     *
     * @return To force the return of a particular result, return an 
     *         ActivityResult object containing the desired data; otherwise
     *         return null.  The default implementation always returns null.
     */
    public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ......
        try {
        ......
            //在此通过binder完成跨进程间的调用
           //通过ActivityManagerService来实现activity的启动
            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;
    }

本条情势中有多少个参数须求非常注意:第叁个参数平日代表原始的activity(通过A
activity 运营B
activity,则A是原始activity,B是目的activity)第二个参数是三个IBinder类型的ApplicationThread,提到IBinder,自然推断ApplicationThread是多个Binder类,下边来申明。
先看activity的startActivityForResult方法:

public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
      if (mParent == null) {
          Instrumentation.ActivityResult ar =
              //第二个参数通过mMainThread.getApplicationThread()
              mInstrumentation.execStartActivity(
                  this, mMainThread.getApplicationThread(), mToken, this,
                  intent, requestCode, options);
          ......
      } else {
          ......
  }

在代码中的注释处,大家看见ApplicationThread类型的参数是经过mMainThread.getApplicationThread(State of Qatar方法得到的,mMainThread在这里地是ActivityThread类型的变量。上边来瞅相仿ActivityThread的getApplicationThread方法:

public ApplicationThread getApplicationThread()
    {
        return mAppThread;
    }

简轻巧单的回到三个mAppThread变量,而:

final ApplicationThread mAppThread = new ApplicationThread();

所以execStartActivity第叁个参数实际上是二个ApplicationThread对象,
而:

private class ApplicationThread extends ApplicationThreadNative {
      ......
        public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }
    ......
}

从代码中得以看来ApplicationThread又是世袭ApplicationThreadNative的:

public abstract class ApplicationThreadNative extends Binder
        implements IApplicationThread {
        ......
}

从这里就能够观望来ApplicationThread实在是一个binder对象。
再再次来到Instrumentation的execStartActivity方法的参数中,后边的多少个参数就不再剖判了,execStartActivity方法注释上写得相比较清楚了。大家再来看这么些形式的落到实处:

try {
      ......
          //在此通过binder完成跨进程间的调用
         //通过ActivityManagerService来实现activity的启动
          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);
      }

先来看下ActivityManagerNative.getDefault(卡塔尔方法:

public abstract class ActivityManagerNative extends Binder implements IActivityManager{
       ......
 static public IActivityManager getDefault() {
        return gDefault.get();
    }
       ......
}

观察这里,再度估摸gDefault.get(State of Qatar获得的IActivityManager的对象实际是二个binder的代理对象。我们来证可瑞康(Karicare卡塔尔下主见是否正确。

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            //1.通过ServiceManager得到IActivityManager类型的binder对象
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            //2.通过IActivityManager类型的binder对象得到IActivityManager的代理对象
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

gDefault是二个Singleton类型的目的,Singleton是一个得以达成单例格局的工具类,通过Singleton的get方法能收获create方法的再次回到值,约等于说gDefault.get(State of Qatar方法能得到八个IActivityManager类型的目的。那几个IActivityManager对象到底是何许呢?先看上述代码的表明豆蔻梢头处:
在Activity运行进度及分界面绘制流程剖析开篇那篇作品中早就关系过ServiceManager,瑟维斯Manager是binder
service的管理类,担当管理运营的binder service,提供客商端访谈binder
service的接口。这里收获了彰显,应用进度经过ServiceManager获得了binder
service在根本驱动中的对象,然后经过注释二处转变为顾客端应用的binder代理对象,进而调用binder
service的艺术。那样就印证了ActivityManagerNative.getDefault(State of Qatar是三个binder代理对象,也落到实处了与binder
service建构连接,能够调用binder service的形式。那么些binder
service实际上是上文曾经关系过的system_server进度中的ActivityManagerService。
ActivityManagerService实际上末了管理activity生命周期之处,上文曾经提到过的Instrumentation也得以处理activity生命周期。那么她们有啥不相同啊?Instrumentation管理activity实际上也必要据守ActivityManagerService的命令。ActivityManager瑟维Stone过ApplicationThread将下令传达给Instrumentation,Instrumentation具体调用activity的生命周期方法。除却,ActivityManagerService还能够管住别的四大组件,所以ActivityManagerService这一个binder
service在android框架中占领主要的地位。
简易表明了ActivityManagerService作用之后,大家再跟着剖判与activity运营有关的法子。
在Instrumentation的execStartActivity方法中还也会有一点点亟需极度注意。在android创立binder连接有三种艺术,生龙活虎种是因此ServiceManager,如应用程序访谈ActivityManagerService。还会有黄金年代种是通过已经创立好的binder连接来建另多少个binder连接,如Instrumentation的execStartActivity方法中的ActivityManagerNative.getDefault(卡塔尔.startActivity中会将ApplicationThread类型whoThread传到ActivityManagerService中,然后ActivityManager瑟维Stone过ApplicationThread来调控应用程序。
进入ystem_server进度调用ActivityManagerService的startActivity方法:

@Override
        public int startActivity(IBinder whoThread, String callingPackage,
                Intent intent, String resolvedType, Bundle options) {
            ......
            IApplicationThread appThread;
            ......
                appThread = ApplicationThreadNative.asInterface(whoThread);
            ......
            return mStackSupervisor.startActivityMayWait(appThread, -1, callingPackage, intent,
                    resolvedType, null, null, null, null, 0, 0, null, null,
                    null, options, callingUser, null, tr);
        }

将应用程序传过来的ApplicationThread调换成binder代理对象,以便ActivityManager瑟维Stone过那些代理对象调整应用程序。然后调用ActivityStackSupervisor的startActivityMayWait继续下一步操作。在深入分析下一步操作早前,大家先掌握下下面那多少个类的效果与利益:

  • ActivityStack:Activity在ActivityManagerService的栈管理,用来记录已经运营的Activity的次第关系,状态音讯等。通过ActivityStack决定是或不是供给运转新的进程。
  • ActivityRecord:应用程序每便运维二个Actvity会有一个一呼百应的ActivityRecord对象,记录Activity的状态以至其余的军事拘禁新闻。
  • TaskRecord:Task记录音信,四个Task恐怕有多少个ActivityRecord,然而三个ActivityRecord只好归于三个TaskRecord,与activity运转形式相关。
    有了这些根基之后再跟着深入分析:

 final int startActivityMayWait(IApplicationThread caller, int callingUid,
            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, String profileFile,
            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
            Bundle options, int userId) {
    int res = startActivityLocked(caller, intent, resolvedType,
                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
                    callingPackage, startFlags, options, componentSpecified, null);
}

世襲调用ActivityStackSupervisor的startActivityLocked方法:

final int startActivityLocked(IApplicationThread caller,
            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
            String resultWho, int requestCode,
            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
            boolean componentSpecified, ActivityRecord[] outActivity) {
        ......
        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration,
                resultRecord, resultWho, requestCode, componentSpecified, this);
        ......
        err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
        ......
}

在startActivityLocked方法里,对传过来的参数做一些校验,然后创制ActivityRecord对象,再调用startActivityUncheckedLocked方法运营Activity:

final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
            boolean doResume, Bundle options, TaskRecord inTask) {

            ......
            targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
            ......

             return ActivityManager.START_SUCCESS;
            }

targetStack指ActivityStack,然后调用ActivityStack的startActivityLocked方法:

final void startActivityLocked(ActivityRecord r, boolean newTask,
            boolean doResume, boolean keepCurTransition, Bundle options) {
         ......
         if (doResume) {
            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
        }
    }

透过黄金时代连串算法找寻栈顶Activity,然后调用ActivityStackSupervisor的resumeTopActivitiesLocked展现栈顶的activity:

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = getFocusedStack();
        }
        if (isFrontStack(targetStack)) {
            result = targetStack.resumeTopActivityLocked(target, targetOptions);
        }

          ......

        return result;
    }

紧接着调用ActivityStack的resumeTopActivityLocked方法呈现栈顶的activity:

final boolean resumeTopActivityLocked(ActivityRecord prev) {
        ......
      if (next.app != null && next.app.thread !=null){
        ......
    }else{
        ......
    startSpecificActivityLocked(next, true, true);
    }
        ......
 }

因为使用尚未运营过,所以调用ActivityStack的startSpecificActivityLocked方法运营应用:

private final void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid);
        ......

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false);
    }

然后调用ActivityManagerService的startProcessLocked方法运维应用:

final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
                hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */);
    }

末尾调用到

private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
    ......
  try {
    ......
  //Zygote孵化dalvik应用进程后,会执行android.app.ActivityThread类的main方法
      Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
              app.processName, uid, uid, gids, debugFlags, mountExternal,
              app.info.targetSdkVersion, app.info.seinfo, null);
      ......    
  } catch (RuntimeException e) {
      ......
  }
}

接下来调用Process的start方法开启三个历程:

public static final ProcessStartResult start(final String processClass,
                              final String niceName,
                              int uid, int gid, int[] gids,
                              int debugFlags, int mountExternal,
                              int targetSdkVersion,
                              String seInfo,
                              String[] zygoteArgs) {
 try{
  //通过socket方式通过Zygote进程孵化一个应用进程                              
  startViaZygote(processClass, niceName, uid, gid, gids,
                    debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
  }catch (ZygoteStartFailedEx ex) {
   ......
  }                    
}

接下来以socket格局经过Zygote进度孵化八个用到进度并施行应用进程的main方法.

1355546884_8512.jpg

的updateLocale(卡塔尔国函数中调用,源码如下:

4.小结

到此就从activity的startActivity方法开首深入分析到一个新的接受进度的main方法试行的大致流程。下篇文章会从应用程序的main方法最早剖析acticity运转进度中生命周期函数实行的历程。

src/main/java/com/android/launcher2/Launcher.java
Launcher.startActivitySafely

/** * Requests the system to update the system locale. Note that the system looks halted for a while during the Locale migration, so the caller need to take care of it. */  
    public static void updateLocale(Locale locale) {  
        try {  
            IActivityManager am = ActivityManagerNative.getDefault();  
            Configuration config = am.getConfiguration();  

            config.locale = locale;  

            // indicate this isn't some passing default - the user wants this remembered 
            config.userSetLocale = true;  

            am.updateConfiguration(config);  
            // Trigger the dirty bit for the Settings Provider. 
            BackupManager.dataChanged("com.android.providers.settings");  
        } catch (RemoteException e) {  
            // Intentionally left blank 
        }  
    }
 /**
     * Launches the intent referred by the clicked shortcut.
     *
     * @param v The view representing the clicked shortcut.
     */
    public void onClick(View v) {
        // Make sure that rogue clicks don't get through while allapps is launching, or after the
        // view has detached (it's possible for this to happen if the view is removed mid touch).
        ....
        Object tag = v.getTag();
        if (tag instanceof ShortcutInfo) {
            // Open shortcut
            final Intent intent = ((ShortcutInfo) tag).intent;
            int[] pos = new int[2];
            v.getLocationOnScreen(pos);
            intent.setSourceBounds(new Rect(pos[0], pos[1],
                    pos[0] + v.getWidth(), pos[1] + v.getHeight()));
            //点击shortcut进入app
            boolean success = startActivitySafely(v, intent, tag);
           ....
        } else if (tag instanceof FolderInfo) {
            ....
        } else if (v == mAllAppsButton) {
            ....
        }
    }

     boolean startActivitySafely(View v, Intent intent, Object tag) {
        boolean success = false;
        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;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    boolean startActivity(View v, Intent intent, Object tag) {
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

        try {
            // Only launch using the new animation if the shortcut has not opted out (this is a
            // private contract between launcher and may be ignored in the future).
            boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
            UserHandle user = (UserHandle) intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
            LauncherApps launcherApps = (LauncherApps)
                    this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
            if (useLaunchAnimation) {
                ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
                        v.getMeasuredWidth(), v.getMeasuredHeight());
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    // Could be launching some bookkeeping activity
                    startActivity(intent, opts.toBundle());
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(),
                            opts.toBundle());
                }
            } else {
                if (user == null || user.equals(android.os.Process.myUserHandle())) {
                    startActivity(intent);
                } else {
                    launcherApps.startMainActivity(intent.getComponent(), user,
                            intent.getSourceBounds(), null);
                }
            }
            return true;
        } catch (SecurityException e) {
            Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
            Log.e(TAG, "Launcher does not have the permission to launch " + intent +
                    ". Make sure to create a MAIN intent-filter for the corresponding activity " +
                    "or use the exported attribute for this activity. "
                    + "tag=" + tag + " intent=" + intent, e);
        }
        return false;
    }

从注释能够看见, 只要本地local改动就能够调用该函数.
查看ActivityManagerNative的getDefault(卡塔尔能够见到,
该函数重返的是长间隔服务目的ActivityManagerServices.java在地点的一个代理.
最后调用的是ActivityManagerService.java中的updateConfiguration(卡塔尔(قطر‎函数.

corejavaandroidcontentpmLauncherApps.java

public void updateConfiguration(Configuration values) {  
        enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,  
                "updateConfiguration()");  

        synchronized(this) {  
            if (values == null && mWindowManager != null) {  
                // sentinel: fetch the current configuration from the window manager 
                values = mWindowManager.computeNewConfiguration();  
            }  

            if (mWindowManager != null) {  
                mProcessList.applyDisplaySize(mWindowManager);  
            }  

            final long origId = Binder.clearCallingIdentity();  
            if (values != null) {  
                Settings.System.clearConfiguration(values);  
            }  
            updateConfigurationLocked(values, null, false, false);  
            Binder.restoreCallingIdentity(origId);  
        }  
    }
/**
     * Starts a Main activity in the specified profile.
     *
     * @param component The ComponentName of the activity to launch
     * @param user The UserHandle of the profile
     * @param sourceBounds The Rect containing the source bounds of the clicked icon
     * @param opts Options to pass to startActivity
     */
    public void startMainActivity(ComponentName component, UserHandle user, Rect sourceBounds,
            Bundle opts) {
        logErrorForInvalidProfileAccess(user);
        if (DEBUG) {
            Log.i(TAG, "StartMainActivity " + component + " " + user.getIdentifier());
        }
        try {
            mService.startActivityAsUser(mContext.getPackageName(),
                    component, sourceBounds, opts, user);
        } catch (RemoteException re) {
            throw re.rethrowFromSystemServer();
        }
    }

该函数, 首先进行的是权力的校验. 然后调用updateConfigurationLocked(State of Qatar函数.

从Launcher类里能够见见运维activity
1:通过startActivity(Launcher继承Activity,直接调Activity的方法);

/** * Do either or both things: (1) change the current configuration, and (2) * make sure the given activity is running with the (now) current * configuration. Returns true if the activity has been left running, or * false if <var>starting</var> is being destroyed to match the new * configuration. * @param persistent TODO */  
    public boolean updateConfigurationLocked(Configuration values,  
            ActivityRecord starting, boolean persistent, boolean initLocale) {  
        int changes = 0;  

        boolean kept = true;  

        if (values != null) {  
            Configuration newConfig = new Configuration(mConfiguration);  
            changes = newConfig.updateFrom(values);  
            if (changes != 0) {  
                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {  
                    Slog.i(TAG, "Updating configuration to: " + values);  
                }  

                EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);  

                if (values.locale != null && !initLocale) {  
                    saveLocaleLocked(values.locale,   
                                     !values.locale.equals(mConfiguration.locale),  
                                     values.userSetLocale, values.simSetLocale);  
                }  

                mConfigurationSeq++;  
                if (mConfigurationSeq <= 0) {  
                    mConfigurationSeq = 1;  
                }  
                newConfig.seq = mConfigurationSeq;  
                mConfiguration = newConfig;  
                Slog.i(TAG, "Config changed: " + newConfig);  

                final Configuration configCopy = new Configuration(mConfiguration);  

                AttributeCache ac = AttributeCache.instance();  
                if (ac != null) {  
                    ac.updateConfiguration(configCopy);  
                }  

                // Make sure all resources in our process are updated 
                // right now, so that anyone who is going to retrieve 
                // resource values after we return will be sure to get 
                // the new ones. This is especially important during 
                // boot, where the first config change needs to guarantee 
                // all resources have that config before following boot 
                // code is executed. 
                mSystemThread.applyConfigurationToResources(configCopy);  

                if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {  
                    Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);  
                    msg.obj = new Configuration(configCopy);  
                    mHandler.sendMessage(msg);  
                }  

                for (int i=mLruProcesses.size()-1; i>=0; i--) {  
                    ProcessRecord app = mLruProcesses.get(i);  
                    try {  
                        if (app.thread != null) {  
                            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "  
                                    + app.processName + " new config " + mConfiguration);  
                            app.thread.scheduleConfigurationChanged(configCopy);  
                        }  
                    } catch (Exception e) {  
                    }  
                }  
                Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);  
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY  
                        | Intent.FLAG_RECEIVER_REPLACE_PENDING);  
                broadcastIntentLocked(null, null, intent, null, null, 0, null, null,  
                        null, false, false, MY_PID, Process.SYSTEM_UID);  
                if ((changes&ActivityInfo.CONFIG_LOCALE) != 0) {  
                    broadcastIntentLocked(null, null,  
                            new Intent(Intent.ACTION_LOCALE_CHANGED),  
                            null, null, 0, null, null,  
                            null, false, false, MY_PID, Process.SYSTEM_UID);  
                }  

            }  
        }  

        if (changes != 0 && starting == null) {  
            // If the configuration changed, and the caller is not already 
            // in the process of starting an activity, then find the top 
            // activity to check if its configuration needs to change. 
            starting = mMainStack.topRunningActivityLocked(null);  
        }  

        if (starting != null) {  
            kept = mMainStack.ensureActivityConfigurationLocked(starting, changes);  
            // And we need to make sure at this point that all other activities 
            // are made visible with the correct configuration. 
            mMainStack.ensureActivitiesVisibleLocked(starting, changes);  
        }  

        if (values != null && mWindowManager != null) {  
            mWindowManager.setNewConfiguration(mConfiguration);  
        }  

        return kept;  
    }
    @Override
    public void startActivity(Intent intent) {
        this.startActivity(intent, null);
    }

    @Override
    public void startActivity(Intent intent, @Nullable Bundle options) {
        if (options != null) {
            startActivityForResult(intent, -1, options);
        } else {
            // Note we want to go through this call for compatibility with
            // applications that may have overridden the method.
            startActivityForResult(intent, -1);
        }
    }

全数语言切换就在这里个函数中产生. 咋大器晚成看犹如没认为到到该函数做了怎样事情.
大家首先来看注释: Do either or both things: (1卡塔尔(قطر‎ change the current
configuration, and (2卡塔尔

corejavaandroidappActivity.java

make sure the given activity is running with the (nowState of Qatar current.
configuration差不离意思是: 这一个函数做了两件事情. (1卡塔尔国.
改换近日的configuration.
意思便是让退换的configuration更新到当下configuration. (2卡塔尔确定保障全数正在运行的activity都能更新退换后的configuration.(这一点是关键.State of Qatar .
大家遵照那个思路看看android是如何翻新configuration. 查看代码 , 首先看见这些函数首先推断values是或不是为空, 这里values肯定不为空的, 然后changes =
newConfig.updateFrom(valuesState of Qatar; 大家看看updateFrom做了何等操作。

 public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
        if (mParent == null) {
            options = transferSpringboardActivityOptions(options);
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
           ....
    }
/** 
     * Copy the fields from delta into this Configuration object, keeping 
     * track of which ones have changed.  Any undefined fields in 
     * <var>delta</var> are ignored and not copied in to the current 
     * Configuration. 
     * @return Returns a bit mask of the changed fields, as per 
     * {@link #diff}. 
     */  
    public int updateFrom(Configuration delta) {  
        int changed = 0;  
        ...  
        if (delta.locale != null   && (locale == null || !locale.equals(delta.locale))) {  
            changed |= ActivityInfo.CONFIG_LOCALE;  
            locale = delta.locale != null   ? (Locale) delta.locale.clone() : null;  
            textLayoutDirection = LocaleUtil.getLayoutDirectionFromLocale(locale);  
        }  
        if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))  
        {  
            userSetLocale = true;  
            changed |= ActivityInfo.CONFIG_LOCALE;  
        }  
        ...  
        return changed;  
    }

mMainThread它的连串是ActivityThread,上边看Instrumentation那么些类如哪管理execStartActivity的
core/java/android/app/Instrumentation.java,用来监督应用程序和系统的相互影响

因为言语退换了, 那么 (!locale.equals(delta.localeState of Qatar卡塔尔 是true. changed
大于0, 然后return changed.
回到ActivityManagerService.java的updateConfigurationLocked函数,
因为changed不为0 , 所以走if这几个流程. 继续看代码。

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        ....
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
        for (int i=mLruProcesses.size()-1; i>=0; i--) {  
                    ProcessRecord app = mLruProcesses.get(i);  
                    try {  
                        if (app.thread != null) {  
                            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "  
                                    + app.processName + " new config " + mConfiguration);  
                            app.thread.scheduleConfigurationChanged(configCopy);  
                        }  
                    } catch (Exception e) {  
                    }  
                }

也正是ActivityManager做了拍卖,—->进去ActivityManager那几个类看一下

第风度翩翩看见的是mLurProcesses 是ArrayList类型. LRU : Least Recently
Used保存全体运维过的进度. ProcessRecord进程类,
多个apk文件运转时会对应多个进度. app.thread.
此处的thread代表的是ApplicationThreadNative.java类型.
然后调用其scheduleConfigurationChanged(State of Qatar; 查看该函数。

    public static IActivityManager getService() {
         return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
    public final void scheduleConfigurationChanged(Configuration config)  
            throws RemoteException {  
        Parcel data = Parcel.obtain(); 
        data.writeInterfaceToken(IApplicationThread.descriptor); 
        config.writeToParcel(data, 0); 
        mRemote.transact(SCHEDULE_CONFIGURATION_CHANGED_TRANSACTION, data, null, 
                IBinder.FLAG_ONEWAY);  
        data.recycle(); 
    }

获得到了ActivityServiceManager对象:调用startActivityAsUser方法

又是经过binder调用, 所以 , binder在android中是二个很主要的概念.
此处远程调用的是ActivityThread.java中的私有内部内ApplicationThread。

 @Override
    public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
        // TODO: Switch to user app stacks here.
        return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
    }
    private class ApplicationThread extends ApplicationThreadNative {  
        private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s";  
        private static final String ONE_COUNT_COLUMN = "%21s %8d";  
        private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";  
        private static final String TWO_COUNT_COLUMNS_DB = "%21s %8d %21s %8d";  
        private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";  

        ...  
        public void scheduleConfigurationChanged(Configuration config) {  
            updatePendingConfiguration(config);  
            queueOrSendMessage(H.CONFIGURATION_CHANGED, config);  
        }  
        ...  
}

此处只是简短地将操作转载给成员变量mActivityStarter的startActivityMayWait函数,这里的mActivityStarter的类型为ActivityStarter。
frameworks/base/services/java/com/android/server/am/ActivityStarter.java的startActivityMayWait函数:

而ApplicationThread中的handler的CONFIGURATION_CHANGED是调用handleConfigurationChanged()。

final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,  
         String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,  
         IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,  
         IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,  
         String callingPackage, int realCallingPid, int realCallingUid, int startFlags,  
         ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,  
         ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,  
         TaskRecord inTask) {  
         int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,  
                 aInfo, rInfo, voiceSession, voiceInteractor,  
                 resultTo, resultWho, requestCode, callingPid,  
                 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,  
                 options, ignoreTargetSecurity, componentSpecified, outRecord, container,  
                 inTask);  
        ....
}  
    final void handleConfigurationChanged(Configuration config, CompatibilityInfo compat) {  

       ArrayList<ComponentCallbacks2> callbacks = null;  

    ...         ...  
       applyConfigurationToResourcesLocked(config, compat);  

       ...  

       callbacks = collectComponentCallbacksLocked(false, config);  
       ...  

       if (callbacks != null) {  
           final int N = callbacks.size();  
           for (int i=0; i<N; i++) {  
               performConfigurationChanged(callbacks.get(i), config);  
           }  
       }

随着又进来startActivityLocked方法:

以此函数首先是调用applyConfigurationToResources洛克d(卡塔尔国.
看函数名大致能够猜度到:
将configuration应用到resources.这里configuration改换的是local 本地语言.
这而resources财富蕴克罗地亚语言包吗?

final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,  
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,  
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,  
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,  
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,  
        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,  
        ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,  
        TaskRecord inTask) {  
        doPendingActivityLaunchesLocked(false);  
....
final void doPendingActivityLaunchesLocked(boolean doResume) {  
    while (!mPendingActivityLaunches.isEmpty()) {  
        final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);  
        final boolean resume = doResume && mPendingActivityLaunches.isEmpty();  
        try {  
            final int result = startActivityUnchecked(  
                    pal.r, pal.sourceRecord, null, null, pal.startFlags, resume, null, null);  
           ....
    }  
}  
startActivityUnchecked函数中:
 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,  
         IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,  
         int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {  
    mSupervisor.resumeFocusedStackTopActivityLocked();  
}  
    final boolean applyConfigurationToResourcesLocked(Configuration config,  
            CompatibilityInfo compat) {  

        int changes = mResConfiguration.updateFrom(config);  
        DisplayMetrics dm = getDisplayMetricsLocked(null, true);  

        if (compat != null && (mResCompatibilityInfo == null ||  
                !mResCompatibilityInfo.equals(compat))) {  
            mResCompatibilityInfo = compat;  
            changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT  
                    | ActivityInfo.CONFIG_SCREEN_SIZE  
                    | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;  
        }  

        ...  

        Resources.updateSystemConfiguration(config, dm, compat);  

        ...  

        Iterator<WeakReference<Resources>> it =  
            mActiveResources.values().iterator();  
        while (it.hasNext()) {  
            WeakReference<Resources> v = it.next();  
            Resources r = v.get();  
            if (r != null) {  
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "  
                        + r + " config to: " + config);  
                r.updateConfiguration(config, dm, compat);  
                //Slog.i(TAG, "Updated app resources " + v.getKey()  
                //        + " " + r + ": " + r.getConfiguration());  
            } else {  
                //Slog.i(TAG, "Removing old resources " + v.getKey());  
                it.remove();  
            }  
        }  

        return changes != 0;  
    }

察觉转到了ActivityStackSupervisor.java中的resumeFocusedStackTopActivityLocked函数:

Resources.updateSystemConfiguration(卡塔尔国灭绝生机勃勃部分系统能源,
何况将config更新到Resources, 而Resources包蕴了三个AssetManager对象,
该对象的中坚完结是在AssetManager.cpp中达成的.
然后循环清空mActivityResources能源.
再再次回到handleConfigurationChanged(卡塔尔(قطر‎函数,
实践完updateSystemConfiguration后, 会循环该进程的有着activity:

boolean resumeFocusedStackTopActivityLocked(  
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {  
    if (targetStack != null && isFocusedStack(targetStack)) {  
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);  
    }  
if (callbacks != null) {   
final int N = callbacks.size();
        for (int i=0; i<N; i++) {
            performConfigurationChanged(callbacks.get(i), config);
        }
    }

终于:进入ActivityStack.java :)
哈哈哈

再来看performConfigurationChanged的实现:

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {  
   //暂停启动Activity的那个Activity
    startPausingLocked(userLeaving, false, true, dontWaitForPause);  
    mStackSupervisor.startSpecificActivityLocked(next, true, true);  
}  
private final void performConfigurationChanged(  
            ComponentCallbacks2 cb, Configuration config) {  
        // Only for Activity objects, check that they actually call up to their 
        // superclass implementation. ComponentCallbacks2 is an interface, so 
        // we check the runtime type and act accordingly. 
        Activity activity = (cb instanceof Activity) ? (Activity) cb : null;  
        if (activity != null) {  
            activity.mCalled = false;  
        }  

        boolean shouldChangeConfig = false;  
        if ((activity == null) || (activity.mCurrentConfig == null)) {  
            shouldChangeConfig = true;  
        } else {  

            // If the new config is the same as the config this Activity 
            // is already running with then don't bother calling 
            // onConfigurationChanged 
            int diff = activity.mCurrentConfig.diff(config);  
            if (diff != 0) {  
                // If this activity doesn't handle any of the config changes 
                // then don't bother calling onConfigurationChanged as we're 
                // going to destroy it. 
                if ((~activity.mActivityInfo.getRealConfigChanged() & diff) == 0) {  
                    shouldChangeConfig = true;  
                }  
            }  
        }  

        if (DEBUG_CONFIGURATION) Slog.v(TAG, "Config callback " + cb  
                + ": shouldChangeConfig=" + shouldChangeConfig);  
        if (shouldChangeConfig) {  
            cb.onConfigurationChanged(config);  

            if (activity != null) {  
                if (!activity.mCalled) {  
                    throw new SuperNotCalledException(  
                            "Activity " + activity.getLocalClassName() +  
                        " did not call through to super.onConfigurationChanged()");  
                }  
                activity.mConfigChangeFlags = 0;  
                activity.mCurrentConfig = new Configuration(config);  
            }  
        }  
    }

然而
。。。又回到ActivityStackSupervisor中的startSpecificActivityLocked函数:

该函数判别configuration是还是不是改造, 借使退换那么shouldChangeConfig为true.
然后调用activity的onConfigurationChange(config卡塔尔;

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.getStack().setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                //因为启动的Activity不是应用的第一个Activity所以上面app的信息不为null,进入realStartActivityLocked中:
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }
/** 
    * Called by the system when the device configuration changes while your 
    * activity is running.  Note that this will <em>only</em> be called if 
    * you have selected configurations you would like to handle with the 
    * {@link android.R.attr#configChanges} attribute in your manifest. If 
    * any configuration change occurs that is not selected to be reported 
    * by that attribute, then instead of reporting it the system will stop 
    * and restart the activity (to have it launched with the new 
    * configuration). 
    *  
    * <p>At the time that this function has been called, your Resources 
    * object will have been updated to return resource values matching the 
    * new configuration. 
    *  
    * @param newConfig The new device configuration. 
    */  
   public void onConfigurationChanged(Configuration newConfig) {  
       mCalled = true;  

       mFragments.dispatchConfigurationChanged(newConfig);  

       if (mWindow != null) {  
           // Pass the configuration changed event to the window  
           mWindow.onConfigurationChanged(newConfig);  
       }  

       if (mActionBar != null) {  
           // Do this last; the action bar will need to access  
           // view changes from above.  
           mActionBar.onConfigurationChanged(newConfig);  
       }  
   }

realStartActivityLocked

查看注释, 大约意思是: 倘诺你的activity运营 ,
设备信息有变动(即configuration改动State of Qatar时由系统调用.
要是你在manifest.xml中配置了configChnages属性则代表有您本人来管理configuration
change. 不然就重启当前这么些activity. 而重启以前, 旧的resources已经被清空,
那么就能装载新的能源, 整个进程就完成了语言切换后 ,
能够让具备app使用新的言语。

 final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
            boolean andResume, boolean checkConfig) throws RemoteException {
        ....
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, !andResume,
                        mService.isNextTransitionForward(), profilerInfo);
        ....

上边那些正是对Android
系统之中的言语切换进行了源码剖判,就先解析到这里;有个别东西我亦不是很看懂,技艺轻便~

最重要看运转,别的忽视:
app.thread是长途 IApplicationThread 的
binder代理,那个代理是ApplicationThreadProxy类型,调用scheduleLaunchActivity会进入stub达成类(ApplicationThread)里面:
ActivityThread.ApplicationThread — >

 public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
             ActivityInfo info, Configuration curConfig, Configuration overrideConfig,  
             CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,  
             int procState, Bundle state, PersistableBundle persistentState,  
             List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,  
             boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {  
.  
.  
         sendMessage(H.LAUNCH_ACTIVITY, r);  
     }  

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {  
    mH.sendMessage(msg);  
}  

这里的mH是handler发音讯让它切换来主线程管理:
也就是ActivityThread的H

 private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        public static final int PAUSE_ACTIVITY_FINISHING= 102;
        public static final int STOP_ACTIVITY_SHOW      = 103;
        public static final int STOP_ACTIVITY_HIDE      = 104;
        public static final int SHOW_WINDOW             = 105;
        public static final int HIDE_WINDOW             = 106;
        public static final int RESUME_ACTIVITY         = 107;
        ....   
        //H.handleMessage函数
         public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
      ....

ActivityThread.handleLaunchActivity函数

 private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        if (r.profilerInfo != null) {
            mProfiler.setProfiler(r.profilerInfo);
            mProfiler.startProfiling();
        }

        // Make sure we are running with the most recent config.
        handleConfigurationChanged(null, null);

        if (localLOGV) Slog.v(
            TAG, "Handling launch of " + r);

        // Initialize before creating the activity
        if (!ThreadedRenderer.sRendererDisabled) {
            GraphicsEnvironment.earlyInitEGL();
        }
        //初始化window,上篇说到过
        WindowManagerGlobal.initialize();
        //开启activity,
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            ....
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            ....
            }
        } else {
            // If there was an error, for any reason, tell the activity manager to stop us.
            try {
                ActivityManager.getService()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

handleResumeActivity:创造视图

final void handleResumeActivity(IBinder token,
            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
        ActivityClientRecord r = mActivities.get(token);
        if (!checkAndUpdateLifecycleSeq(seq, r, "resumeActivity")) {
            return;
        }

        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        r = performResumeActivity(token, clearHide, reason);

        if (r != null) {
            final Activity a = r.activity;

            if (localLOGV) Slog.v(
                TAG, "Resume " + r + " started activity: " +
                a.mStartedActivity + ", hideForNow: " + r.hideForNow
                + ", finished: " + a.mFinished);

            final int forwardBit = isForward ?
                    WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

            // If the window hasn't yet been added to the window manager,
            // and this guy didn't finish itself or start another activity,
            // then go ahead and add the window.
            boolean willBeVisible = !a.mStartedActivity;
            if (!willBeVisible) {
                try {
                    willBeVisible = ActivityManager.getService().willActivityBeVisible(
                            a.getActivityToken());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (r.mPreserveWindow) {
                    a.mWindowAdded = true;
                    r.mPreserveWindow = false;
                    // Normally the ViewRoot sets up callbacks with the Activity
                    // in addView->ViewRootImpl#setView. If we are instead reusing
                    // the decor view we have to notify the view root that the
                    // callbacks may have changed.
                    ViewRootImpl impl = decor.getViewRootImpl();
                    if (impl != null) {
                        impl.notifyChildRebuilt();
                    }
                }
                if (a.mVisibleFromClient) {
                    if (!a.mWindowAdded) {
                        a.mWindowAdded = true;
                        wm.addView(decor, l);
                    } else {
                        // The activity will get a callback for this {@link LayoutParams} change
                        // earlier. However, at that time the decor will not be set (this is set
                        // in this method), so no action will be taken. This call ensures the
                        // callback occurs with the decor set.
                        a.onWindowAttributesChanged(l);
                    }
                }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
            } else if (!willBeVisible) {
                if (localLOGV) Slog.v(
                    TAG, "Launch " + r + " mStartedActivity set");
                r.hideForNow = true;
            }

            // Get rid of anything left hanging around.
            cleanUpPendingRemoveWindows(r, false /* force */);

            // The window is now visible if it has been added, we are not
            // simply finishing, and we are not starting another activity.
            if (!r.activity.mFinished && willBeVisible
                    && r.activity.mDecor != null && !r.hideForNow) {
                if (r.newConfig != null) {
                    performConfigurationChangedForActivity(r, r.newConfig);
                    if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity "
                            + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig);
                    r.newConfig = null;
                }
                if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward="
                        + isForward);
                WindowManager.LayoutParams l = r.window.getAttributes();
                if ((l.softInputMode
                        & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
                        != forwardBit) {
                    l.softInputMode = (l.softInputMode
                            & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
                            | forwardBit;
                    if (r.activity.mVisibleFromClient) {
                        ViewManager wm = a.getWindowManager();
                        View decor = r.window.getDecorView();
                        wm.updateViewLayout(decor, l);
                    }
                }

                r.activity.mVisibleFromServer = true;
                mNumVisibleActivities++;
                if (r.activity.mVisibleFromClient) {
                    r.activity.makeVisible();
                }
            }

            if (!r.onlyLocalRequest) {
                r.nextIdle = mNewActivities;
                mNewActivities = r;
                if (localLOGV) Slog.v(
                    TAG, "Scheduling idle handler for " + r);
                Looper.myQueue().addIdleHandler(new Idler());
            }
            r.onlyLocalRequest = false;

            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                    ActivityManager.getService().activityResumed(token);
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            }

        } else {
            // If an exception was thrown when trying to resume, then
            // just end this activity.
            try {
                ActivityManager.getService()
                    .finishActivity(token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

事后是上篇聊过的了,hhh
performResumeActivity;
wm.addView(decor, l);

2:LauncherApps.java—-ILauncherApps—-LauncherAppsService三者使用aidl动态代理的款型(那总格局随后再聊),所以那边的startMainActivity(卡塔尔方法其实是调用的LauncherApps瑟维斯中的startActivityAsUser(卡塔尔方法

frameworks/base/services/core/java/com/android/server/pm/LauncherAppsService.java

@Override
        public void startActivityAsUser(String callingPackage,
                ComponentName component, Rect sourceBounds,
                Bundle opts, UserHandle user) throws RemoteException {
            if (!canAccessProfile(callingPackage, user, "Cannot start activity")) {
                return;
            }
            if (!isUserEnabled(user)) {
                throw new IllegalStateException("Cannot start activity for disabled profile "  + user);
            }
            //初始化launchIntent
            Intent launchIntent = new Intent(Intent.ACTION_MAIN);
            launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            launchIntent.setSourceBounds(sourceBounds);
            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                    | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            launchIntent.setPackage(component.getPackageName());

            final int callingUid = injectBinderCallingUid();
            long ident = Binder.clearCallingIdentity();
            try {
                final PackageManagerInternal pmInt =
                        LocalServices.getService(PackageManagerInternal.class);
                //通过PackageManager得到ActivityInfo信息
                ActivityInfo info = pmInt.getActivityInfo(component,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                        callingUid, user.getIdentifier());
                if (!info.exported) {
                    throw new SecurityException("Cannot launch non-exported components "
                            + component);
                }

                // Check that the component actually has Intent.CATEGORY_LAUCNCHER
                // as calling startActivityAsUser ignores the category and just
                // resolves based on the component if present.
                List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
                        PackageManager.MATCH_DIRECT_BOOT_AWARE
                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                        callingUid, user.getIdentifier());
                final int size = apps.size();
                for (int i = 0; i < size; ++i) {
                    ActivityInfo activityInfo = apps.get(i).activityInfo;
                    if (activityInfo.packageName.equals(component.getPackageName()) &&
                            activityInfo.name.equals(component.getClassName())) {
                        // Found an activity with category launcher that matches
                        // this component so ok to launch.
                        launchIntent.setComponent(component);
                        mContext.startActivityAsUser(launchIntent, opts, user);
                        return;
                    }
                }
                throw new SecurityException("Attempt to launch activity without "
                        + " category Intent.CATEGORY_LAUNCHER " + component);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

这里mContext.startActivityAsUser(launchIntent, opts, user);

也便是说第三种activity的启航格局最后都以也调用了.startActivityAsUser(卡塔尔(قطر‎方法.也正是ActivityManagerService.java中的startActivityAsUser(卡塔尔方法.

嘿嘿,到此先暂停一下,
关于activity多少个难题,我们还应该有嫌疑,
1 – 上篇提到的ApplicationThread,也正是AMS – ActivityThread – Activity
终究是什么样的关系 ?
2 – Activity的生命周期的详尽流程是怎么样的 ?
3 – Activity的开发银行格局,Activity的xml的风姿洒脱部分性格,咱们还大概有待继续商量

谢谢:)

发表评论

电子邮件地址不会被公开。 必填项已用*标注