android AMS 详解四

文章出处:https://blog.csdn.net/shift_wwx/article/details/46467677

接着之前三篇

android AMS 详解一

android AMS 详解二

android AMS 详解三

SystemServer中的ActivityManagerService.self().setWindowManager(wm);暂时不总结了,需要结合WMS。

接着总结:

ActivityManagerService.self().systemReady(new Runnable() {
    public void run() {
        Slog.i(TAG, "Making services ready");

        try {
            ActivityManagerService.self().startObservingNativeCrashes();
        } catch (Throwable e) {
            reportWtf("observing native crashes", e);
        }
        if (!headless) {
            startSystemUi(contextF);
        }
        try {
            if (mountServiceF != null) mountServiceF.systemReady();
        } catch (Throwable e) {
            reportWtf("making Mount Service ready", e);
        }
        
        ......
        
        ......
    }
};

这里systemReady的参数是一个Runnable的对象,并且实现了run,可以看到run里面都是AMS之后的一些准备工作。

例如startSystemUi、mountServiceF(MountService)、batteryF(BatteryService)、networkManagementF(NetworkManagementService)等等。

这些后续补充,来看一下systemReady的source code,由于systemReady的source code太长了,所以就分开来分析:

1、

// Check to see if there are any update receivers to run.
if (!mDidUpdate) {
    if (mWaitingUpdate) {
        return;
    }
    Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
    List<ResolveInfo> ris = null;
    try {
        ris = AppGlobals.getPackageManager().queryIntentReceivers(
                intent, null, 0, 0);
    } catch (RemoteException e) {
    }
    if (ris != null) {
        for (int i=ris.size()-1; i>=0; i--) {
            if ((ris.get(i).activityInfo.applicationInfo.flags
                    &ApplicationInfo.FLAG_SYSTEM) == 0) {
                ris.remove(i);
            }
        }
        intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE);

        ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers();

        final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>();
        for (int i=0; i<ris.size(); i++) {
            ActivityInfo ai = ris.get(i).activityInfo;
            ComponentName comp = new ComponentName(ai.packageName, ai.name);
            if (lastDoneReceivers.contains(comp)) {
                ris.remove(i);
                i--;
            }
        }

        final int[] users = getUsersLocked();
        for (int i=0; i<ris.size(); i++) {
            ActivityInfo ai = ris.get(i).activityInfo;
            ComponentName comp = new ComponentName(ai.packageName, ai.name);
            doneReceivers.add(comp);
            intent.setComponent(comp);
            for (int j=0; j<users.length; j++) {
                IIntentReceiver finisher = null;
                if (i == ris.size()-1 && j == users.length-1) {
                    finisher = new IIntentReceiver.Stub() {
                        public void performReceive(Intent intent, int resultCode,
                                String data, Bundle extras, boolean ordered,
                                boolean sticky, int sendingUser) {
                            // The raw IIntentReceiver interface is called
                            // with the AM lock held, so redispatch to
                            // execute our code without the lock.
                            mHandler.post(new Runnable() {
                                public void run() {
                                    synchronized (ActivityManagerService.this) {
                                        mDidUpdate = true;
                                    }
                                    writeLastDonePreBootReceivers(doneReceivers);
                                    showBootMessage(mContext.getText(
                                            R.string.android_upgrading_complete),
                                            false);
                                    systemReady(goingCallback);
                                }
                            });
                        }
                    };
                }
                Slog.i(TAG, "Sending system update to " + intent.getComponent()
                        + " for user " + users[j]);
                broadcastIntentLocked(null, null, intent, null, finisher,
                        0, null, null, null, AppOpsManager.OP_NONE,
                        true, false, MY_PID, Process.SYSTEM_UID,
                        users[j]);
                if (finisher != null) {
                    mWaitingUpdate = true;
                }
            }
        }
    }
    if (mWaitingUpdate) {
        return;
    }
    mDidUpdate = true;
}

主要用来处理OTA升级后database有改变的状况,这里会从PMS中获取所有接收ACTION_PRE_BOOT_COMPLETED的Receivers,并发送广播给它们,最后会记录这些已经发送广播的Receivers到/data/system/called_pre_boots.dat文件中。关于OTA升级这部分我们先不关注了。

接着来看systemReady后面的代码:
2、

ArrayList<ProcessRecord> procsToKill = null;
synchronized(mPidsSelfLocked) {
    for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
        ProcessRecord proc = mPidsSelfLocked.valueAt(i);
        if (!isAllowedWhileBooting(proc.info)){
            if (procsToKill == null) {
                procsToKill = new ArrayList<ProcessRecord>();
            }
            procsToKill.add(proc);
        }
    }
}

synchronized(this) {
    if (procsToKill != null) {
        for (int i=procsToKill.size()-1; i>=0; i--) {
            ProcessRecord proc = procsToKill.get(i);
            Slog.i(TAG, "Removing system update proc: " + proc);
            removeProcessLocked(proc, true, false, "system update done");
        }
    }
    
    // Now that we have cleaned up any update processes, we
    // are ready to start launching real processes and know that
    // we won't trample on them any more.
    mProcessesReady = true;
}

上面的代码主要是杀死在AMS systemReady之前启动的启动process,且这些process没有设置FLAG_PERSISTENT(例如update进程),然后调用removeProcessLocked去结束进程并释放资源,这部分代码我们后面再来介绍。

3、retrieveSettings();

    private void retrieveSettings() {
        final ContentResolver resolver = mContext.getContentResolver();
        String debugApp = Settings.Global.getString(
            resolver, Settings.Global.DEBUG_APP);
        boolean waitForDebugger = Settings.Global.getInt(
            resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0;
        boolean alwaysFinishActivities = Settings.Global.getInt(
            resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
        boolean forceRtl = Settings.Global.getInt(
                resolver, Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0;
        // Transfer any global setting for forcing RTL layout, into a System Property
        SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");

        Configuration configuration = new Configuration();
        Settings.System.getConfiguration(resolver, configuration);
        if (forceRtl) {
            // This will take care of setting the correct layout direction flags
            configuration.setLayoutDirection(configuration.locale);
        }

        synchronized (this) {
            mDebugApp = mOrigDebugApp = debugApp;
            mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger;
            mAlwaysFinishActivities = alwaysFinishActivities;
            // This happens before any activities are started, so we can
            // change mConfiguration in-place.
            updateConfigurationLocked(configuration, null, false, true);
            if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration);
        }
    }

从SettingsProvider中获取DEBUG_APP、WAIT_FOR_DEBUGGER、ALWAYS_FINISH_ACTIVITIES和DEVELOPMENT_FORCE_RTL四个配置项。

4、readGrantedUriPermissionsLocked

readGrantedUriPermissionsLocked从/data/system/urigrants.xml中读取Uri权限,并构造UriPermission保存在AMS全局的mGrantedUriPermissions中,这部分我们以后遇到的时候再来介绍。

5、if (goingCallback != null) goingCallback.run();

这里就是刚开始说到的,在systemServer中调用systemReady的时候同时注册的callback。

主要就是其他一些service 的systemReady、startSystemUi、软件启动Watchdog等。

6、mBooting = true;

7、mStackSupervisor.resumeTopActivitiesLocked();

    boolean resumeTopActivitiesLocked() {
        return resumeTopActivitiesLocked(null, null, null);
    }
    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
            Bundle targetOptions) {
        if (targetStack == null) {
            targetStack = getFocusedStack();
        }
        boolean result = false;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            if (isFrontStack(stack)) {
                if (stack == targetStack) {
                    result = stack.resumeTopActivityLocked(target, targetOptions);
                } else {
                    stack.resumeTopActivityLocked(null);
                }
            }
        }
        return result;
    }

targetStack传进来的是null,所以,重新赋值为mHomeStack。记得ActivityStackSupervisor这个类吧?在AMS.main的时候实例化的。

刚开始的时候mStacks应该就一个mHomeStack,这里会调用到result = stack.resumeTopActivityLocked(target, targetOptions);这里的两个参数应该都是null:

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");

        // 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 = mStackSupervisor.mUserLeaving;
        mStackSupervisor.mUserLeaving = false;

        if (next == null) {
            // There are no more activities!  Let's just start up the
            // Launcher...
            ActivityOptions.abort(options);
            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
            return mStackSupervisor.resumeHomeActivity(prev);
        }

首先要获取next:

    final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
            ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(notTop);
            if (r != null) {
                return r;
            }
        }
        return null;
    }

刚启动的时候mTaskHistory应该是空,所以,返回后next应该是null。

最终会调用return mStackSupervisor.resumeHomeActivity(prev);

    boolean resumeHomeActivity(ActivityRecord prev) {
        moveHomeToTop();
        if (prev != null) {
            prev.task.mOnTopOfHome = false;
        }
        ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
        if (r != null && r.isHomeActivity()) {
            mService.setFocusedActivityLocked(r);
            return resumeTopActivitiesLocked(mHomeStack, prev, null);
        }
        return mService.startHomeActivityLocked(mCurrentUser, false);
    }

r还是null,直接调用AMS的startHomeActivityLocked:

    boolean startHomeActivityLocked(int userId, boolean preStart) {
        if (mHeadless) {
            // Added because none of the other calls to ensureBootCompleted seem to fire
            // when running headless.
            ensureBootCompleted();
            return false;
        }

        if(preStart){
            ensureBootCompleted();
        }
        
        if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // We are running in factory test mode, but unable to find
            // the factory test app, so just sit around displaying the
            // error message and don't try to start anything.
            return false;
        }
        Intent intent = getHomeIntent();

	    try {
    	    //check if mount data fail
    	    Boolean bMountFail = SystemProperties.getBoolean("ro.init.mountdatafail", false);
    	    //Log.i( TAG, "bMountFail:" + bMountFail );

            ComponentName name = new ComponentName("com.amlogic.promptuser", "com.amlogic.promptuser.BootActivity");
    	    //PackageManager pm = mContext.getPackageManager();
    	    //pm.setComponentEnabledSetting(name, bMountFail ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
            final IPackageManager pm = AppGlobals.getPackageManager();
            pm.setComponentEnabledSetting(name, 
                bMountFail ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 
                PackageManager.DONT_KILL_APP, userId);
        } catch (Exception e) {
    	    Log.w( TAG, "setComponentEnabledSetting with com.amlogic.promptuser boot activity fail" );
    	    e.printStackTrace();
    	}

	    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, true);
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
              mStackSupervisor.startHomeActivity(intent, aInfo);
           }
        }

        return true;
    }

1)getHomeIntent

    Intent getHomeIntent() {
        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);
        }
        return intent;
    }

mTopAction、mTopData、mTopComponent都是在AMS.main中调用的startRunning(null,null,null,null)中初始值的。

    public final void startRunning(String pkg, String cls, String action,
            String data) {
        synchronized(this) {
            if (mStartRunning) {
                return;
            }
            mStartRunning = true;
            mTopComponent = pkg != null && cls != null
                    ? new ComponentName(pkg, cls) : null;
            mTopAction = action != null ? action : Intent.ACTION_MAIN;
            mTopData = data;
            if (!mSystemReady) {
                return;
            }
        }

        systemReady(null);
    }

可以看出mTopAction是Intent.ACTION_MAIN,mTopComponent是null。

那么综合看来getHomeIntent的目的就是实例化一个ACTION 是Intent.ACTION_MAIN、category是Intent.CATEGORY_HOME的一个intent。

2)通过之前获得的intent来解析ActivityInfo:

resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);

    private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
        ActivityInfo ai = null;
        ComponentName comp = intent.getComponent();
        try {
            if (comp != null) {
                ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
            } else {
                ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
                        intent,
                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                            flags, userId);

                if (info != null) {
                    ai = info.activityInfo;
                }
            }
        } catch (RemoteException e) {
            // ignore
        }

        return ai;
    }
    @Override
    public ResolveInfo resolveIntent(Intent intent, String resolvedType,
            int flags, int userId) {
        if (!sUserManager.exists(userId)) return null;
        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
        return chooseBestActivity(intent, resolvedType, flags, query, userId);
    }

 可能存在多个ACTION_MAIN,category是home的 intent,queryIntentActivities就是筛选,最开始的时候如果没有选择过会进入ResolverActivity (frameworks/base/core/java/com/android/internal/app) 让用户选择,至于怎么解析出ResolverActivity,我也是跟了一半,后期需要研究一下。如果有选择过了,就会通过chooseBestActivity函数来筛选:

    private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
            int flags, List<ResolveInfo> query, int userId) {
        if (query != null) {
            final int N = query.size();
            if (N == 1) {
                return query.get(0);
            } else if (N > 1) {
                final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
                // If there is more than one activity with the same priority,
                // then let the user decide between them.
                ResolveInfo r0 = query.get(0);
                ResolveInfo r1 = query.get(1);
                if (DEBUG_INTENT_MATCHING || debug) {
                    Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
                            + r1.activityInfo.name + "=" + r1.priority);
                }
                // If the first activity has a higher priority, or a different
                // default, then it is always desireable to pick it.
                if (r0.priority != r1.priority
                        || r0.preferredOrder != r1.preferredOrder
                        || r0.isDefault != r1.isDefault) {
                    return query.get(0);
                }
                // If we have saved a preference for a preferred activity for
                // this Intent, use that.
                ResolveInfo ri = findPreferredActivity(intent, resolvedType,
                        flags, query, r0.priority, true, false, debug, userId);
                if (ri != null) {
                    return ri;
                }
                if (userId != 0) {
                    ri = new ResolveInfo(mResolveInfo);
                    ri.activityInfo = new ActivityInfo(ri.activityInfo);
                    ri.activityInfo.applicationInfo = new ApplicationInfo(
                            ri.activityInfo.applicationInfo);
                    ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
                            UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
                    return ri;
                }
                return mResolveInfo;
            }
        }
        return null;
    }

通过code可以看到,如果就一个home activity的话,就直接返回了。如果是多个的话就需要比较,例如priority、preferredOrder、isDefault等。

3)通过之前获取了ActivityInfo,就可以设置component了,当然第一次启动的时候如果home多个,这里的ActivityInfo肯定是ResolverActivity,如果是单个home,或者是经过筛选的,这里的ActivityInfo应该是筛选出来的。

ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true);

这里app显然null,于是进入:

intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mStackSupervisor.startHomeActivity(intent, aInfo);

Home 是一个新的task,最终看到了启动Home Activity的地方了。

接下来详细分析一下启动Home Activity的过程,以后单纯的启动一个activity也会有很多相似的地方。这里以android 的Launcher2为例。

void startHomeActivity(Intent intent, ActivityInfo aInfo) {
    moveHomeToTop();//mTaskHistory 现在是空,这里没有做处理
    startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
            null, false, null);
}


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) {
    int err = ActivityManager.START_SUCCESS;

    ProcessRecord callerApp = null;
    PackageManager mPm = mContext.getPackageManager();
    if (caller != null) {//传进来参数为null
        ......
    }

    if (err == ActivityManager.START_SUCCESS) {
        final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
        Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
                + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
    }

    ActivityRecord sourceRecord = null;
    ActivityRecord resultRecord = null;
    if (resultTo != null) {//传进来参数为null
        ......
    }
    ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;

    int launchFlags = intent.getFlags();

    if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
            && sourceRecord != null) {//sourceRecord 为null
                ......
    }

    if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {//component 不为null
        ......
    }

    if (err == ActivityManager.START_SUCCESS && aInfo == null) {//aInfo不为null
        ......
    }

    ResolveInfo info = mPm.resolveActivity(intent, PackageManager.GET_DISABLED_COMPONENTS);
    //ResolveInfo info = mPm.resolveActivity(intent, PackageManager.GET_DISABLED_COMPONENTS|PackageManager.GET_INTENT_FILTERS);
    String packageName = (info != null) ? info.activityInfo.applicationInfo.packageName : null;
    String className = (info != null) ? info.activityInfo.name : null;
    Slog.i(TAG, "start package name is " + packageName
            + ", class name is " + className
            + ", error code is " + err);//打印:
                                        //I/ActivityManager(  506): start package name is com.android.launcher,
                                        //class name is com.android.launcher2.Launcher, error code is 0

    if (err != ActivityManager.START_SUCCESS) {
        ......
    }

    final int startAnyPerm = mService.checkPermission(
            START_ANY_ACTIVITY, callingPid, callingUid);//返回值是PERMISSION_GRANTED
    final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
            callingUid, aInfo.applicationInfo.uid, aInfo.exported);
    if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
        ......
    }

    boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
            callingPid, resolvedType, aInfo.applicationInfo);

    if (mService.mController != null) {
        ......
    }

    if (abort) {
        ......
    }

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration,
            resultRecord, resultWho, requestCode, componentSpecified, this);
    if (outActivity != null) {//传进来的参数是null
        ......
    }

    final ActivityStack stack = getFocusedStack();//mHomeStack
    if (stack.mResumedActivity == null
            || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
            ......
        }
    }

    if (mService.mDidAppSwitch) {
        // This is the second allowed switch since we stopped switches,
        // so now just generally allow switches.  Use case: user presses
        // home (switches disabled, switch to home, mDidAppSwitch now true);
        // user taps a home icon (coming from home so allowed, we hit here
        // and now allow anyone to switch again).
        mService.mAppSwitchesAllowedTime = 0;
    } else {
        mService.mDidAppSwitch = true;
    }

    mService.doPendingActivityLaunchesLocked(false);

    err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);

    if (allPausedActivitiesComplete()) {
        // If someone asked to have the keyguard dismissed on the next
        // activity start, but we are not actually doing an activity
        // switch...  just dismiss the keyguard now, because we
        // probably want to see whatever is behind it.
        dismissKeyguard();
    }

    return err;
}

看一下code中添加的注释。

针对home来分析一下startActivityLocked 如果不是home activity,过程是不一样的。

1)r

ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
        intent, resolvedType, aInfo, mService.mConfiguration,
        resultRecord, resultWho, requestCode, componentSpecified, this);

    原文作者:私房菜
    原文地址: https://blog.csdn.net/shift_wwx/article/details/46467677
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞