Android---AMS核心分析1

目录

ActivityManagerService 的启动流程

AMS 是什么?

startActivlty 流程

AMS 与 app 进程之间通信

AMS 管理 Activity

ActivityRecord

TaskRecord

ActivityStack

ActivityStackSupervisor

Activity 启动流程相关

Launcher 请求 AMS 阶段 

​编辑 

AMS 到 ApplicationThread 阶段 

ApplicationThread 到 Activity 阶段

HookActivity

ActivityManagerService(AMS) 是 Android 系统中一个特别重要的系统服务,也是我们上层 APP 打交道最多的系统服务之一。ActivityManagerService 主要负责四大组件的启动、切换、调度已经应用进程的管理和调度工作。所有的 APP 应用都需要与 AMS 打交道。

Activity Manager 主要由以下几个部分组成:

  1. 服务代理:由 ActivityManagerProxy 实现,用于与 Server 端提供的系统服务进行进程间通信

  2. 服务中枢:ActivityManagerNative 继承自 Binder 并实现 IActivityManager,它提供了服务接口和 Binder 接口的相互转化功能,并在内部存储服务代理对象,并提供了 getDefault 方法返回服务代理

  3. Client:由 ActivityManager 封装一部分服务接口供 Client 调用。ActivityManager 内部通过调用 ActivityManagerNative 的 getDefault 方法,可以看到一个 ActivityManagerProxy 对象的引用,进而通过该代理对象调用远程服务的方法

4. Server:由 ActivityManagerService 实现,提供 Server 端的系统服务

ActivityManagerService 的启动流程

AMS 是在 SystemServer 中被添加的,所以先到 SystemServer 中查看初始化。在 main 方法中通过 new SystemServer().run() 方法来启动 SystemServer

public static void main(String[] args) {
    new SystemServer().run();
}
private void run() {
    ...
    createSystemContext();
    // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setStartInfo(mRuntimeRestart,
    mRuntimeStartElapsedTime, mRuntimeStartUptime);
    LocalServices.addService(SystemServiceManager.class,
    mSystemServiceManager);
    // Prepare the thread pool for init tasks that can be parallelized
    SystemServerInitThreadPool.get();
    } finally {
        traceEnd(); // InitBeforeStartServices
    }
    //TODO Start services.
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices(); //TODO 启动引导服务.里面启动 AMS
        startCoreServices(); // 启动核心服务
        startOtherServices(); //启动其它服务
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        throw ex;
    } finally {
        traceEnd();
    }
    ...
    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

 在 run() 方法里有3个比较重要的函数:startBootstrapServices()、startCoreService()、startOtherServices()。其中,AMS 是在 startBootstrapServices() 中启动的:

private void startBootstrapServices() {
    ...
    // Activity manager runs the show.
    traceBeginAndSlog("StartActivityManager");
    //TODO 启动了AMS
    mActivityManagerService = mSystemServiceManager.startService(
    ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    traceEnd();
    ...
    // Now that the power manager has been started, let the activity manager
    // initialize power management features.
    traceBeginAndSlog("InitPowerManagement");
    mActivityManagerService.initPowerManagement();
    traceEnd();
    // Set up the Application instance for the system process and get started.
    traceBeginAndSlog("SetSystemProcess");
    mActivityManagerService.setSystemProcess();
    traceEnd();
}

AMS 是通过startBootstrapServices() 里的 SystemServiceManager.startService 去启动的,参数是 ActivityManagerService.Lifecycle.class,所以现在我们看看 startService() 方法:

@SuppressWarnings("unchecked")
public SystemService startService(String className) {
    final Class serviceClass;
    try {
        serviceClass = (Class)Class.forName(className);
    } catch (ClassNotFoundException ex) {
        Slog.i(TAG, "Starting " + className);
        throw new RuntimeException("Failed to create service " + className
            + ": service class not found, usually indicates that the
            caller should "
            + "have called PackageManager.hasSystemFeature() to check
            whether the "
            + "feature is available on this device before trying to
            start the "
            + "services that implement it", ex);
    }
    return startService(serviceClass);
}

@SuppressWarnings("unchecked")
public  T startService(Class serviceClass) {
    try {
        final String name = serviceClass.getName();
        Slog.i(TAG, "Starting " + name);
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " +
            name);
        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
            + ": service must extend " +
            SystemService.class.getName());
        }
        final T service;
        try {
            Constructor constructor =
            serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {
            throw new RuntimeException("Failed to create service " + name
            + ": service could not be instantiated", ex);
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("Failed to create service " + name
            + ": service must have a public constructor with a
            Context argument", ex);
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException("Failed to create service " + name
            + ": service must have a public constructor with a
            Context argument", ex);
        } catch (InvocationTargetException ex) {
            throw new RuntimeException("Failed to create service " + name
            + ": service constructor threw an exception", ex);
    }
    startService(service);
        return service;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }
}

public void startService(@NonNull final SystemService service) {
    // Register it.
    mServices.add(service);
    // Start it.
    long time = SystemClock.elapsedRealtime();
    try {
        service.onStart();
    } catch (RuntimeException ex) {
        throw new RuntimeException("Failed to start service " +
        service.getClass().getName()
        + ": onStart threw an exception", ex);
    }
    warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}

startService 方法很简单,是通过传进来的 class 然后反射创建对应的 Service 服务。所以此次创建的是 Lifecycle 的实例,然后通过 startService 启动了 AMS 服务。

接下来再看看 ActivityManagerService.Lifecycle 这个类的构造方法:

public static final class Lifecycle extends SystemService {
    private final ActivityManagerService mService; // 初始化 AMS 

    public Lifecycle(Context context) {
    super(context);
        mService = new ActivityManagerService(context); // 实例化 AMS
    }

    @Override
    public void onStart() {
        mService.start();
    }

    @Override
    public void onBootPhase(int phase) {
        mService.mBootPhase = phase;
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            mService.mBatteryStatsService.systemServicesReady();
        mService.mServices.systemServicesReady();
        }
    }

    @Override
    public void onCleanupUser(int userId) {
        mService.mBatteryStatsService.onCleanupUser(userId);
    }

    public ActivityManagerService getService() {
        return mService;
    }
}

通过上面的 Lifecycle 代码可以看到,Lifecycle 类里的第一句就初始化了一个 AMS, 并在 Lifecycle 的构造函数里实例化了 AMS。到此,AMS 初始化完成

所有应用的上下文(context)资源,都是来自 SystemContext,SystemContext 里面会加载资源。

再来看看 AMS 初始化做了什么

// Note: This method is invoked on the main thread but may need to attach
various
// handlers to other threads. So take care to be explicit about the looper.
public ActivityManagerService(Context systemContext) {
    LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);
    mInjector = new Injector();
    mContext = systemContext;//赋值mContext
    mFactoryTest = FactoryTest.getMode();
    mSystemThread = ActivityThread.currentActivityThread();//获取当前的
    ActivityThread
    mUiContext = mSystemThread.getSystemUiContext();//赋值mUiContext
    Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
    mPermissionReviewRequired = mContext.getResources().getBoolean(
    com.android.internal.R.bool.config_permissionReviewRequired);
    //创建Handler线程,用来处理handler消息
    mHandlerThread = new ServiceThread(TAG,
    THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    mHandlerThread.start();
    mHandler = new MainHandler(mHandlerThread.getLooper());
    mUiHandler = mInjector.getUiHandler(this);//处理ui相关msg的Handler
    mProcStartHandlerThread = new ServiceThread(TAG + ":procStart",
    THREAD_PRIORITY_FOREGROUND, false /* allowIo */);
    mProcStartHandlerThread.start();
    mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper());
    //管理AMS的一些常量,厂商定制系统就可能修改此处
    mConstants = new ActivityManagerConstants(this, mHandler);
    /* static; one-time init here */
    if (sKillHandler == null) {
        sKillThread = new ServiceThread(TAG + ":kill",
        THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
        sKillThread.start();
        sKillHandler = new KillHandler(sKillThread.getLooper());
    }

    //初始化管理前台、后台广播的队列, 系统会优先遍历发送前台广播
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
    "foreground", BROADCAST_FG_TIMEOUT, false);
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
    "background", BROADCAST_BG_TIMEOUT, true);
    mBroadcastQueues[0] = mFgBroadcastQueue;
    mBroadcastQueues[1] = mBgBroadcastQueue;
    //初始化管理Service的 ActiveServices对象
    mServices = new ActiveServices(this);
    mProviderMap = new ProviderMap(this);//初始化Provider的管理者
    mAppErrors = new AppErrors(mUiContext, this);//初始化APP错误日志的打印器
    //创建电池统计服务, 并输出到指定目录
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    systemDir.mkdirs();
    mAppWarnings = new AppWarnings(this, mUiContext, mHandler, mUiHandler,
    systemDir);
    // TODO: Move creation of battery stats service outside of activity
    manager service.
    mBatteryStatsService = new BatteryStatsService(systemContext, systemDir,
    mHandler);
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.scheduleWriteToDisk();
    mOnBattery = DEBUG_POWER ? true
    //创建进程统计分析服务,追踪统计哪些进程有滥用或不良行为 :
    mBatteryStatsService.getActiveStatistics().getIsOnBattery();
    mBatteryStatsService.getActiveStatistics().setCallback(this);
    mProcessStats = new ProcessStatsService(this, new File(systemDir,
    "procstats"));
    mAppOpsService = mInjector.getAppOpsService(new File(systemDir,
    "appops.xml"), mHandler);
    //加载Uri的授权文件
    mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "urigrants");
    //负责管理多用户
    mUserController = new UserController(this);
    //vr功能的控制器
    mVrController = new VrController(this);
    //初始化OpenGL版本号
    GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
    ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
    if (SystemProperties.getInt("sys.use_fifo_ui", 0) != 0) {
        mUseFifoUiScheduling = true;
    }
    mTrackingAssociations = "1".equals(SystemProperties.get("debug.trackassociations"));
    mTempConfig.setToDefaults();
    mTempConfig.setLocales(LocaleList.getDefault());
    mConfigurationSeq = mTempConfig.seq = 1;
    //管理ActivityStack的重要类,这里面记录着activity状态信息,是AMS中的核心类
    mStackSupervisor = createStackSupervisor();
    mStackSupervisor.onConfigurationChanged(mTempConfig);
    //根据当前可见的Activity类型,控制Keyguard遮挡,关闭和转换。 Keyguard就是我们的锁
    屏相关页面
    mKeyguardController = mStackSupervisor.getKeyguardController();
    管理APK的兼容性配置
    解析/data/system/packages-compat.xml文件,该文件用于存储那些需要考虑屏幕尺寸的APK信
    息,
    mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
    //Intent防火墙,Google定义了一组规则,来过滤intent,如果触发了,则intent会被系统丢
    弃,且不会告知发送者
    mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(),
    mHandler);
    mTaskChangeNotificationController =
    new TaskChangeNotificationController(this, mStackSupervisor,
    mHandler);
    //这是activity启动的处理类,这里管理者activity启动中用到的intent信息和flag标识,也
    和stack和task有重要的联系
    mActivityStartController = new ActivityStartController(this);
    mRecentTasks = createRecentTasks();
    mStackSupervisor.setRecentTasks(mRecentTasks);
    mLockTaskController = new LockTaskController(mContext, mStackSupervisor,
    mHandler);
    mLifecycleManager = new ClientLifecycleManager();
    //启动一个线程专门跟进cpu当前状态信息,AMS对当前cpu状态了如指掌,可以更加高效的安排其他工
作
    mProcessCpuThread = new Thread("CpuTracker") {

    @Override
    public void run() {
        synchronized (mProcessCpuTracker) {
        mProcessCpuInitLatch.countDown();
        mProcessCpuTracker.init();
    }
    while (true) {
        try {
            try {
                synchronized(this) {
                final long now = SystemClock.uptimeMillis();
                long nextCpuDelay =
                (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
                long nextWriteDelay =
                (mLastWriteTime+BATTERY_STATS_TIME)-now;
                //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
                // + ", write delay=" + nextWriteDelay);
                if (nextWriteDelay < nextCpuDelay) {
                    nextCpuDelay = nextWriteDelay;
                }
                if (nextCpuDelay > 0) {
                    mProcessCpuMutexFree.set(true);
                    this.wait(nextCpuDelay);
                }
            }
        } catch (InterruptedException e) {
    }
    updateCpuStatsNow();
    } catch (Exception e) {
            Slog.e(TAG, "Unexpected exception collecting process
            stats", e);
    }
    }
    }
};
    mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);
    //看门狗,监听进程。这个类每分钟调用一次监视器。 如果进程没有任何返回就杀掉
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
    // bind background thread to little cores
    // this is expected to fail inside of framework tests because apps can't
    touch cpusets directly
    // make sure we've already adjusted system_server's internal view of
    itself first
    updateOomAdjLocked();
    try {
        Process.setThreadGroupAndCpuset(BackgroundThread.get().getThreadId(),
        Process.THREAD_GROUP_BG_NONINTERACTIVE);
    } catch (Exception e) {
        Slog.w(TAG, "Setting background thread cpuset failed");
    }
}

private void start() {
    removeAllProcessGroups();
    mProcessCpuThread.start();
    mBatteryStatsService.publish();
    mAppOpsService.publish(mContext);
    Slog.d("AppOps", "AppOpsService published");
    LocalServices.addService(ActivityManagerInternal.class, new
    LocalService());
    // Wait for the synchronized block started in mProcessCpuThread,
    // so that any other acccess to mProcessCpuTracker from main thread
    // will be blocked during mProcessCpuTracker initialization.
    //等待mProcessCpuThread完成初始化后, 释放锁,初始化期间禁止访问
    try {
        mProcessCpuInitLatch.await();
    } catch (InterruptedException e) {
        Slog.wtf(TAG, "Interrupted wait during start", e);
        Thread.currentThread().interrupt();
        throw new IllegalStateException("Interrupted wait during start");
    }
}

然后看看 setSystemProcess 干了什么事情

public void setSystemProcess() {
    try {
        ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /*
        allowIsolated= */ true,
        DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL |
        DUMP_FLAG_PROTO);
        ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
        ServiceManager.addService("meminfo", new MemBinder(this), /*
        allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_HIGH);
        ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
        ServiceManager.addService("dbinfo", new DbBinder(this));
        if (MONITOR_CPU_USAGE) {
            ServiceManager.addService("cpuinfo", new CpuBinder(this),
            /* allowIsolated= */ false,
        DUMP_FLAG_PRIORITY_CRITICAL);
    }
    ServiceManager.addService("permission", new
    PermissionController(this));
    ServiceManager.addService("processinfo", new
    ProcessInfoService(this));
    ApplicationInfo info =
    mContext.getPackageManager().getApplicationInfo(
    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
    mSystemThread.installSystemApplicationInfo(info,
    getClass().getClassLoader());
    synchronized (this) {
    ProcessRecord app = newProcessRecordLocked(info,
    info.processName, false, 0);
    app.persistent = true;
    app.pid = MY_PID;
    app.maxAdj = ProcessList.SYSTEM_ADJ;
    app.makeActive(mSystemThread.getApplicationThread(),
    mProcessStats);
    synchronized (mPidsSelfLocked) {
    mPidsSelfLocked.put(app.pid, app);
    }
    updateLruProcessLocked(app, false, null);
    updateOomAdjLocked();
    }
} catch (PackageManager.NameNotFoundException e) {
    throw new RuntimeException(
    "Unable to find android system package", e);
}
    // Start watching app ops after we and the package manager are up and
    running.
    mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND,
    null,
    new IAppOpsCallback.Stub() {
    @Override public void opChanged(int op, int uid, String
        packageName) {
        if (op == AppOpsManager.OP_RUN_IN_BACKGROUND &&
            packageName != null) {
        if (mAppOpsService.checkOperation(op, uid,
        packageName)
        != AppOpsManager.MODE_ALLOWED) {
        runInBackgroundDisabled(uid);
        }
    }
    }
});
}

注册服务。首先将 ActivityManagerService 注册到 ServiceManager 中( setSystemProcess() 中 第一句ServiceManager.addService(), 就是在把 AMS 注册到 SM 中),其次将几个与系统性能调试相关的服务注册到 ServiceManager。

查询并处理 Application。首先调用 PackageManagerService 的接口,查询包名为 android 的应用程序的 ApplicationInfo 信息,对应于 framework-res.apk。然后以该信息为参数调用 ActivityThread 上的 installSystemApplication 方法。

创建并处理 ProcessRecord。调用 ActivityManagerService 上的 newProcessRecordLocked,创建一个 ProcessRecord 类型的对象,并保存对象的信息。

AMS 是什么?

1. 从 java 角度来看,AMS 就是一个 java 对象,实现了 Ibinder 接口,所以它是一个用于进程间通信的接口,这个对象初始化是在 systemServer.java 的 run() 方法里

public Lifecycle(Context context) {
    super(context);
    mService = new ActivityManagerService(context);
}

2. AMS 是一个服务

ActivityManagerService 从名字就可以看出,它是一个服务,用来管理 Activity,而且是一个系统服务,就是包管理服务,电池管理服务,震动管理服务等。

3. AMS 是一个 Binder

AMS 实现了 Ibinder 接口,所以它是一个 Binder,这意味着他不但可以用于进程间通信,还是一个线程,因为一个 Binder 就是一个线程。

如果我们启动一个 hello World 安卓应用程序,里面不另外启动其它线程,这个里面最少要启动4个线程:

  \bullet main 线程,只是程序的主线程,也是日常用到的最多的线程,也就 UI 线程,因为 android 的组件是非线程安全的,所以只允许 UI/MAIN 线程来操作。

  \bullet GC 线程,java 有垃圾回收机制,每个 java 程序都有一个专门负责垃圾回收的线程。

  \bullet Binder1 就是我们的 ApplicationThread,这个类实现了 Ibinder 接口,用于进程间通信,具体来说,就是我们程序和 AMS 通信的工具

  \bullet Binder2 就是我们的 ViewRoot 对象,他也是实现了 IBinder 接口,就是用于我们的应用程序和 WMS 通信的工具。WMS 就是 WindowManagerService,和 AMS 差不多的概念,不管他是管理窗口的系统服务。 

startActivlty 流程

Android---AMS核心分析1_第1张图片

当我们点击某个图标使得Launcher 触发 ---> startActivity --> 启动一个 activity 那么就要和 System Server 里的 AMS 打交道,当启动的 Activity 所在的进程还不存在,AMS 就会向 Zygote 进行请求,请求创建一个 app(应用程序进程) 进程。当 Zygote进程 fork()出一个 app(应用程序进程) 进程后,就没 Launcher 和 Zygote 什么事了。接下来就是 AMS 与 app(应用程序进程) 进程之间打交道了

AMS 与 app 进程之间通信

注意:Launcher, AMS, Zygote, app 是属于不同的进程的,他们的资源是不能共享的。所以需要跨进程机制。

所以考虑一个问题,AMS 与 app 进程之间如何通信?

app-->AMS: 在 app 里获取到 AMS 是很容易的,在 setSystemProcess() 函数中,通过ServiceManager.addService() 就把服务注册到了SM中。然后,通过ServiceManager.getService("ServiceName") ,传 Service 的名字,然后就可以在 SM 里面查询到这个服务(AMS),然后获取到他。

AMS-->app:当我们 fork 出一个 app 进程后,肯定是 app 进程先通信 AMS(app-->AMS) ,为了后面 AMS 也能通信到 app(AMS-->app) ,app 里面也会存在一个 binder 调用,即 IApplicationThread。在 app 通信 AMS 时,会把自己的代理(app_proxy)作为参数传递给 AMS,然后 AMS 就能找到这个 app 了,即上图中第2步。

根 Activity 启动过程中的进程调用时序图

Android---AMS核心分析1_第2张图片

AMS 管理 Activity

ActivityRecord

AMS 管理 activity 时,activity 是以一个 activityRecord 存储在 AMS 中的。所以我们一个 activity 就与一个 activityRecord 一一对应。activityRecord 中存在着大量的成员变量,包含了一个 Activity 的所有信息。ActivityRecord 是在 ActivityStarter() 里面创建的。

TaskRecord

TaskRecord(TaskRecord.java),内部维护一个 ArrayList用来保存ActivityRecord。

ActivityStack

ActivityStack, 内部维护了一个ArraryList,用来管理 TaskRecord

ActivityStackSupervisor

ActivityStackSupervisor 是用来管理 ActivityStack 的。

Android---AMS核心分析1_第3张图片

 

Activity 启动流程相关

Android---AMS核心分析1_第4张图片

Launcher 请求 AMS 阶段 

Android---AMS核心分析1_第5张图片 

AMS 到 ApplicationThread 阶段 

Android---AMS核心分析1_第6张图片

ApplicationThread 到 Activity 阶段

Android---AMS核心分析1_第7张图片 

 

 在哪儿判断 Activity 是否在 AndroidManifest.xml 里面注册的?

首先没有在 AndroidManifest.xml 注册,报错如下:

Android---AMS核心分析1_第8张图片

 从这里我们可以看到这个错误是在哪个代码块报出来的,与 execStartActivity() 和 checkStartActivityResult() 两个函数有关。在execStartActivity()里通过 IActivityManager 调用执行AMS 的 startActivity() 方法,并返回执行结果,再将结果传递给 checkStartActivityResult() 来判断该 Activity 是否再 AndroidManifest 里注册了。

Android---AMS核心分析1_第9张图片

 checkStartActivityResult() 是在 execStartActivity() 函数里调用的。

 Android---AMS核心分析1_第10张图片

 

HookActivity

HookActivity 启动没有注册的 Activity。当我们程序中一个activity 没有在 androidManifest.xml 里注册,那么我们允许程序时肯定会报错。

startActivity --> AMS(验证activity是否注册) --> 回到 app 进程后(Instrumentation 创建 Activity) --> AMS 控制 Instrumentation 执行 Activity 生命周期。

你可能感兴趣的:(#,FrameWork层源码,android)