Android Framework核心服务联动

146 阅读6分钟

​一、系统启动与服务初始化全链路​

​1. Zygote进程到SystemServer的跃迁​

frameworks/base/cmds/app_process/app_main.cpp

`// app_main.cpp (Zygote进程)
int main(int argc, char** argv) {
    
    // 创建Binder线程池
    sp<ProcessState> proc(ProcessState::self());
    // 启动SystemServer进程
    if (startSystemServer) {
        pid_t pid = fork();
        if (pid == 0) {
            // 设置实时优先级(关键参数)
            setpriority(PRIO_PROCESS, 0, -20);
            // 跳转到SystemServer主函数
            SystemMain();
        }
    }
}`

值得注意的是:

Binder线程池初始化​​:ProcessState::self()->startThreadPool()创建Binder线程池

ade5bfde-e6f1-4d16-9ce7-d09d45801e04.png

如上代码将流程直接推到了ZygoInit.java

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

` /**
     * Performs Zygote process initialization. Loads and initializes commonly used classes.
     *
     * Most classes only cause a few hundred bytes to be allocated, but a few will allocate a dozen
     * Kbytes (in one case, 500+K).
     */
    private static void preloadClasses() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        InputStream is;
        try {
            is = new FileInputStream(PRELOADED_CLASSES);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
            return;
        }

        Log.i(TAG, "Preloading classes...");
        long startTime = SystemClock.uptimeMillis();

        // Drop root perms while running static initializers.
        final int reuid = Os.getuid();
        final int regid = Os.getgid();

        // We need to drop root perms only if we're already root. In the case of "wrapped"
        // processes (see WrapperInit), this function is called from an unprivileged uid
        // and gid.
        boolean droppedPriviliges = false;
        if (reuid == ROOT_UID && regid == ROOT_GID) {
            try {
                Os.setregid(ROOT_GID, UNPRIVILEGED_GID);
                Os.setreuid(ROOT_UID, UNPRIVILEGED_UID);
            } catch (ErrnoException ex) {
                throw new RuntimeException("Failed to drop root", ex);
            }

            droppedPriviliges = true;
        }

        try {
            BufferedReader br =
                    new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);

            int count = 0;
            int missingLambdaCount = 0;
            String line;
            while ((line = br.readLine()) != null) {
                // Skip comments and blank lines.
                line = line.trim();
                if (line.startsWith("#") || line.equals("")) {
                    continue;
                }

                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line);
                try {
                    // Load and explicitly initialize the given class. Use
                    // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups
                    // (to derive the caller's class-loader). Use true to force initialization, and
                    // null for the boot classpath class-loader (could as well cache the
                    // class-loader of this class in a variable).
                    Class.forName(line, true, null);
                    count++;
                } catch (ClassNotFoundException e) {
                    if (line.contains("$$Lambda$")) {
                        if (LOGGING_DEBUG) {
                            missingLambdaCount++;
                        }
                    } else {
                        Log.w(TAG, "Class not found for preloading: " + line);
                    }
                } catch (UnsatisfiedLinkError e) {
                    Log.w(TAG, "Problem preloading " + line + ": " + e);
                } catch (Throwable t) {
                    Log.e(TAG, "Error preloading " + line + ".", t);
                    if (t instanceof Error) {
                        throw (Error) t;
                    } else if (t instanceof RuntimeException) {
                        throw (RuntimeException) t;
                    } else {
                        throw new RuntimeException(t);
                    }
                }
                Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
            }

            Log.i(TAG, "...preloaded " + count + " classes in "
                    + (SystemClock.uptimeMillis() - startTime) + "ms.");
            if (LOGGING_DEBUG && missingLambdaCount != 0) {
                Log.i(TAG, "Unresolved lambda preloads: " + missingLambdaCount);
            }
        } catch (IOException e) {
            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
        } finally {
            IoUtils.closeQuietly(is);

            // Fill in dex caches with classes, fields, and methods brought in by preloading.
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches");
            runtime.preloadDexCaches();
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            // If we are profiling the boot image, reset the Jit counters after preloading the
            // classes. We want to preload for performance, and we can use method counters to
            // infer what clases are used after calling resetJitCounters, for profile purposes.
            if (shouldProfileBootClasspath()) {
                Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ResetJitCounters");
                VMRuntime.resetJitCounters();
                Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
            }

            // Bring back root. We'll need it later if we're in the zygote.
            if (droppedPriviliges) {
                try {
                    Os.setreuid(ROOT_UID, ROOT_UID);
                    Os.setregid(ROOT_GID, ROOT_GID);
                } catch (ErrnoException ex) {
                    throw new RuntimeException("Failed to restore root", ex);
                }
            }
        }
    }`
    
​2. SystemServer服务启动时序​

进入SystemServer之后,执行run方法

private void run() {
    TimingsTraceAndSlog t = new TimingsTraceAndSlog();
    try {
        t.traceBegin("InitBeforeStartServices");

        // Record the process start information in sys props.
        SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
        SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
        SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));

        EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
                mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);

        // Set the device's time zone (a system property) if it is not set or is invalid.
        SystemTimeZone.initializeTimeZoneSettingsIfRequired();

        // 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.forceSafeLabels();

        // 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!");
        final long uptimeMillis = SystemClock.elapsedRealtime();
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
        if (!mRuntimeRestart) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                    FrameworkStatsLog
                            .BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,
                    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'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();

        // 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);

        SystemServiceRegistry.sEnableServiceNotFoundWtf = true;

        // Initialize native services.
        System.loadLibrary("android_servers");

        // Allow heap / perf profiling.
        initZygoteChildHeapProfiling();

        // Debug builds - spawn a thread to monitor for fd leaks.
        if (Build.IS_DEBUGGABLE) {
            spawnFdLeakCheckThread();
        }

        // Check whether we failed to shut down last time we tried.
        // This call may not return.
        performPendingShutdown();

        // Initialize the system context.
        createSystemContext();

        // Call per-process mainline module initialization.
        ActivityThread.initializeMainlineModules();

        // Sets the dumper service
        ServiceManager.addService("system_server_dumper", mDumper);
        mDumper.addDumpable(this);

        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        mSystemServiceManager.setStartInfo(mRuntimeRestart,
                mRuntimeStartElapsedTime, mRuntimeStartUptime);
        mDumper.addDumpable(mSystemServiceManager);

        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        SystemServerInitThreadPool tp = SystemServerInitThreadPool.start();
        mDumper.addDumpable(tp);

        // Lazily load the pre-installed system font map in SystemServer only if we're not doing
        // the optimized font loading in the FontManagerService.
        if (!com.android.text.flags.Flags.useOptimizedBoottimeFontLoading()
                && Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
            Slog.i(TAG, "Loading pre-installed system font map.");
            Typeface.loadPreinstalledSystemFontMap();
        }

        // Attach JVMTI agent if this is a debuggable build and the system property is set.
        if (Build.IS_DEBUGGABLE) {
            // Property is of the form "library_path=parameters".
            String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
            if (!jvmtiAgent.isEmpty()) {
                int equalIndex = jvmtiAgent.indexOf('=');
                String libraryPath = jvmtiAgent.substring(0, equalIndex);
                String parameterList =
                        jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
                // Attach the agent.
                try {
                    Debug.attachJvmtiAgent(libraryPath, parameterList, null);
                } catch (Exception e) {
                    Slog.e("System", "*************************************************");
                    Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
                }
            }
        }
    } finally {
        t.traceEnd();  // InitBeforeStartServices
    }

    // Setup the default WTF handler
    RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);

    // Start services.
    try {
        t.traceBegin("StartServices");
        startBootstrapServices(t);
        startCoreServices(t);
        startOtherServices(t);
        startApexServices(t);
        // Only update the timeout after starting all the services so that we use
        // the default timeout to start system server.
        updateWatchdogTimeout(t);
        CriticalEventLog.getInstance().logSystemServerStarted();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        t.traceEnd(); // StartServices
    }

    StrictMode.initVmDefaults(null);

    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        final long uptimeMillis = SystemClock.elapsedRealtime();
        FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_READY,
                uptimeMillis);
        final long maxUptimeMillis = 60 * 1000;
        if (uptimeMillis > maxUptimeMillis) {
            Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                    "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
        }
    }

    // Set binder transaction callback after starting system services
    Binder.setTransactionCallback(new IBinderCallback() {
        @Override
        public void onTransactionError(int pid, int code, int flags, int err) {
            mActivityManagerService.frozenBinderTransactionDetected(pid, code, flags, err);
        }
    });

    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

如上代码,可以持续优化,所有的核心服务开始在此处启动,其中包括AMS,WMS等服务,其中WMS和AMS依赖关系如下:

  • WMS初始化需AMS注册窗口管理接口(ServiceManager.addService("window", wms)
  • PMS需等待Installer服务就绪(mInstaller = mSystemServiceManager.startService(Installer.class)

接下来,进入AMS,WMS,PMS等交互全链路

二、AMS-WMS-PMS交互全链路​

​1. Activity启动触发窗口创建​
  • ​调用链路​​:
    ActivityThread.handleLaunchActivity()ActivityManagerService.attachApplication()

ActivityThread:frameworks/base/core/java/android/app/ActivityThread.java

/**
 * Extended implementation of activity launch. Used when server requests a launch or relaunch.
 */
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
    mSomeActivitiesChanged = true;

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

    // Make sure we are running with the most recent config and resource paths.
    applyPendingApplicationInfoChanges(r.activityInfo.packageName);
    mConfigurationController.handleConfigurationChanged(null, null);
    updateDeviceIdForNonUIContexts(deviceId);

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

    // Initialize before creating the activity
    if (ThreadedRenderer.sRendererEnabled
            && (r.activityInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
        HardwareRenderer.preload();
    }
    WindowManagerGlobal.initialize();

    // Hint the GraphicsEnvironment that an activity is launching on the process.
    GraphicsEnvironment.hintActivityLaunch();

    final Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
        r.createdConfig = new Configuration(mConfigurationController.getConfiguration());
        reportSizeConfigurations(r);
        if (!r.activity.mFinished && pendingActions != null) {
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
            pendingActions.setCallOnPostCreate(true);
        }
    } else {
        // If there was an error, for any reason, tell the activity manager to stop us.
        ActivityClient.getInstance().finishActivity(r.token, Activity.RESULT_CANCELED,
                null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
    }

    return a;
}

AMS:

image.png

​2. WMS窗口绑定​

WMS启动整体流程:

1.SystemServer: mWindowManagerService = WindowManagerService.main( mContext, mDisplayManager, mPackageManagerService, mPowerManagerService); ServiceManager.addService(Context.WINDOW_SERVICE, mWindowManagerService);

2.创建DisplayContent​​:初始化物理/虚拟屏幕的显示区域(DisplayContent.java)

3.​​注册窗口策略​​:PhoneWindowManager设置系统窗口规则(如状态栏位置)

4.​​绑定SurfaceFlinger​​:通过SurfaceComposerClient建立与图形子系统的连接

5 `// WindowManagerGlobal.java public void addView(View view, LayoutParams params) { // 1. 创建WindowState WindowState win = new WindowState(...); // 2. 调用WMS接口 mWindowManager.addView(win, params); }

// WindowManagerService.java (JNI层)
static void android_view_WindowManager_addView(JNIEnv* env, jobject clazz, jobject view, jobject attrs) {
    sp<IWindowManager> wms = IWindowManager::asBinder(getService("window"));
    wms->addWindow(...); // Binder调用WMS
}`

6.

`  
// WindowManagerService.cpp
status_t WindowManagerService::addWindow(...) {
    sp<WindowState> win = new WindowState(...);
    mWindows.add(win); // 添加到窗口列表
    mLayoutNeeded = true; // 触发布局更新
} `

7. `

3. 图形合成机制
```cpp
// SurfaceFlinger.cpp
void SurfaceFlinger::composeSurfaces() {
    for (auto& layer : mLayers) {
        if (layer->isVisible()) {
            layer->latchBuffer(); // 获取GraphicBuffer
            mHwc->setLayerBuffer(layer->getHandle(), buffer); // 提交给HWC
        }
    }
    mHwc->commit(); // 提交合成指令
} `

WMS角色​​:通过SurfaceControl.setLayer()调整窗口Z-order,触发SurfaceFlinger重新排序

三,PMS全流程解析

1.PMS启动流程:

` // SystemServer.java
private void startBootstrapServices() {
    mPackageManagerService = PackageManagerService.main(
        mContext, mInstaller, mFactoryTestMode != FactoryTest.OFF, mOnlyCore);
    ServiceManager.addService("package", mPackageManagerService);
}

// PackageManagerService.java
public static PackageManagerService main(...) {
    PackageManagerService pms = new PackageManagerService(...);
    pms.mInstaller = mSystemServiceManager.startService(Installer.class); // 依赖Installer
    pms.scanPackagesLI(); // 扫描已安装应用
    return pms;
} `

2. APK解析与安装​​

    `// PackageParser.java
    public Package parsePackage(File apkFile, int flags) {
        // 1. 解析AndroidManifest.xml
        XmlPullParser parser = Xml.resolvePullParser(manifestFile);
        mPackage = new Package(...);
        // 2. 提取权限声明
        mPackage.mPermissions = parsePermissions(parser);
        // 3. 生成应用信息
        mPackage.applicationInfo = generateApplicationInfo();
    }`
    

3.权限校验流程

` // PackageManagerService.java
int checkUidPermission(String permName, int uid) {
    synchronized (mLock) {
        return mSettings.getPermissionsState().checkUidPermission(permName, uid);
    }
}

// 权限状态检查(PermissionsState.java)
int checkUidPermission(String permName, int uid) {
    UidState uidState = mUidStates.get(uid);
    return uidState != null ? uidState.checkPermission(permName) : PERMISSION_DENIED;
} `

关键数据结构:

    `// PackageInfo.java
    public static class Package {
        String packageName;          // 包名
        int versionCode;             // 版本号
        Signature[] signatures;      // 签名信息
        Permission[] permissions;    // 声明权限
    }`

联动示例图:

image.png

联动的基础是IPC的通信,这里就必须介绍一下Binder

Binder通信详细介绍在这里

说到这里,关于WMS有一个很重要的组成部分(专题)

SurfaceFlinger合成引擎