ActivityManagerService启动学习

简介

学习android高级课程的时候遇到几个问题,就是如何启动一个app。activity与ActivityManagerService通讯流程?Activity究竟是什么?

Activity究竟是什么?

个人理解是一个状态。当前页面处于什么状态。而绘制是通过WindowManagerService来进行。状态控制通过ActivityManagerService来进行。而activity可以理解为一个代理。

ActivityManagerService

要剖析ActivityManagerService的作用,第一个就是先弄明白他是如何启动的

AMS启动流程

android在启动的时候会初始化init进程,之后通过init进程启动zygoto进程,Android中大多数应用进程和系统进程都是通过zygoto进程生成的。上面的文章已经讲解了如何去fork一个进程。这里看一下AMS的启动流程
首先zygoto进程是通过zygotoinit.java启动的

先看一下zygotoinitmain方法,发现他创建了ZygoteServer,接着初始化ZygoteHooks,接着调用forkSystemServer进行fork,发现他其实调用的是ZygoteforkSystemServer方法

class zygotoinit{   @UnsupportedAppUsage    public static void main(String argv[]) {        // 这里创建ZygoteServer,是创建一个serversocket        ZygoteServer zygoteServer = new ZygoteServer();        // Mark zygote start. This ensures that thread creation will throw        // an error.        ZygoteHooks.startZygoteNoThreadCreation();        // Zygote goes into its own process group.        Os.setpgid(0, 0);        zygoteServer.createZygoteSocket(socketName);        Zygote.createBlastulaSocket(blastulaSocketName);        Zygote.getSocketFDs(socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME));        // 这里进行fork        if (startSystemServer) {                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the                // child (system_server) process.                if (r != null) {                    r.run();                    return;                }            }       }        // 进行fork操作    private static Runnable forkSystemServer(String abiList, String socketName,            ZygoteServer zygoteServer) {        long capabilities = posixCapabilitiesAsBits(                OsConstants.CAP_IPC_LOCK,                OsConstants.CAP_KILL,                OsConstants.CAP_NET_ADMIN,                OsConstants.CAP_NET_BIND_SERVICE,                OsConstants.CAP_NET_BROADCAST,                OsConstants.CAP_NET_RAW,                OsConstants.CAP_SYS_MODULE,                OsConstants.CAP_SYS_NICE,                OsConstants.CAP_SYS_PTRACE,                OsConstants.CAP_SYS_TIME,                OsConstants.CAP_SYS_TTY_CONFIG,                OsConstants.CAP_WAKE_ALARM,                OsConstants.CAP_BLOCK_SUSPEND        );         try {            /* Request to fork the system server process */            pid = Zygote.forkSystemServer(                    parsedArgs.mUid, parsedArgs.mGid,                    parsedArgs.mGids,                    parsedArgs.mRuntimeFlags,                    null,                    parsedArgs.mPermittedCapabilities,                    parsedArgs.mEffectiveCapabilities);        } catch (IllegalArgumentException ex) {            throw new RuntimeException(ex);        }        /* For child process */        if (pid == 0) {            if (hasSecondZygote(abiList)) {                waitForSecondaryZygote(socketName);            }            zygoteServer.closeServerSocket();            return handleSystemServerProcess(parsedArgs);        }        return null;    }    }

ZygoteforkSystemServer调用了nativeForkSystemServer方法,这是一个native方法,接着调用ZygoteHooks.postForkCommon(),看一下两个方法的具体实现

class Zygote{    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {        ZygoteHooks.preFork();        // Resets nice priority for zygote process.        resetNicePriority();        int pid = nativeForkSystemServer(                uid, gid, gids, runtimeFlags, rlimits,                permittedCapabilities, effectiveCapabilities);        // Enable tracing as soon as we enter the system_server.        if (pid == 0) {            Trace.setTracingEnabled(true, runtimeFlags);        }        ZygoteHooks.postForkCommon();        return pid;    }}

可以发现在他的jnif方法中调用了ForkCommon方法,前面的介绍,如果是子进程,他的返回id不是0,如果是当前进程则返回fork进程的id。

static jint com_android_internal_os_Zygote_nativeForkSystemServer(        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,        jlong effective_capabilities) {  std::vector<int> fds_to_close(MakeBlastulaPipeReadFDVector()),                   fds_to_ignore(fds_to_close);  fds_to_close.push_back(gBlastulaPoolSocketFD);  if (gBlastulaPoolEventFD != -1) {    fds_to_close.push_back(gBlastulaPoolEventFD);    fds_to_ignore.push_back(gBlastulaPoolEventFD);  }    //这里fork进程  pid_t pid = ForkCommon(env, true,                         fds_to_close,                         fds_to_ignore);  //如果是子进程  if (pid == 0) {      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,                       permitted_capabilities, effective_capabilities,                       MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,                       false, nullptr, nullptr);  // 如果是父进程                       } else if (pid > 0) {      // The zygote process checks whether the child process has died or not.      ALOGI("System server process %d has been created", pid);      gSystemServerPid = pid;      // There is a slight window that the system server process has crashed      // but it went unnoticed because we haven't published its pid yet. So      // we recheck here just to make sure that all is well.      int status;      if (waitpid(pid, &status, WNOHANG) == pid) {          ALOGE("System server process %d has died. Restarting Zygote!", pid);          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");      }      if (UsePerAppMemcg()) {          // Assign system_server to the correct memory cgroup.          // Not all devices mount memcg so check if it is mounted first          // to avoid unnecessarily printing errors and denials in the logs.          if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {              ALOGE("couldn't add process %d into system memcg group", pid);          }      }  }  return pid;}// Utility routine to specialize a zygote child process.static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,                             jint runtime_flags, jobjectArray rlimits,                             jlong permitted_capabilities, jlong effective_capabilities,                             jint mount_external, jstring managed_se_info,                             jstring managed_nice_name, bool is_system_server,                             bool is_child_zygote, jstring managed_instruction_set,                             jstring managed_app_data_dir) {  const char* process_name = is_system_server ? "system_server" : "zygote";  auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);  auto se_info = extract_fn(managed_se_info);  auto nice_name = extract_fn(managed_nice_name);  auto instruction_set = extract_fn(managed_instruction_set);  auto app_data_dir = extract_fn(managed_app_data_dir);  // Keep capabilities across UID change, unless we're staying root.  if (uid != 0) {    EnableKeepCapabilities(fail_fn);  }  SetInheritable(permitted_capabilities, fail_fn);  DropCapabilitiesBoundingSet(fail_fn);  bool use_native_bridge = !is_system_server &&                           instruction_set.has_value() &&                           android::NativeBridgeAvailable() &&                           android::NeedsNativeBridge(instruction_set.value().c_str());  if (use_native_bridge && !app_data_dir.has_value()) {    // The app_data_dir variable should never be empty if we need to use a    // native bridge.  In general, app_data_dir will never be empty for normal    // applications.  It can only happen in special cases (for isolated    // processes which are not associated with any app).  These are launched by    // the framework and should not be emulated anyway.    use_native_bridge = false;    ALOGW("Native bridge will not be used because managed_app_data_dir == nullptr.");  }//进行fork// Utility routine to fork a process from the zygote.static pid_t ForkCommon(JNIEnv* env, bool is_system_server,                        const std::vector<int>& fds_to_close,                        const std::vector<int>& fds_to_ignore) {  SetSignalHandlers();  // Curry a failure function.  auto fail_fn = std::bind(ZygoteFailure, env, is_system_server ? "system_server" : "zygote",                           nullptr, _1);  // Temporarily block SIGCHLD during forks. The SIGCHLD handler might  // log, which would result in the logging FDs we close being reopened.  // This would cause failures because the FDs are not whitelisted.  //  // Note that the zygote process is single threaded at this point.  BlockSignal(SIGCHLD, fail_fn);  // Close any logging related FDs before we start evaluating the list of  // file descriptors.  __android_log_close();  stats_log_close();  // If this is the first fork for this zygote, create the open FD table.  If  // it isn't, we just need to check whether the list of open files has changed  // (and it shouldn't in the normal case).  if (gOpenFdTable == nullptr) {    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, fail_fn);  } else {    gOpenFdTable->Restat(fds_to_ignore, fail_fn);  }  android_fdsan_error_level fdsan_error_level = android_fdsan_get_error_level();    // 关键的地方来了,,这里进行了fork操作  pid_t pid = fork();  if (pid == 0) {    // The child process.    PreApplicationInit();    // Clean up any descriptors which must be closed immediately    DetachDescriptors(env, fds_to_close, fail_fn);    // Re-open all remaining open file descriptors so that they aren't shared    // with the zygote across a fork.    gOpenFdTable->ReopenOrDetach(fail_fn);    // Turn fdsan back on.    android_fdsan_set_error_level(fdsan_error_level);  } else {    ALOGD("Forked child process %d", pid);  }  // We blocked SIGCHLD prior to a fork, we unblock it here.  UnblockSignal(SIGCHLD, fail_fn);  return pid;}

fork完成之后执行这个方法ZygoteHooks.postForkCommon();

class ZygoteHooks{    @libcore.api.CorePlatformApi    public static void postForkCommon() {        // 启动守护进程        Daemons.startPostZygoteFork();        nativePostZygoteFork();    }}

接着调用了ZygoteHooks.cpp中的ZygoteHooks_nativePostZygoteFork

static void ZygoteHooks_nativePostZygoteFork(JNIEnv*, jclass) {  Runtime* runtime = Runtime::Current();  if (runtime->IsZygote()) {    runtime->PostZygoteFork();  }}

接着回到ZygotoInit,发现他调用了handleSystemServerProcess方法

class ZygotoInit{    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {        // set umask to 0077 so new files and directories will default to owner-only permissions.        Os.umask(S_IRWXG | S_IRWXO);        if (parsedArgs.mNiceName != null) {            Process.setArgV0(parsedArgs.mNiceName);        }        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");        if (systemServerClasspath != null) {            if (performSystemServerDexOpt(systemServerClasspath)) {                // Throw away the cached classloader. If we compiled here, the classloader would                // not have had AoT-ed artifacts.                // Note: This only works in a very special environment where selinux enforcement is                // disabled, e.g., Mac builds.                sCachedSystemServerClassLoader = null;            }            // Capturing profiles is only supported for debug or eng builds since selinux normally            // prevents it.            boolean profileSystemServer = SystemProperties.getBoolean(                    "dalvik.vm.profilesystemserver", false);            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {                try {                    prepareSystemServerProfile(systemServerClasspath);                } catch (Exception e) {                    Log.wtf(TAG, "Failed to set up system server profile", e);                }            }        }        if (parsedArgs.mInvokeWith != null) {            String[] args = parsedArgs.mRemainingArgs;            // If we have a non-null system server class path, we'll have to duplicate the            // existing arguments and append the classpath to it. ART will handle the classpath            // correctly when we exec a new process.            if (systemServerClasspath != null) {                String[] amendedArgs = new String[args.length + 2];                amendedArgs[0] = "-cp";                amendedArgs[1] = systemServerClasspath;                System.arraycopy(args, 0, amendedArgs, 2, args.length);                args = amendedArgs;            }            WrapperInit.execApplication(parsedArgs.mInvokeWith,                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,                    VMRuntime.getCurrentInstructionSet(), null, args);            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");        } else {            //字面意思 创建系统的classloader            createSystemServerClassLoader();            ClassLoader cl = sCachedSystemServerClassLoader;            if (cl != null) {                Thread.currentThread().setContextClassLoader(cl);            }            /*             * Pass the remaining arguments to SystemServer.             */             // 进程初始化工作            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,                    parsedArgs.mRemainingArgs, cl);        }        /* should never reach here */    }   public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,            ClassLoader classLoader) {        if (RuntimeInit.DEBUG) {            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");        }        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");        RuntimeInit.redirectLogStreams();        RuntimeInit.commonInit();        ZygoteInit.nativeZygoteInit();        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);    }    }

applicationInit方法进行初始化操作,

class RuntimeInit{    protected static Runnable applicationInit(int targetSdkVersion, String[] argv,            ClassLoader classLoader) {        // If the application calls System.exit(), terminate the process        // immediately without running any shutdown hooks.  It is not possible to        // shutdown an Android application gracefully.  Among other things, the        // Android runtime shutdown hooks close the Binder driver, which can cause        // leftover running threads to crash before the process actually exits.        nativeSetExitWithoutCleanup(true);        // We want to be fairly aggressive about heap utilization, to avoid        // holding on to a lot of memory that isn't needed.        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);        final Arguments args = new Arguments(argv);        // The end of of the RuntimeInit event (see #zygoteInit).        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        // Remaining arguments are passed to the start class's static main        return findStaticMain(args.startClass, args.startArgs, classLoader);    }    // 找到SystemServer入口  protected static Runnable findStaticMain(String className, String[] argv,            ClassLoader classLoader) {        Class<?> cl;        try {            cl = Class.forName(className, true, classLoader);        } catch (ClassNotFoundException ex) {            throw new RuntimeException(                    "Missing class when invoking static main " + className,                    ex);        }        Method m;        try {            m = cl.getMethod("main", new Class[] { String[].class });        } catch (NoSuchMethodException ex) {            throw new RuntimeException(                    "Missing static main on " + className, ex);        } catch (SecurityException ex) {            throw new RuntimeException(                    "Problem getting static main on " + className, ex);        }        int modifiers = m.getModifiers();        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {            throw new RuntimeException(                    "Main method is not public and static on " + className);        }        /*         * This throw gets caught in ZygoteInit.main(), which responds         * by invoking the exception's run() method. This arrangement         * clears up all the stack frames that were required in setting         * up the process.         */        return new MethodAndArgsCaller(m, argv);    }}

发现这里通过反射调用了SystemServer的main方法,发现他初始化了SystemServiceManager并且调用了startBootstrapServices();startCoreServices();startOtherServices();

class SystemServer{  public static void main(String[] args) {        new SystemServer().run();    }           private void run() {        try {            traceBeginAndSlog("InitBeforeStartServices");            // If a device's clock is before 1970 (before 0), a lot of            // APIs crash dealing with negative numbers, notably            // java.io.File#setLastModified, so instead we fake it and            // hope that time from cell towers or NTP fixes it shortly.            if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {                Slog.w(TAG, "System clock is before 1970; setting to 1970.");                SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);            }            //            // Default the timezone property to GMT if not set.            //            String timezoneProperty =  SystemProperties.get("persist.sys.timezone");            if (timezoneProperty == null || timezoneProperty.isEmpty()) {                Slog.w(TAG, "Timezone not set; setting to GMT.");                SystemProperties.set("persist.sys.timezone", "GMT");            }            // If the system has "persist.sys.language" and friends set, replace them with            // "persist.sys.locale". Note that the default locale at this point is calculated            // using the "-Duser.locale" command line flag. That flag is usually populated by            // AndroidRuntime using the same set of system properties, but only the system_server            // and system apps are allowed to set them.            //            // NOTE: Most changes made here will need an equivalent change to            // core/jni/AndroidRuntime.cpp            if (!SystemProperties.get("persist.sys.language").isEmpty()) {                final String languageTag = Locale.getDefault().toLanguageTag();                SystemProperties.set("persist.sys.locale", languageTag);                SystemProperties.set("persist.sys.language", "");                SystemProperties.set("persist.sys.country", "");                SystemProperties.set("persist.sys.localevar", "");            }            // The system server should never make non-oneway calls            Binder.setWarnOnBlocking(true);            // The system server should always load safe labels            PackageItemInfo.setForceSafeLabels(true);            // Default to FULL within the system server.            SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;            // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized            SQLiteCompatibilityWalFlags.init(null);            // Here we go!            Slog.i(TAG, "Entered the Android system server!");            int uptimeMillis = (int) SystemClock.elapsedRealtime();            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);            if (!mRuntimeRestart) {                MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);            }            // In case the runtime switched since last boot (such as when            // the old runtime was removed in an OTA), set the system            // property so that it is in sync. We can | xq oqi't do this in            // libnativehelper's JniInvocation::Init code where we already            // had to fallback to a different runtime because it is            // running as root and we need to be the system user to set            // the property. http://b/11463182            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());            // Mmmmmm... more memory!            VMRuntime.getRuntime().clearGrowthLimit();            // The system server has to run all of the time, so it needs to be            // as efficient as possible with its memory usage.            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);            // Some devices rely on runtime fingerprint generation, so make sure            // we've defined it before booting further.            Build.ensureFingerprintProperty();            // Within the system server, it is an error to access Environment paths without            // explicitly specifying a user.            Environment.setUserRequired(true);            // Within the system server, any incoming Bundles should be defused            // to avoid throwing BadParcelableException.            BaseBundle.setShouldDefuse(true);            // Within the system server, when parceling exceptions, include the stack trace            Parcel.setStackTraceParceling(true);            // Ensure binder calls into the system always run at foreground priority.            BinderInternal.disableBackgroundScheduling(true);            // Increase the number of binder threads in system_server            BinderInternal.setMaxThreads(sMaxBinderThreads);            // Prepare the main looper thread (this thread).            android.os.Process.setThreadPriority(                android.os.Process.THREAD_PRIORITY_FOREGROUND);            android.os.Process.setCanSelfBackground(false);            Looper.prepareMainLooper();            Looper.getMainLooper().setSlowLogThresholdMs(                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);            // Initialize native services.            System.loadLibrary("android_servers");            // Check whether we failed to shut down last time we tried.            // This call may not return.            performPendingShutdown();            // Initialize the system context.            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        }        // Start services.        try {            traceBeginAndSlog("StartServices");            startBootstrapServices();            startCoreServices();            startOtherServices();            SystemServerInitThreadPool.shutdown();        } catch (Throwable ex) {            Slog.e("System", "******************************************");            Slog.e("System", "************ Failure starting system services", ex);            throw ex;        } finally {            traceEnd();        }        StrictMode.initVmDefaults(null);        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {            int uptimeMillis = (int) SystemClock.elapsedRealtime();            MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);            final int MAX_UPTIME_MILLIS = 60 * 1000;            if (uptimeMillis > MAX_UPTIME_MILLIS) {                Slog.wtf(SYSTEM_SERVER_TIMING_TAG,                        "SystemServer init took too long. uptimeMillis=" + uptimeMillis);            }        }        // Diagnostic to ensure that the system is in a base healthy state. Done here as a common        // non-zygote process.        if (!VMRuntime.hasBootImageSpaces()) {            Slog.wtf(TAG, "Runtime is not running with a boot image!");        }        // Loop forever.        Looper.loop();        throw new RuntimeException("Main thread loop unexpectedly exited");    }}
class SystemServer{ private void startBootstrapServices() {        Slog.i(TAG, "Reading configuration...");        final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";        traceBeginAndSlog(TAG_SYSTEM_CONFIG);        SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);        traceEnd();        // Wait for installd to finish starting up so that it has a chance to        // create critical directories such as /data/user with the appropriate        // permissions.  We need this to complete before we initialize other services.        traceBeginAndSlog("StartInstaller");        Installer installer = mSystemServiceManager.startService(Installer.class);        traceEnd();        // In some cases after launching an app we need to access device identifiers,        // therefore register the device identifier policy before the activity manager.        traceBeginAndSlog("DeviceIdentifiersPolicyService");        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);        traceEnd();        // Activity manager runs the show.  就是这里了        traceBeginAndSlog("StartActivityManager");        mActivityManagerService = mSystemServiceManager.startService(                ActivityManagerService.Lifecycle.class).getService();        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);        mActivityManagerService.setInstaller(installer);        traceEnd();        // Power manager needs to be started early because other services need it.        // Native daemons may be watching for it to be registered so it must be ready        // to handle incoming binder calls immediately (including being able to verify        // the permissions for those calls).        traceBeginAndSlog("StartPowerManager");        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);        traceEnd();        // Now that the power manager has been started, let the activity manager        // initialize power management features.        traceBeginAndSlog("InitPowerManagement");        mActivityManagerService.initPowerManagement();        traceEnd();        // Bring up recovery system in case a rescue party needs a reboot        traceBeginAndSlog("StartRecoverySystemService");        mSystemServiceManager.startService(RecoverySystemService.class);        traceEnd();        // Now that we have the bare essentials of the OS up and running, take        // note that we just booted, which might send out a rescue party if        // we're stuck in a runtime restart loop.        RescueParty.noteBoot(mSystemContext);        // Manages LEDs and display backlight so we need it to bring up the display.        traceBeginAndSlog("StartLightsService");        mSystemServiceManager.startService(LightsService.class);        traceEnd();        traceBeginAndSlog("StartSidekickService");        // Package manager isn't started yet; need to use SysProp not hardware feature        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);        }        traceEnd();        // Display manager is needed to provide display metrics before package manager        // starts up.        traceBeginAndSlog("StartDisplayManager");        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);        traceEnd();        // We need the default display before we can initialize the package manager.        traceBeginAndSlog("WaitForDisplay");        mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);        traceEnd();        // Only run "core" apps if we're encrypting the device.        String cryptState = VoldProperties.decrypt().orElse("");        if (ENCRYPTING_STATE.equals(cryptState)) {            Slog.w(TAG, "Detected encryption in progress - only parsing core apps");            mOnlyCore = true;        } else if (ENCRYPTED_STATE.equals(cryptState)) {            Slog.w(TAG, "Device encrypted - only parsing core apps");            mOnlyCore = true;        }        // Start the package manager.        if (!mRuntimeRestart) {            MetricsLogger.histogram(null, "boot_package_manager_init_start",                    (int) SystemClock.elapsedRealtime());        }        traceBeginAndSlog("StartPackageManagerService");        mPackageManagerService = PackageManagerService.main(mSystemContext, installer,                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);        mFirstBoot = mPackageManagerService.isFirstBoot();        mPackageManager = mSystemContext.getPackageManager();        traceEnd();        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {            MetricsLogger.histogram(null, "boot_package_manager_init_ready",                    (int) SystemClock.elapsedRealtime());        }        // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename        // A/B artifacts after boot, before anything else might touch/need them.        // Note: this isn't needed during decryption (we don't have /data anyways).        if (!mOnlyCore) {            boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",                    false);            if (!disableOtaDexopt) {                traceBeginAndSlog("StartOtaDexOptService");                try {                    OtaDexoptService.main(mSystemContext, mPackageManagerService);                } catch (Throwable e) {                    reportWtf("starting OtaDexOptService", e);                } finally {                    traceEnd();                }            }        }        traceBeginAndSlog("StartUserManagerService");        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);        traceEnd();        // Initialize attribute cache used to cache resources from packages.        traceBeginAndSlog("InitAttributerCache");        AttributeCache.init(mSystemContext);        traceEnd();        // Set up the Application instance for the system process and get started.        traceBeginAndSlog("SetSystemProcess");        mActivityManagerService.setSystemProcess();        traceEnd();        // DisplayManagerService needs to setup android.display scheduling related policies        // since setSystemProcess() would have overridden policies due to setProcessGroup        mDisplayManagerService.setupSchedulerPolicies();        // Manages Overlay packages        traceBeginAndSlog("StartOverlayManagerService");        OverlayManagerService overlayManagerService = new OverlayManagerService(                mSystemContext, installer);        mSystemServiceManager.startService(overlayManagerService);        traceEnd();        if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {            // DisplayManager needs the overlay immediately.            overlayManagerService.updateSystemUiContext();            LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();        }        // The sensor service needs access to package manager service, app ops        // service, and permissions service, therefore we start it after them.        // Start sensor service in a separate thread. Completion should be checked        // before using it.        mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {            TimingsTraceLog traceLog = new TimingsTraceLog(                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);            traceLog.traceBegin(START_SENSOR_SERVICE);            startSensorService();            traceLog.traceEnd();        }, START_SENSOR_SERVICE);    }}
class AMS{    public void setSystemProcess() {        try {           // 这里注册service            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);                            }                        }                    }                });    }}

看一下他的构造方法做了什么

public ActivityManagerService(Context systemContext) {        LockGuard.installLock(this, LockGuard.INDEX_ACTIVITY);        mInjector = new Injector();        mContext = systemContext;        mFactoryTest = FactoryTest.getMode();        mSystemThread = ActivityThread.currentActivityThread();        mUiContext = mSystemThread.getSystemUiContext();        Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());        mPermissionReviewRequired = mContext.getResources().getBoolean(                com.android.internal.R.bool.config_permissionReviewRequired);        mHandlerThread = new ServiceThread(TAG,                THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);        mHandlerThread.start();        mHandler = new MainHandler(mHandlerThread.getLooper());        mUiHandler = mInjector.getUiHandler(this);        mProcStartHandlerThread = new ServiceThread(TAG + ":procStart",                THREAD_PRIORITY_FOREGROUND, false /* allowIo */);        mProcStartHandlerThread.start();        mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper());        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;        // 初始化activityservice和provider对象数组        mServices = new ActiveServices(this);        mProviderMap = new ProviderMap(this);        mAppErrors = new AppErrors(mUiContext, this);        // 初始化目录        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);        mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");        mUserController = new UserController(this);        mVrController = new VrController(this);        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.track-associations"));        mTempConfig.setToDefaults();        mTempConfig.setLocales(LocaleList.getDefault());        mConfigurationSeq = mTempConfig.seq = 1;        //这里创建了activityStackSupervisor 里面记录了activity的状态,activitystarter activity启动处理类        mStackSupervisor = createStackSupervisor();        mStackSupervisor.onConfigurationChanged(mTempConfig);        mKeyguardController = mStackSupervisor.getKeyguardController();        mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);        mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);        mTaskChangeNotificationController =                new TaskChangeNotificationController(this, mStackSupervisor, mHandler);        mActivityStartController = new ActivityStartController(this);        mRecentTasks = createRecentTasks();        mStackSupervisor.setRecentTasks(mRecentTasks);        mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);        mLifecycleManager = new ClientLifecycleManager();        // 创建thread,记录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");        }    }

发现他创建了handler,并且定义了前后台广播队列

@startumlZygotoInit->ZygoteServer:ZygotoInit->ZygoteHooks:startZygoteNoThreadCreationZygoteHooks->ZygoteHooks.cc:通过native调用ZygotoInit->ZygotoInit:forkSystemServerZygotoInit->Zygote:forkSystemServerZygote->Zygote.cpp:com_android_internal_os_Zygote_nativeForkSystemServerZygote.cpp->Zygote.cpp:ForkCommon() 进程的fork操作Zygote.cpp->Zygote.cpp:SpecializeCommon()子进程调用执行一些初始化工作Zygote->ZygoteHooks:postForkCommonZygoteHooks->ZygoteHooks.cpp:nativePostZygoteForkZygotoInit->ZygotoInit:handleSystemServerProcess(parsedArgs)ZygotoInit->ZygotoInit:createSystemServerClassLoader 创建classloaderZygotoInit->ZygotoInit:zygoteInit() ZygotoInit-> RuntimeInit:commonInit(); 初始化LoggingHandler和KillApplicationHandlerZygotoInit-> ZygoteInit:nativeZygoteInit();ZygotoInit->RuntimeInit:applicationInit(targetSdkVersion, argv, classLoader)ZygotoInit->SystemServer:main方法SystemServer->SystemServer:run()SystemServer->SystemServer:startBootstrapServices()启动boot相关的服务,包含AMSSystemServer->AMS:setSystemServiceManagerSystemServer->AMS:setInstallerSystemServer->AMS:setSystemProcessSystemServer->SystemServer:startCoreServices()启动其他核心服务SystemServer->SystemServer:startOtherServices()启动其他服务@enduml

Activity如何启动,开启一个进程

从ActivityStackSupervisor启动activity

class ActivityStackSupervisor{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);        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.longVersionCode,                            mService.mProcessStats);                }                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);    }}

调用AMS的startProcessLocked方法,重点关注一个东西entryPoint,他的值是final String entryPoint = "android.app.ActivityThread";是不是很熟悉,在这个方法中,首先判断app是否存在,因为android中进程是和包名相关,如果没有,会

    @GuardedBy("this")    private final boolean startProcessLocked(ProcessRecord app, String hostingType,            String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {        if (app.pendingStart) {            return true;        }        long startTime = SystemClock.elapsedRealtime();        if (app.pid > 0 && app.pid != MY_PID) {            checkTime(startTime, "startProcess: removing from pids map");            synchronized (mPidsSelfLocked) {                mPidsSelfLocked.remove(app.pid);                mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);            }            checkTime(startTime, "startProcess: done removing from pids map");            app.setPid(0);        }        if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,                "startProcessLocked removing on hold: " + app);        mProcessesOnHold.remove(app);        checkTime(startTime, "startProcess: starting to update cpu stats");        updateCpuStats();        checkTime(startTime, "startProcess: done updating cpu stats");        try {            try {                final int userId = UserHandle.getUserId(app.uid);                AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);            } catch (RemoteException e) {                throw e.rethrowAsRuntimeException();            }            int uid = app.uid;            int[] gids = null;            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;            if (!app.isolated) {                int[] permGids = null;                try {                    checkTime(startTime, "startProcess: getting gids from package manager");                    final IPackageManager pm = AppGlobals.getPackageManager();                    permGids = pm.getPackageGids(app.info.packageName,                            MATCH_DEBUG_TRIAGED_MISSING, app.userId);                    StorageManagerInternal storageManagerInternal = LocalServices.getService(                            StorageManagerInternal.class);                    mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,                            app.info.packageName);                } catch (RemoteException e) {                    throw e.rethrowAsRuntimeException();                }                /*                 * Add shared application and profile GIDs so applications can share some                 * resources like shared libraries and access user-wide resources                 */                if (ArrayUtils.isEmpty(permGids)) {                    gids = new int[3];                } else {                    gids = new int[permGids.length + 3];                    System.arraycopy(permGids, 0, gids, 3, permGids.length);                }                gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));                gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));                gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));                // Replace any invalid GIDs                if (gids[0] == UserHandle.ERR_GID) gids[0] = gids[2];                if (gids[1] == UserHandle.ERR_GID) gids[1] = gids[2];            }            checkTime(startTime, "startProcess: building args");            if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {                if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL                        && mTopComponent != null                        && app.processName.equals(mTopComponent.getPackageName())) {                    uid = 0;                }                if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL                        && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {                    uid = 0;                }            }            int runtimeFlags = 0;            if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {                runtimeFlags |= Zygote.DEBUG_ENABLE_JDWP;                runtimeFlags |= Zygote.DEBUG_JAVA_DEBUGGABLE;                // Also turn on CheckJNI for debuggable apps. It's quite                // awkward to turn on otherwise.                runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;            }            // Run the app in safe mode if its manifest requests so or the            // system is booted in safe mode.            if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||                mSafeMode == true) {                runtimeFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;            }            if ("1".equals(SystemProperties.get("debug.checkjni"))) {                runtimeFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;            }            String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");            if ("1".equals(genDebugInfoProperty) || "true".equals(genDebugInfoProperty)) {                runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;            }            String genMiniDebugInfoProperty = SystemProperties.get("dalvik.vm.minidebuginfo");            if ("1".equals(genMiniDebugInfoProperty) || "true".equals(genMiniDebugInfoProperty)) {                runtimeFlags |= Zygote.DEBUG_GENERATE_MINI_DEBUG_INFO;            }            if ("1".equals(SystemProperties.get("debug.jni.logging"))) {                runtimeFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;            }            if ("1".equals(SystemProperties.get("debug.assert"))) {                runtimeFlags |= Zygote.DEBUG_ENABLE_ASSERT;            }            if ("1".equals(SystemProperties.get("debug.ignoreappsignalhandler"))) {                runtimeFlags |= Zygote.DEBUG_IGNORE_APP_SIGNAL_HANDLER;            }            if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) {                // Enable all debug flags required by the native debugger.                runtimeFlags |= Zygote.DEBUG_ALWAYS_JIT;          // Don't interpret anything                runtimeFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug info                runtimeFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE;   // Disbale optimizations                mNativeDebuggingApp = null;            }            if (app.info.isPrivilegedApp() &&                    DexManager.isPackageSelectedToRunOob(app.pkgList.keySet())) {                runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;            }            if (!disableHiddenApiChecks && !mHiddenApiBlacklist.isDisabled()) {                app.info.maybeUpdateHiddenApiEnforcementPolicy(mHiddenApiBlacklist.getPolicy());                @HiddenApiEnforcementPolicy int policy =                        app.info.getHiddenApiEnforcementPolicy();                int policyBits = (policy << Zygote.API_ENFORCEMENT_POLICY_SHIFT);                if ((policyBits & Zygote.API_ENFORCEMENT_POLICY_MASK) != policyBits) {                    throw new IllegalStateException("Invalid API policy: " + policy);                }                runtimeFlags |= policyBits;            }            String invokeWith = null;            if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {                // Debuggable apps may include a wrapper script with their library directory.                String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();                try {                    if (new File(wrapperFileName).exists()) {                        invokeWith = "/system/bin/logwrapper " + wrapperFileName;                    }                } finally {                    StrictMode.setThreadPolicy(oldPolicy);                }            }            String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;            if (requiredAbi == null) {                requiredAbi = Build.SUPPORTED_ABIS[0];            }            String instructionSet = null;            if (app.info.primaryCpuAbi != null) {                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);            }            app.gids = gids;            app.requiredAbi = requiredAbi;            app.instructionSet = instructionSet;            // the per-user SELinux context must be set            if (TextUtils.isEmpty(app.info.seInfoUser)) {                Slog.wtf(TAG, "SELinux tag not defined",                        new IllegalStateException("SELinux tag not defined for "                        + app.info.packageName + " (uid " + app.uid + ")"));            }            final String seInfo = app.info.seInfo                    + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);            // Start the process.  It will either succeed and return a result containing            // the PID of the new process, or else throw a RuntimeException.            final String entryPoint = "android.app.ActivityThread";            return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,                    startTime);        } catch (RuntimeException e) {            Slog.e(TAG, "Failure starting process " + app.processName, e);            // Something went very wrong while trying to start this process; one            // common case is when the package is frozen due to an active            // upgrade. To recover, clean up any active bookkeeping related to            // starting this process. (We already invoked this method once when            // the package was initially frozen through KILL_APPLICATION_MSG, so            // it doesn't hurt to use it again.)            forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,                    false, true, false, false, app.userId, "start failure");            return false;        }    }     // 如果进程不存在    @GuardedBy("this")    private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,            String seInfo, String requiredAbi, String instructionSet, String invokeWith,            long startTime) {        app.pendingStart = true;        app.killedByAm = false;        app.removed = false;        app.killed = false;        final long startSeq = app.startSeq = ++mProcStartSeqCounter;        app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);        if (mConstants.FLAG_PROCESS_START_ASYNC) {            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,                    "Posting procStart msg for " + app.toShortString());            mProcStartHandler.post(() -> {                try {                    synchronized (ActivityManagerService.this) {                        final String reason = isProcStartValidLocked(app, startSeq);                        if (reason != null) {                            Slog.w(TAG_PROCESSES, app + " not valid anymore,"                                    + " don't start process, " + reason);                            app.pendingStart = false;                            return;                        }                        app.usingWrapper = invokeWith != null                                || SystemProperties.get("wrap." + app.processName) != null;                        mPendingStarts.put(startSeq, app);                    }                    // 开启新的进程                    final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,                            app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,                            requiredAbi, instructionSet, invokeWith, app.startTime);                    synchronized (ActivityManagerService.this) {                        handleProcessStartedLocked(app, startResult, startSeq);                    }                } catch (RuntimeException e) {                    synchronized (ActivityManagerService.this) {                        Slog.e(TAG, "Failure starting process " + app.processName, e);                        mPendingStarts.remove(startSeq);                        app.pendingStart = false;                        forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),                                false, false, true, false, false,                                UserHandle.getUserId(app.userId), "start failure");                    }                }            });            return true;        } else {            try {                final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,                        uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,                        invokeWith, startTime);                handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,                        startSeq, false);            } catch (RuntimeException e) {                Slog.e(TAG, "Failure starting process " + app.processName, e);                app.pendingStart = false;                forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),                        false, false, true, false, false,                        UserHandle.getUserId(app.userId), "start failure");            }            return app.pid > 0;        }    }            // 启动进程   private ProcessStartResult startProcess(String hostingType, String entryPoint,            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,            String seInfo, String requiredAbi, String instructionSet, String invokeWith,            long startTime) {        try {            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +                    app.processName);            checkTime(startTime, "startProcess: asking zygote to start proc");            final ProcessStartResult startResult;            if (hostingType.equals("webview_service")) {                startResult = startWebView(entryPoint,                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,                        app.info.dataDir, null,                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});            } else {                startResult = Process.start(entryPoint,                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,                        app.info.dataDir, invokeWith,                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});            }            checkTime(startTime, "startProcess: returned from zygote!");            return startResult;        } finally {            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);        }    }

看一下android的Process.java注意与jdk中的Process做区分

    public static final ProcessStartResult start(final String processClass,                                  final String niceName,                                  int uid, int gid, int[] gids,                                  int runtimeFlags, int mountExternal,                                  int targetSdkVersion,                                  String seInfo,                                  String abi,                                  String instructionSet,                                  String appDataDir,                                  String invokeWith,                                  String[] zygoteArgs) {        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, invokeWith,                    /*useBlastulaPool=*/ true, zygoteArgs);    }

看一下zygoteProcess方法

 public final Process.ProcessStartResult start(final String processClass,                                                  final String niceName,                                                  int uid, int gid, int[] gids,                                                  int runtimeFlags, int mountExternal,                                                  int targetSdkVersion,                                                  String seInfo,                                                  String abi,                                                  String instructionSet,                                                  String appDataDir,                                                  String invokeWith,                                                  boolean useBlastulaPool,                                                  String[] zygoteArgs) {        try {            return startViaZygote(processClass, niceName, uid, gid, gids,                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,                    abi, instructionSet, appDataDir, invokeWith,                    /*startChildZygote=*/false,                    useBlastulaPool, zygoteArgs);        } catch (ZygoteStartFailedEx ex) {            Log.e(LOG_TAG,                    "Starting VM process through Zygote failed");            throw new RuntimeException(                    "Starting VM process through Zygote failed", ex);        }    }  private Process.ProcessStartResult startViaZygote(final String processClass,                                                      final String niceName,                                                      final int uid, final int gid,                                                      final int[] gids,                                                      int runtimeFlags, int mountExternal,                                                      int targetSdkVersion,                                                      String seInfo,                                                      String abi,                                                      String instructionSet,                                                      String appDataDir,                                                      String invokeWith,                                                      boolean startChildZygote,                                                      boolean useBlastulaPool,                                                      String[] extraArgs)                                                      throws ZygoteStartFailedEx {        ArrayList<String> argsForZygote = new ArrayList<String>();        // --runtime-args, --setuid=, --setgid=,        // and --setgroups= must go first        argsForZygote.add("--runtime-args");        argsForZygote.add("--setuid=" + uid);        argsForZygote.add("--setgid=" + gid);        argsForZygote.add("--runtime-flags=" + runtimeFlags);        if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {            argsForZygote.add("--mount-external-default");        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {            argsForZygote.add("--mount-external-read");        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {            argsForZygote.add("--mount-external-write");        }        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);        // --setgroups is a comma-separated list        if (gids != null && gids.length > 0) {            StringBuilder sb = new StringBuilder();            sb.append("--setgroups=");            int sz = gids.length;            for (int i = 0; i < sz; i++) {                if (i != 0) {                    sb.append(',');                }                sb.append(gids[i]);            }            argsForZygote.add(sb.toString());        }        if (niceName != null) {            argsForZygote.add("--nice-name=" + niceName);        }        if (seInfo != null) {            argsForZygote.add("--seinfo=" + seInfo);        }        if (instructionSet != null) {            argsForZygote.add("--instruction-set=" + instructionSet);        }        if (appDataDir != null) {            argsForZygote.add("--app-data-dir=" + appDataDir);        }        if (invokeWith != null) {            argsForZygote.add("--invoke-with");            argsForZygote.add(invokeWith);        }        if (startChildZygote) {            argsForZygote.add("--start-child-zygote");        }        argsForZygote.add(processClass);        if (extraArgs != null) {            for (String arg : extraArgs) {                argsForZygote.add(arg);            }        }        synchronized(mLock) {            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),                                              useBlastulaPool,                                              argsForZygote);        }    }        //这里通过locksocket去fork进程,那么这个socket的接收者是谁呢? @GuardedBy("mLock")    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(            ZygoteState zygoteState, boolean useBlastulaPool, ArrayList<String> args)            throws ZygoteStartFailedEx {        // Throw early if any of the arguments are malformed. This means we can        // avoid writing a partial response to the zygote.        for (String arg : args) {            if (arg.indexOf('\n') >= 0) {                throw new ZygoteStartFailedEx("embedded newlines not allowed");            }        }        /*         * See com.android.internal.os.ZygoteArguments.parseArgs()         * Presently the wire format to the zygote process is:         * a) a count of arguments (argc, in essence)         * b) a number of newline-separated argument strings equal to count         *         * After the zygote process reads these it will write the pid of         * the child or -1 on failure, followed by boolean to         * indicate whether a wrapper process was used.         */        String msgStr = Integer.toString(args.size()) + "\n"                        + String.join("\n", args) + "\n";        // Should there be a timeout on this?        Process.ProcessStartResult result = new Process.ProcessStartResult();        // TODO (chriswailes): Move branch body into separate function.        if (useBlastulaPool && Zygote.BLASTULA_POOL_ENABLED && isValidBlastulaCommand(args)) {            LocalSocket blastulaSessionSocket = null;            try {                blastulaSessionSocket = zygoteState.getBlastulaSessionSocket();                final BufferedWriter blastulaWriter =                        new BufferedWriter(                                new OutputStreamWriter(blastulaSessionSocket.getOutputStream()),                                Zygote.SOCKET_BUFFER_SIZE);                final DataInputStream blastulaReader =                        new DataInputStream(blastulaSessionSocket.getInputStream());                blastulaWriter.write(msgStr);                blastulaWriter.flush();                result.pid = blastulaReader.readInt();                // Blastulas can't be used to spawn processes that need wrappers.                result.usingWrapper = false;                if (result.pid < 0) {                    throw new ZygoteStartFailedEx("Blastula specialization failed");                }                return result;            } catch (IOException ex) {                // If there was an IOException using the blastula pool we will log the error and                // attempt to start the process through the Zygote.                Log.e(LOG_TAG, "IO Exception while communicating with blastula pool - "                               + ex.toString());            } finally {                try {                    blastulaSessionSocket.close();                } catch (IOException ex) {                    Log.e(LOG_TAG, "Failed to close blastula session socket: " + ex.getMessage());                }            }        }        try {            final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;            final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;            zygoteWriter.write(msgStr);            zygoteWriter.flush();            // Always read the entire result from the input stream to avoid leaving            // bytes in the stream for future process starts to accidentally stumble            // upon.            result.pid = zygoteInputStream.readInt();            result.usingWrapper = zygoteInputStream.readBoolean();        } catch (IOException ex) {            zygoteState.close();            Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "                    + ex.toString());            throw new ZygoteStartFailedEx(ex);        }        if (result.pid < 0) {            throw new ZygoteStartFailedEx("fork() failed");        }        return result;    }

看一下监听的内容

 public enum Namespace {        /** A socket in the Linux abstract namespace */        ABSTRACT(0),        /**         * A socket in the Android reserved namespace in /dev/socket.         * Only the init process may create a socket here.         */         // 就是这个,是android特有的一个,监听/dev/socket.        RESERVED(1),        /**         * A socket named with a normal filesystem path.         */        FILESYSTEM(2);        /** The id matches with a #define in include/cutils/sockets.h */        private int id;        Namespace (int id) {            this.id = id;        }        /**         * @return int constant shared with native code         */        /*package*/ int getId() {            return id;        }    }

回到ZygoteInit的main方法

@UnsupportedAppUsage    public static void main(String argv[]) {        ZygoteServer zygoteServer = new ZygoteServer();        // Mark zygote start. This ensures that thread creation will throw        // an error.        ZygoteHooks.startZygoteNoThreadCreation();        // Zygote goes into its own process group.        try {            Os.setpgid(0, 0);        } catch (ErrnoException ex) {            throw new RuntimeException("Failed to setpgid(0,0)", ex);        }        Runnable caller;        try {            // Report Zygote start time to tron unless it is a runtime restart            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {                MetricsLogger.histogram(null, "boot_zygote_init",                        (int) SystemClock.elapsedRealtime());            }            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,                    Trace.TRACE_TAG_DALVIK);            bootTimingsTraceLog.traceBegin("ZygoteInit");            RuntimeInit.enableDdms();            boolean startSystemServer = false;            String socketName = "zygote";            String abiList = null;            boolean enableLazyPreload = false;            for (int i = 1; i < argv.length; i++) {                if ("start-system-server".equals(argv[i])) {                    startSystemServer = true;                } else if ("--enable-lazy-preload".equals(argv[i])) {                    enableLazyPreload = true;                } else if (argv[i].startsWith(ABI_LIST_ARG)) {                    abiList = argv[i].substring(ABI_LIST_ARG.length());                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());                } else {                    throw new RuntimeException("Unknown command line argument: " + argv[i]);                }            }            if (abiList == null) {                throw new RuntimeException("No ABI list supplied.");            }            // TODO (chriswailes): Wrap these three calls in a helper function?            final String blastulaSocketName =                    socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME)                            ? ZygoteProcess.BLASTULA_POOL_SOCKET_NAME                            : ZygoteProcess.BLASTULA_POOL_SECONDARY_SOCKET_NAME;            // 这里进行了注册            zygoteServer.createZygoteSocket(socketName);            Zygote.createBlastulaSocket(blastulaSocketName);            Zygote.getSocketFDs(socketName.equals(ZygoteProcess.ZYGOTE_SOCKET_NAME));            // In some configurations, we avoid preloading resources and classes eagerly.            // In such cases, we will preload things prior to our first fork.            if (!enableLazyPreload) {                bootTimingsTraceLog.traceBegin("ZygotePreload");                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,                        SystemClock.uptimeMillis());                preload(bootTimingsTraceLog);                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,                        SystemClock.uptimeMillis());                bootTimingsTraceLog.traceEnd(); // ZygotePreload            } else {                Zygote.resetNicePriority();            }            // Do an initial gc to clean up after startup            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");            gcAndFinalize();            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC            bootTimingsTraceLog.traceEnd(); // ZygoteInit            // Disable tracing so that forked processes do not inherit stale tracing tags from            // Zygote.            Trace.setTracingEnabled(false, 0);            Zygote.nativeSecurityInit();            // Zygote process unmounts root storage spaces.            Zygote.nativeUnmountStorageOnInit();            ZygoteHooks.stopZygoteNoThreadCreation();            if (startSystemServer) {                Runnable r = forkSystemServer(abiList, socketName, zygoteServer);                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the                // child (system_server) process.                if (r != null) {                    r.run();                    return;                }            }            // If the return value is null then this is the zygote process            // returning to the normal control flow.  If it returns a Runnable            // object then this is a blastula that has finished specializing.            caller = Zygote.initBlastulaPool();            if (caller == null) {                Log.i(TAG, "Accepting command socket connections");                // The select loop returns early in the child process after a fork and                // loops forever in the zygote.                caller = zygoteServer.runSelectLoop(abiList);            }        } catch (Throwable ex) {            Log.e(TAG, "System zygote died with exception", ex);            throw ex;        } finally {            zygoteServer.closeServerSocket();        }        // We're in the child process and have exited the select loop. Proceed to execute the        // command.        if (caller != null) {            caller.run();        }    }

可以发现zygoteServer进行了注册,那么看一下他收到消息之后会干什么
可以发现,这里有一个zygoteConnection.java类用于监听,里面有一个runnable实现,在runnable中实现了fork进程

   Runnable processOneCommand(ZygoteServer zygoteServer) {        String args[];        ZygoteArguments parsedArgs = null;        FileDescriptor[] descriptors;        try {            args = Zygote.readArgumentList(mSocketReader);            // TODO (chriswailes): Remove this and add an assert.            descriptors = mSocket.getAncillaryFileDescriptors();        } catch (IOException ex) {            throw new IllegalStateException("IOException on command socket", ex);        }        // readArgumentList returns null only when it has reached EOF with no available        // data to read. This will only happen when the remote socket has disconnected.        if (args == null) {            isEof = true;            return null;        }        int pid = -1;        FileDescriptor childPipeFd = null;        FileDescriptor serverPipeFd = null;        parsedArgs = new ZygoteArguments(args);        if (parsedArgs.mAbiListQuery) {            handleAbiListQuery();            return null;        }        if (parsedArgs.mPidQuery) {            handlePidQuery();            return null;        }        if (parsedArgs.mPreloadDefault) {            handlePreload();            return null;        }        if (parsedArgs.mPreloadPackage != null) {            handlePreloadPackage(parsedArgs.mPreloadPackage, parsedArgs.mPreloadPackageLibs,                    parsedArgs.mPreloadPackageLibFileName, parsedArgs.mPreloadPackageCacheKey);            return null;        }        if (parsedArgs.mApiBlacklistExemptions != null) {            handleApiBlacklistExemptions(parsedArgs.mApiBlacklistExemptions);            return null;        }        if (parsedArgs.mHiddenApiAccessLogSampleRate != -1) {            handleHiddenApiAccessLogSampleRate(parsedArgs.mHiddenApiAccessLogSampleRate);            return null;        }        if (parsedArgs.mPermittedCapabilities != 0 || parsedArgs.mEffectiveCapabilities != 0) {            throw new ZygoteSecurityException("Client may not specify capabilities: "                    + "permitted=0x" + Long.toHexString(parsedArgs.mPermittedCapabilities)                    + ", effective=0x" + Long.toHexString(parsedArgs.mEffectiveCapabilities));        }        Zygote.applyUidSecurityPolicy(parsedArgs, peer);        Zygote.applyInvokeWithSecurityPolicy(parsedArgs, peer);        Zygote.applyDebuggerSystemProperty(parsedArgs);        Zygote.applyInvokeWithSystemProperty(parsedArgs);        int[][] rlimits = null;        if (parsedArgs.mRLimits != null) {            rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);        }        int[] fdsToIgnore = null;        if (parsedArgs.mInvokeWith != null) {            try {                FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);                childPipeFd = pipeFds[1];                serverPipeFd = pipeFds[0];                Os.fcntlInt(childPipeFd, F_SETFD, 0);                fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};            } catch (ErrnoException errnoEx) {                throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);            }        }        /**         * In order to avoid leaking descriptors to the Zygote child,         * the native code must close the two Zygote socket descriptors         * in the child process before it switches from Zygote-root to         * the UID and privileges of the application being launched.         *         * In order to avoid "bad file descriptor" errors when the         * two LocalSocket objects are closed, the Posix file         * descriptors are released via a dup2() call which closes         * the socket and substitutes an open descriptor to /dev/null.         */        int [] fdsToClose = { -1, -1 };        FileDescriptor fd = mSocket.getFileDescriptor();        if (fd != null) {            fdsToClose[0] = fd.getInt$();        }        fd = zygoteServer.getZygoteSocketFileDescriptor();        if (fd != null) {            fdsToClose[1] = fd.getInt$();        }        fd = null;        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);        try {            if (pid == 0) {                // in child                zygoteServer.setForkChild();                zygoteServer.closeServerSocket();                IoUtils.closeQuietly(serverPipeFd);                serverPipeFd = null;                return handleChildProc(parsedArgs, descriptors, childPipeFd,                        parsedArgs.mStartChildZygote);            } else {                // In the parent. A pid < 0 indicates a failure and will be handled in                // handleParentProc.                IoUtils.closeQuietly(childPipeFd);                childPipeFd = null;                handleParentProc(pid, descriptors, serverPipeFd);                return null;            }        } finally {            IoUtils.closeQuietly(childPipeFd);            IoUtils.closeQuietly(serverPipeFd);        }    }

通过zygoreConnection关联这些zygote和新创建的进程

ActivitySta ActivityMan Process ZygoteProcess ZygoteInit zygoteserver ZygoteConnection Zygote Zygote.cpp startSpecificActivityLocked startProcessLocked startProcessLocked final String entryPoint = "android.app.ActivityThread" 这里就得到了ActivityThread startProcess start start startViaZygote zygoteSendArgsAndGetResult openZygoteSocketIfNeeded 获得ZygoteState 在zygoteInit进程初始化的时候,创建了zygoteserver runSelectLoop 进行监听 acceptCommandPeer() createNewConnection() accept() processOneCommand() forkAndSpecialize nativeForkAndSpecialize ForkCommon() 进程的fork操作 SpecializeCommon()子进程调用执行一些初始化工作 ActivitySta ActivityMan Process ZygoteProcess ZygoteInit zygoteserver ZygoteConnection Zygote Zygote.cpp

Activity如何改变状态

SystemServer AMS ActivitySta ActivityDisplay ActivityStack startOtherServices setWindowManager setWindowManager ... ... SystemServer AMS ActivitySta ActivityDisplay ActivityStack
class AMS{    public void setWindowManager(WindowManagerService wm) {        synchronized (this) {            mWindowManager = wm;            mStackSupervisor.setWindowManager(wm);            mLockTaskController.setWindowManager(wm);        }    }   }

接着看一下他调用的setwindow方法

 class ActivityStackSupervisor{    void setWindowManager(WindowManagerService wm) {        synchronized (mService) {            mWindowManager = wm;            getKeyguardController().setWindowManager(wm);            mDisplayManager =                    (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);            mDisplayManager.registerDisplayListener(this, null);            mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);            Display[] displays = mDisplayManager.getDisplays();            for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {                final Display display = displays[displayNdx];                ActivityDisplay activityDisplay = new ActivityDisplay(this, display);                mActivityDisplays.put(display.getDisplayId(), activityDisplay);                calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);            }            mHomeStack = mFocusedStack = mLastFocusedStack = getDefaultDisplay().getOrCreateStack(                    WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);        }    } }

这里从栈中去取activityStack

    <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,            boolean onTop) {        if (!alwaysCreateStack(windowingMode, activityType)) {            T stack = getStack(windowingMode, activityType);            if (stack != null) {                return stack;            }        }        return createStack(windowingMode, activityType, onTop);    }

更多相关文章

  1. Android(安卓)Training - 网络操作(1) - 连接网络
  2. MAC OSX上SDK Manager无法下载Android(安卓)SDK5.0的解决方法
  3. [android] Activity 的生命周期 以及 横屏竖屏切换时 Activity
  4. Android(安卓)display架构分析四-msm_fb.c 函数和数据结构介绍
  5. android不公开的面试题偶!!!
  6. Okhttp的简单介绍和使用(一)
  7. ffmpeg入门教程之Android使用FFmpeg so(封装格式转换)
  8. SurfaceFlinger启动过程分析(一)
  9. 防止ListView变色

随机推荐

  1. Android之WebView篇
  2. Android 网络显示图片
  3. Android中的dispatchTouchEvent()、onInt
  4. Android关机界面代码
  5. Android签名制作apk
  6. Failure [INSTALL_FAILED_TEST_ONLY: ins
  7. 个人帐号密码信息管理(PAPIM)软件构想
  8. apk分享: Android应用更换皮肤功能的实现
  9. android volatile的使用
  10. android > android 发布各大市场