推荐 最新
chole

Android源码分析 - SystemServer(下)

开篇本篇以android-11.0.0_r25作为基础解析上一篇文章Android源码分析 - SystemServer(上)我们分析了SystemServer进程是怎么被启动起来的,今天这篇,我们来分析SystemServer进程启动后做了什么main我们上一章中讲到,Zygote进程fork出子进程后,最终调用了SystemServer.main方法,SystemServer源代码在frameworks/base/services/java/com/android/server/SystemServer.java中,我们来看看做了什么public static void main(String[] args) { new SystemServer().run(); }构造方法非常简单,就是先new了一个SystemServer对象,然后调用它的run方法,我们先看一下构造方法public SystemServer() { //工厂模式 mFactoryTestMode = FactoryTest.getMode(); ... //记录启动信息 //记录是否经历过重启 mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed")); }工厂模式首先,先从系统属性中获取工厂模式级别,有三种属性:FACTORY_TEST_OFF:正常模式FACTORY_TEST_LOW_LEVEL:低级别工厂模式,在此模式下,很多Service不会启动FACTORY_TEST_HIGH_LEVEL:高级别工厂模式,此模式与正常模式基本相同,略有区别它们被定义在frameworks/base/core/java/android/os/FactoryTest.java中run紧接着便开始执行run方法private void run() { ... //记录启动信息 //如果没有设置时区,将时区设置为GMT 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 (!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", ""); } //Binder事务发生阻塞时发出警告 Binder.setWarnOnBlocking(true); //PackageManager相关 PackageItemInfo.forceSafeLabels(); ... //设置虚拟机库文件libart.so SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); //清除虚拟机内存增长上限,以获得更多内存 VMRuntime.getRuntime().clearGrowthLimit(); // Some devices rely on runtime fingerprint generation, so make sure // we've defined it before booting further. Build.ensureFingerprintProperty(); //设置在访问环境变量前,需要明确指定用户 Environment.setUserRequired(true); //设置标记,当发生BadParcelableException异常时保守处理,不要抛出异常 BaseBundle.setShouldDefuse(true); //设置异常跟踪 Parcel.setStackTraceParceling(true); //确保Binder调用优先级总为前台优先级 BinderInternal.disableBackgroundScheduling(true); //设置Binder线程池最大数量 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); //以当前线程作为MainLooper准备 Looper.prepareMainLooper(); Looper.getMainLooper().setSlowLogThresholdMs( SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS); SystemServiceRegistry.sEnableServiceNotFoundWtf = true; //加载android_servers.so库 System.loadLibrary("android_servers"); //标记该进程的堆可分析 initZygoteChildHeapProfiling(); //Debug选项 - 开启一个线程用来监测FD泄漏 if (Build.IS_DEBUGGABLE) { spawnFdLeakCheckThread(); } //检查上次关机过程中是否失败 performPendingShutdown(); //初始化System Context createSystemContext(); //创建并设置一些每个进程启动时都需要的一些模块 (TelephonyServiceManager, StatsServiceManager) ActivityThread.initializeMainlineModules(); //创建SystemServiceManager(管理所有的系统Service) mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime); //将SystemServiceManager作为本地进程Service使用 LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); //为初始化任务准备线程池 SystemServerInitThreadPool.start(); ... //设置默认异常处理程序 RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf); ... //启动引导服务 startBootstrapServices(t); //启动核心服务 startCoreServices(t); //启动其他服务 startOtherServices(t); ... //严格模式初始化虚拟机策略 StrictMode.initVmDefaults(null); ... //进入Looper死循环,等待Handler事件 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }可以看到,run方法主要做了以下工作检查并设置各种参数handler创建SystemContext创建SystemServiceManager启动服务Looper循环其中,创建SystemContext这一步是由ContextImpl完成的,等后面分析到的时候在详细去看,Looper也是,我们将重点放在启动服务上启动服务启动服务分为三步,首先是启动引导服务,其次是启动核心服务,最后是启动其他服务,我们先从引导服务开始由于启动的服务太多了,我们只介绍一些我们比较熟悉的服务startBootstrapServicesprivate void startBootstrapServices(@NonNull TimingsTraceAndSlog t) { ... //看门狗 final Watchdog watchdog = Watchdog.getInstance(); watchdog.start(); ... final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig"; //读取系统配置 SystemServerInitThreadPool.submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG); ... //Installer服务(实际上是与installd跨进程通信) Installer installer = mSystemServiceManager.startService(Installer.class); ... //创建 ATMS & AMS ActivityTaskManagerService atm = mSystemServiceManager.startService( ActivityTaskManagerService.Lifecycle.class).getService(); mActivityManagerService = ActivityManagerService.Lifecycle.startService( mSystemServiceManager, atm); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); mWindowManagerGlobalLock = atm.getGlobalLock(); ... //电源管理服务,后面有其他服务依赖它,所以需要较早启动 mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); ... mActivityManagerService.initPowerManagement(); ... //灯光服务 mSystemServiceManager.startService(LightsService.class); ... //显示管理服务 mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); ... //阶段100 mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); ... //创建PMS try { Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain"); mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); } finally { Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain"); } //捕获dex load行为 SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService); //是否首次启动 mFirstBoot = mPackageManagerService.isFirstBoot(); //获取PMS mPackageManager = mSystemContext.getPackageManager(); ... //用户管理服务 mSystemServiceManager.startService(UserManagerService.LifeCycle.class); ... //初始化属性缓存 AttributeCache.init(mSystemContext); ... //注册各种系统服务 mActivityManagerService.setSystemProcess(); ... //使用AMS完成看门狗的设置,并监听重新启动 watchdog.init(mSystemContext, mActivityManagerService); ... //设置调度策略 mDisplayManagerService.setupSchedulerPolicies(); ... //在单独线程中启动传感器服务 mSensorServiceStart = SystemServerInitThreadPool.submit(() -> { TimingsTraceAndSlog traceLog = TimingsTraceAndSlog.newAsyncLog(); traceLog.traceBegin(START_SENSOR_SERVICE); startSensorService(); traceLog.traceEnd(); }, START_SENSOR_SERVICE); ... } startCoreServices private void startCoreServices(@NonNull TimingsTraceAndSlog t) { ... //电池电量服务,依赖LightsService mSystemServiceManager.startService(BatteryService.class); ... //应用统计服务 mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); ... } startOtherServices private void startOtherServices(@NonNull TimingsTraceAndSlog t) { ... //AccountManagerService - 账户管理 mSystemServiceManager.startService(ACCOUNT_SERVICE_CLASS); ... //ContentService - 内容服务 mSystemServiceManager.startService(CONTENT_SERVICE_CLASS); ... //加载SettingProvider mActivityManagerService.installSystemProviders(); ... //DropBox日志服务 mSystemServiceManager.startService(DropBoxManagerService.class); ... //震动服务 vibrator = new VibratorService(context); ServiceManager.addService("vibrator", vibrator); ... //时钟/闹钟服务 mSystemServiceManager.startService(new AlarmManagerService(context)); //输入服务 inputManager = new InputManagerService(context); ... //等待传感器服务准备完毕 ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE); mSensorServiceStart = null; //启动WindowManagerService wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore, new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager); ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO); ServiceManager.addService(Context.INPUT_SERVICE, inputManager, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL); ... mActivityManagerService.setWindowManager(wm); ... wm.onInitReady(); ... //HIDL services SystemServerInitThreadPool.submit(() -> { startHidlServices(); }, START_HIDL_SERVICES); ... //关联WMS,启动输入服务 inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback()); inputManager.start(); ... mDisplayManagerService.windowManagerAndInputReady(); ... //有蓝牙功能且非低级工厂模式,启动蓝牙服务 if (mFactoryTestMode == FactoryTest.FACTORY_TEST_LOW_LEVEL) { ... } else if (!context.getPackageManager().hasSystemFeature (PackageManager.FEATURE_BLUETOOTH)) { ... } else { mSystemServiceManager.startService(BluetoothService.class); } ... //输入法/无障碍服务 if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { if (InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) { mSystemServiceManager.startService( MultiClientInputMethodManagerService.Lifecycle.class); } else { mSystemServiceManager.startService(InputMethodManagerService.Lifecycle.class); } mSystemServiceManager.startService(ACCESSIBILITY_MANAGER_SERVICE_CLASS); } wm.displayReady(); //存储相关服务 if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) { mSystemServiceManager.startService(STORAGE_MANAGER_SERVICE_CLASS); storageManager = IStorageManager.Stub.asInterface( ServiceManager.getService("mount")); mSystemServiceManager.startService(STORAGE_STATS_SERVICE_CLASS); } } //UIMode服务(夜间模式,驾驶模式等) mSystemServiceManager.startService(UiModeManagerService.class); ... //执行磁盘清理工作,释放磁盘空间 mPackageManagerService.performFstrimIfNeeded(); if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) { ... final boolean hasPdb = !SystemProperties.get(PERSISTENT_DATA_BLOCK_PROP).equals(""); ... if (hasPdb || OemLockService.isHalPresent()) { //OEM锁服务 mSystemServiceManager.startService(OemLockService.class); } ... if (!isWatch) { //状态栏管理服务 statusBar = new StatusBarManagerService(context); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } //网络相关服务 ConnectivityModuleConnector.getInstance().init(context); NetworkStackClient.getInstance().init(); networkManagement = NetworkManagementService.create(context); ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement); ipSecService = IpSecService.create(context, networkManagement); ServiceManager.addService(Context.IPSEC_SERVICE, ipSecService); //文本服务 mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class); mSystemServiceManager .startService(TextClassificationManagerService.Lifecycle.class); //网络相关服务 mSystemServiceManager.startService(NetworkScoreService.Lifecycle.class); networkStats = NetworkStatsService.create(context, networkManagement); ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats); networkPolicy = new NetworkPolicyManagerService(context, mActivityManagerService, networkManagement); ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy); if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI)) { mSystemServiceManager.startServiceFromJar( WIFI_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH); mSystemServiceManager.startServiceFromJar( WIFI_SCANNING_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH); } if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_RTT)) { mSystemServiceManager.startServiceFromJar( WIFI_RTT_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH); } if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_AWARE)) { mSystemServiceManager.startServiceFromJar( WIFI_AWARE_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH); } if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_WIFI_DIRECT)) { mSystemServiceManager.startServiceFromJar( WIFI_P2P_SERVICE_CLASS, WIFI_APEX_SERVICE_JAR_PATH); } if (context.getPackageManager().hasSystemFeature( PackageManager.FEATURE_LOWPAN)) { mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS); } if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) || mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS); } connectivity = new ConnectivityService( context, networkManagement, networkStats, networkPolicy); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity, /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL); networkPolicy.bindConnectivityManager(connectivity); ... //系统更新服务 ServiceManager.addService(Context.SYSTEM_UPDATE_SERVICE, new SystemUpdateManagerService(context)); ServiceManager.addService(Context.UPDATE_LOCK_SERVICE, new UpdateLockService(context)); //通知服务 mSystemServiceManager.startService(NotificationManagerService.class); SystemNotificationChannels.removeDeprecated(context); SystemNotificationChannels.createAll(context); notification = INotificationManager.Stub.asInterface( ServiceManager.getService(Context.NOTIFICATION_SERVICE)); ... //位置服务 mSystemServiceManager.startService(LocationManagerService.Lifecycle.class); ... //墙纸服务 if (context.getResources().getBoolean(R.bool.config_enableWallpaperService)) { mSystemServiceManager.startService(WALLPAPER_SERVICE_CLASS); } else { ... } //音频服务 if (!isArc) { mSystemServiceManager.startService(AudioService.Lifecycle.class); } else { String className = context.getResources() .getString(R.string.config_deviceSpecificAudioService); mSystemServiceManager.startService(className + "$Lifecycle"); } ... //ADB服务 mSystemServiceManager.startService(ADB_SERVICE_CLASS); //USB服务 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST) || mPackageManager.hasSystemFeature( PackageManager.FEATURE_USB_ACCESSORY) || isEmulator) { mSystemServiceManager.startService(USB_SERVICE_CLASS); } //微件(小组件)服务 if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS) || context.getResources().getBoolean(R.bool.config_enableAppWidgetService)) { mSystemServiceManager.startService(APPWIDGET_SERVICE_CLASS); } ... //Android10新增,用于报告来自运行时模块的信息 ServiceManager.addService("runtime", new RuntimeService(context)); ... //App后台Dex优化 BackgroundDexOptService.schedule(context); ... } ... //相机服务 if (!disableCameraService) { mSystemServiceManager.startService(CameraServiceProxy.class); } //进入安全模式 if (safeMode) { mActivityManagerService.enterSafeMode(); } //短信服务 mmsService = mSystemServiceManager.startService(MmsServiceBroker.class); ... //剪贴板服务 mSystemServiceManager.startService(ClipboardService.class); ... //调用各大服务的systemReady方法 vibrator.systemReady(); lockSettings.systemReady(); //阶段480 mSystemServiceManager.startBootPhase(t, SystemService.PHASE_LOCK_SETTINGS_READY); //阶段500 mSystemServiceManager.startBootPhase(t, SystemService.PHASE_SYSTEM_SERVICES_READY); wm.systemReady(); ... //手动更新Context Configuration final Configuration config = wm.computeNewConfiguration(DEFAULT_DISPLAY); DisplayMetrics metrics = new DisplayMetrics(); context.getDisplay().getMetrics(metrics); context.getResources().updateConfiguration(config, metrics); final Theme systemTheme = context.getTheme(); if (systemTheme.getChangingConfigurations() != 0) { systemTheme.rebase(); } mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); ... mPackageManagerService.systemReady(); mDisplayManagerService.systemReady(safeMode, mOnlyCore); mSystemServiceManager.setSafeMode(safeMode); //阶段520 mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY); ... //最后运行AMS.systemReady mActivityManagerService.systemReady(() -> { //阶段550 mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY); ... //阶段600 mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); ... }, t); }服务的启动是分阶段完成的,从0-100-480-500-520-550-600-1000,最后的阶段1000,是在AMS调用finishBooting方法后进入可以看到,启动的服务非常之多,不可能全看得完,其中最重要的几个:ActivityManagerService、WindowManagerService、PackageManagerService和InputManagerService,后面我们会慢慢看过去,在此之前,我们还是先看看服务启动的方式SystemServiceManager绝大部分的服务是通过SystemServiceManager启动的,它的源码路径为frameworks/base/services/core/java/com/android/server/SystemServiceManager.javastartService我们来看看这个类里的启动服务方法这个类中有三个方法用于启动Serivce,分别是:public SystemService startService(String className)public SystemService startServiceFromJar(String className, String path)public <T extends SystemService> T startService(Class<T> serviceClass)public void startService(@NonNull final SystemService service)实际上最后都是调用了最后一个方法先看参数为String的startService方法public SystemService startService(String className) { final Class<SystemService> serviceClass = loadClassFromLoader(className, this.getClass().getClassLoader()); return startService(serviceClass); } private static Class<SystemService> loadClassFromLoader(String className, ClassLoader classLoader) { try { return (Class<SystemService>) Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { ... } }实际上就是通过反射拿到类名对应的Class,再调用Class为参的startService方法startServiceFromJar实际上也是一样,只不过是先通过PathClassLoader加载了jar而已public SystemService startServiceFromJar(String className, String path) { PathClassLoader pathClassLoader = mLoadedPaths.get(path); if (pathClassLoader == null) { // NB: the parent class loader should always be the system server class loader. // Changing it has implications that require discussion with the mainline team. pathClassLoader = new PathClassLoader(path, this.getClass().getClassLoader()); mLoadedPaths.put(path, pathClassLoader); } final Class<SystemService> serviceClass = loadClassFromLoader(className, pathClassLoader); return startService(serviceClass); }接着我们看看Class为参数的startService方法public <T extends SystemService> T startService(Class<T> serviceClass) { final String name = serviceClass.getName(); // Create the service. if (!SystemService.class.isAssignableFrom(serviceClass)) { throw new RuntimeException("Failed to create " + name + ": service must extend " + SystemService.class.getName()); } final T service; try { Constructor<T> constructor = serviceClass.getConstructor(Context.class); service = constructor.newInstance(mContext); } catch (...) { ... } startService(service); return service; }看函数泛型我们就可以知道,这个方法只接受SystemService的子类,并且在方法的开头,还使用了isAssignableFrom方法做了类型校验,避免通过String反射获取的Class非SystemService的子类之后的逻辑也很简单,反射实例化对象,然后调用另一个以SystemService对象为参数的重载方法 public void startService(@NonNull final SystemService service) { mServices.add(service); try { service.onStart(); } catch (RuntimeException ex) { throw new RuntimeException("Failed to start service " + service.getClass().getName() + ": onStart threw an exception", ex); } }这个方法会将SystemService对象加入一个List中,然后调用它的onStart方法,通知SystemService自行处理启动startBootPhase因为各种服务之间是存在依赖关系的,所以Android将服务的启动划分了8个阶段:0-100-480-500-520-550-600-1000,而startBootPhase方法便是用来通知各个服务进行到哪一阶段了public void startBootPhase(@NonNull TimingsTraceAndSlog t, int phase) { if (phase <= mCurrentPhase) { throw new IllegalArgumentException("Next phase must be larger than previous"); } mCurrentPhase = phase; final int serviceLen = mServices.size(); for (int i = 0; i < serviceLen; i++) { final SystemService service = mServices.get(i); service.onBootPhase(mCurrentPhase); } if (phase == SystemService.PHASE_BOOT_COMPLETED) { SystemServerInitThreadPool.shutdown(); } }每进入到一个阶段,便会调用Service List中所有SystemService的onBootPhase方法,通知SystemService阶段变换,而当阶段达到1000 (PHASE_BOOT_COMPLETED) 时,就代表着所有的服务都已准备完毕,关闭SystemServerInitThreadPool线程池ServiceManager当服务被创建出来后,会调用ServiceManager.addService方法添加服务,以供其他地方使用这些服务addService有三个重载,最终调用的为:public static void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) { try { getIServiceManager().addService(name, service, allowIsolated, dumpPriority); } catch (RemoteException e) { Log.e(TAG, "error in addService", e); } }private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; }public static IServiceManager asInterface(IBinder obj) { if (obj == null) { return null; } // ServiceManager is never local return new ServiceManagerProxy(obj); }class ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { mRemote = remote; mServiceManager = IServiceManager.Stub.asInterface(remote); } public IBinder asBinder() { return mRemote; } ... public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority) throws RemoteException { mServiceManager.addService(name, service, allowIsolated, dumpPriority); } ... private IBinder mRemote; private IServiceManager mServiceManager; }从这里就能看出来ServiceManager实际上是一个单独的进程,名为servicemanager,它负责管理所有服务,使用了Binder IPC机制,我们调用addService方法实际上是调用了Binder Proxy的方法,他向/dev/binder中写入消息,在servicemanager进程中接收到了这个消息并处理这个请求关于Binder机制,我们随后便会分析它最终调用了frameworks/native/cmds/servicemanager/ServiceManager.cpp中的addService函数 Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) { auto ctx = mAccess->getCallingContext(); ... //添加服务 auto entry = mNameToService.emplace(name, Service { .binder = binder, .allowIsolated = allowIsolated, .dumpPriority = dumpPriority, .debugPid = ctx.debugPid, }); auto it = mNameToRegistrationCallback.find(name); if (it != mNameToRegistrationCallback.end()) { for (const sp<IServiceCallback>& cb : it->second) { entry.first->second.guaranteeClient = true; // permission checked in registerForNotifications cb->onRegistration(name, binder); } } return Status::ok(); }可以看到,最终通过service name和传过来的binder对象构造出一个Service结构体,并将其保存至mNameToService这个Map中,以供后面使用关于进程SystemServer启动的服务大多都运行在systemserver进程中,但也有一些例外譬如Installer服务,便是从init进程单独fork出了一个installd进程下面是它的rc文件,frameworks/native/cmds/installd/installd.rc service installd /system/bin/installd class main ...而在SystemServer进程中start的Installer,便是通过binder连接到installd进程提供服务源码路径frameworks/base/services/core/java/com/android/server/pm/Installer.java @Override public void onStart() { if (mIsolated) { mInstalld = null; } else { connect(); } } private void connect() { IBinder binder = ServiceManager.getService("installd"); if (binder != null) { try { binder.linkToDeath(new DeathRecipient() { @Override public void binderDied() { Slog.w(TAG, "installd died; reconnecting"); connect(); } }, 0); } catch (RemoteException e) { binder = null; } } if (binder != null) { mInstalld = IInstalld.Stub.asInterface(binder); try { invalidateMounts(); } catch (InstallerException ignored) { } } else { Slog.w(TAG, "installd not found; trying again"); BackgroundThread.getHandler().postDelayed(() -> { connect(); }, DateUtils.SECOND_IN_MILLIS); } }结束SystemServer启动了非常多的服务,并将这些服务添加到了ServiceManager中,我们又从中引申出了Binder机制,我们下一章便开始分析Binder

0
0
0
浏览量1935
万码学说

简历这么操作,让你与众不同!

在求职的道路上,简历是我们展示个人能力、经验和潜力最直观也是最重要的工具之一。1、五大常见错误,千万要小心!(1)一份简历,应聘多样岗位不同岗位对雇员的要求是不一样的。通用的简历,无法突出你与目标岗位的关联性,反而会降低竞争力。要基于每个不同岗位的需求,调整简历内容,突出与该职位相关的技能和经验。                                                                (2)模板滥用,配色缺乏审美高颜值的简历是求职的有力敲门砖,但滥用模板可能会导致配色混乱、排版杂乱,甚至是逻辑混乱。                                                                                         简历应选择简洁、专业的模板,并保持一致的配色方案。同时,注意选择合适的颜色和排版,以给HR营造专业、清晰的印象。                                                                                     (3)个人信息,不必过于暴露虽然简历需要提供足够的个人信息,但不要暴露过多不必要的隐私信息,比如:婚姻状况、家庭情况、身份证号等。要注意保护个人隐私,只提供与求职相关的信息,比如:联系方式、教育背景、科研经历、志愿活动和工作经验等。(4)经历杂乱,能力不够聚焦大家可能会有很多个人经历,但呈现在简历中,应该有舍有得、清晰明了、有逻辑地呈现。要避免杂乱地列举经历,基于目标岗位的能力要求,选择恰当的个人经历,并用相应的话术突出在这个经历中你的某几项与目标岗位需求匹配的能力,且需要为每个经历提供简洁的描述,强调你做事的结果和贡献。                                                                                                                                          (5)篇幅过长,错字病句标点如果简历篇幅过长并且逻辑性不强,可能会导致关键信息被埋没。要突出关键信息,避免在简历中包含冗长的段落和不必要的细节。一般情况,应届毕业生用一整页A4纸,大约写800-1000字即可。                                                                                                                                         此外,拼写、错字、病句、标点错误,在简历中非常常见,这是非常严重的低级错误,很容易被雇主判断为态度问题。                                                                                            写完简历之后,最好出声音读一遍,仔细校对。这些小错误,可能会给雇主留下不重视、不专业、不踏实、不仔细、不够关注细节的不好印象。 2、如何能让自己的简历脱颖而出?(1)STAR原则S(Situation)交代事件的背景,为什么会去做这件事?T(Task)自己承担的任务是什么,怎样在事情的背景下明确自己的任务。A(Action)自己都完成了些什么,为了完成任务,做了哪些事,为什么要这么做。R(Result)最终获得了何种成果?行动中收获了什么,有没有完成目标。我们来看一个例子: 大家是不是觉得写到这里就完成了呢?如果希望提高简历通过率,我们还可以继续对内容进行优化,不仅让内容符合STAR原则,还可以让内容更具备条理性。以下是进一步的优化结果: 那么STAR原则只能用在简历经历的描述吗?当然不是!在面试时,面试官可能就某段经历,请应聘者展开讲述。很多同学依然会使用STAR原则来描述,但这样的描述平铺直叙,缺乏吸引力。此时完全可以直奔主题,对个人经历进行先抑后扬的故事化重组。                                                                这个时候STAR原则就可以转为CAR原则(Chagllenge挑战、Action行动、Result成果)。例如:在XX基金公司任职期间,作为技术主要负责人我曾遇到一次重大挑战,当时公司B端微信小程序版本大迭代,不仅需要参与并把控前端开发事务,而且还需要整体对接后端开发人员及产品业务人员(Challenge挑战),于是我们几个部门负责人就一起商量,使用微信小程序开发框架,搭建项目架构,根据设计和产品需求,参与需求分析和功能设计,参与后端开发人员进行接口对接,实现数据的交互和展示(Action行动),最后完善小程序各项功能,提升用户体验,用户满意度比原来提升 12%(Result成果)。我觉得这件事既锻炼了我的团队协作能力,更让我对自己的潜力有十足的信心。(2)利用视觉化的方法A.数据与经历的可视化 在简历中使用数据体现经历,可以更加直观地展示经验和能力。 比如,你运营了一个公众号,就可以写,在校期间,运营什么公众号几个月,发表原创文章多少,原创字数累计多少,浏览量多少,用户新增多少,用户完读率多少,公转私多少,还可以进一步增加同比环比数据。一定要学会挖掘数据化的成果,这不仅可以让HR更快地了解你的成就,还能使你的简历更具备说服力。B. 图像化的处理在设计简历时,合理运用颜色、图标和排版,能够使你的简历更具吸引力。但要注意保持简洁和专业,避免过多的花哨元素。一般是选择一个主色调,并在整个简历中保持一致,以营造统一的视觉效果。整个页面所有色彩元素最多不要超过三种。此外,图标可以用来突出你的技能或特长。 比如,如果你擅长多种编程语言,可以用相应的图标来表示每种语言的熟练程度。这样,HR可以在短时间内快速了解你的技能结构。C. 有效利用模板选择一个干净、简洁但又有个性的模板,能够帮助你更好地展示个人信息。要适度地进行个性化调整,以突出你的独特之处。 注意!不要完全套用模板哦~需要构建自己的简历逻辑,将你的职业优势关键信息放置在显眼位置,并按照你自己的思路排布简历,不要简单地把自己的信息直接安到某个模板里。排列逻辑可以是时间轴倒叙,最近的工作、实习放在最前面,依次往后排,方便雇主尽快清晰的看到你现在的经历与匹配度;可以是按类别,比如按照实习、校园工作、科研经历、志愿活动这样排列;也可以是按能力排列,比如按照专业能力、综合能力这样排列。这样做,HR在浏览你的简历时,可以快速获取到你想要传达的最重要的信息。以上这些你都学会了吗?赶快按照上面的步骤和方法修改你的简历吧!如果你对优化简历仍有疑问,可以寻找万码小助手的帮助~ 祝大家在求职过程中取得成功!

2
0
0
浏览量679
chole

Android源码分析 - Framework层的ContentProvider全解析

开篇本篇以android-11.0.0_r25作为基础解析在四大组件中,可能我们平时用到最少的便是ContentProvider了,ContentProvider是用来帮助应用管理其自身和其他应用所存储数据的访问,并提供与其他应用共享数据的方法,使用ContentProvider可以安全的在应用之间共享和修改数据,比如说访问图库,通讯录等在之前的文章中,我们提到了ContentProvider的启动时机,不妨顺水推舟,干脆把这一块分析个明白,本篇文章并不会教大家怎样使用ContentProvider,只将精力集中在ContentProvider在系统层面的启动与交互上基础知识ContentResolver想要通过ContentProvider访问应用数据,我们通常需要借助ContentResolver的API,我们可以通过Context.getContentResolver方法获取其实例对象ContentResolver是一个抽象类,它的抽象方法由ContextImpl.ApplicationContentResolver继承实现,我们实际上获取到的也是这个实例对象Uri格式ContentProvider的使用需要先获得提供者的Uri,它的格式如下:Scheme:固定为content://Authority:为提供者在AndroidManifest里设置的android:authorities属性资源相对路径资源ID其中,资源相对路径和资源ID不是必须的,要看资源存储的数量及形式举个栗子,外部存储中某张图片的Uri为:content://media/external/images/media/${id},其中media为Authority,/external/images/media为外部存储图片的相对路径,id为这张图片资源在数据库中存储的id获取ContentProviderContentProvider作为共享数据的桥梁,最主要的几个功能无非是增、删、改、查,我们就以查作为入口来分析ContentProvider对象是怎么获取的//ContentResolver.query public final @Nullable Cursor query(final @RequiresPermission.Read @NonNull Uri uri, @Nullable String[] projection, @Nullable Bundle queryArgs, @Nullable CancellationSignal cancellationSignal) { ... //尝试获取unstableProvider IContentProvider unstableProvider = acquireUnstableProvider(uri); if (unstableProvider == null) { return null; } IContentProvider stableProvider = null; Cursor qCursor = null; try { ... try { //调用远程对象query qCursor = unstableProvider.query(mPackageName, mAttributionTag, uri, projection, queryArgs, remoteCancellationSignal); } catch (DeadObjectException e) { // The remote process has died... but we only hold an unstable // reference though, so we might recover!!! Let's try!!!! // This is exciting!!1!!1!!!!1 unstableProviderDied(unstableProvider); //尝试获取stableProvider stableProvider = acquireProvider(uri); if (stableProvider == null) { return null; } //调用远程对象query qCursor = stableProvider.query(mPackageName, mAttributionTag, uri, projection, queryArgs, remoteCancellationSignal); } if (qCursor == null) { return null; } // Force query execution. Might fail and throw a runtime exception here. qCursor.getCount(); ... // Wrap the cursor object into CursorWrapperInner object. //将qCursor和provider包装成CursorWrapperInner对象返回 final IContentProvider provider = (stableProvider != null) ? stableProvider : acquireProvider(uri); final CursorWrapperInner wrapper = new CursorWrapperInner(qCursor, provider); stableProvider = null; qCursor = null; return wrapper; } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity // Manager will kill this process shortly anyway. return null; } finally { //释放资源 if (qCursor != null) { qCursor.close(); } if (cancellationSignal != null) { cancellationSignal.setRemote(null); } if (unstableProvider != null) { releaseUnstableProvider(unstableProvider); } if (stableProvider != null) { releaseProvider(stableProvider); } } }我们可以将这个方法大致分成以下几个步骤:获取unstableProvider远程对象调用unstableProvider对象的query方法,获取qCursor如果query过程中远程对象死亡,尝试获取stableProvider并调用query方法获取qCursor获取stableProvider(如果之前没获取的话)将qCursor和stableProvider包装成CursorWrapperInner对象返回释放资源既然ContentProvider可以在应用之前共享数据,那它必然是支持跨进程的,没错,用的还是我们熟悉的Binder通信,IContentProvider对象即是给调用方进程使用的远程Binder对象,回顾这个方法我们发现,IContentProvider远程对象是通过acquireUnstableProvider或acquireProvider获取的,我们接下来看看这两个方法做了什么这里有一个关于unstable和stable的概念,对于通过这两种方式获取的ContentProvider分别会有unstableCount和stableCount两种引用计数,如果远程ContentProvider所在进程死亡,且其stableCount > 0的话,则会将其通过stable方式关联的调用方进程一同杀死,具体的流程我们会在后面分析 public final IContentProvider acquireUnstableProvider(Uri uri) { if (!SCHEME_CONTENT.equals(uri.getScheme())) { return null; } String auth = uri.getAuthority(); if (auth != null) { return acquireUnstableProvider(mContext, uri.getAuthority()); } return null; } public final IContentProvider acquireProvider(Uri uri) { if (!SCHEME_CONTENT.equals(uri.getScheme())) { return null; } final String auth = uri.getAuthority(); if (auth != null) { return acquireProvider(mContext, auth); } return null; } public final IContentProvider acquireUnstableProvider(String name) { if (name == null) { return null; } return acquireUnstableProvider(mContext, name); } public final IContentProvider acquireProvider(String name) { if (name == null) { return null; } return acquireProvider(mContext, name); } // ContextImpl.ApplicationContentResolver 内实现 protected IContentProvider acquireUnstableProvider(Context c, String auth) { return mMainThread.acquireProvider(c, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), false); } // ContextImpl.ApplicationContentResolver 内实现 protected IContentProvider acquireProvider(Context context, String auth) { return mMainThread.acquireProvider(context, ContentProvider.getAuthorityWithoutUserId(auth), resolveUserIdFromAuthority(auth), true); }ActivityThread.acquireProviderAndroid系统是通过Authority来区分不同的ContentProvider的,经过一些简单的判断处理后,最终调用了ActivityThread.acquireProvider方法去获取ContentProvider,而acquireUnstableProvider和acquireProvider的区别只是最后一个布尔值入参不同罢了 public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) { //尝试从本地缓存中获取ContentProvider对象 final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); if (provider != null) { return provider; } // There is a possible race here. Another thread may try to acquire // the same provider at the same time. When this happens, we want to ensure // that the first one wins. // Note that we cannot hold the lock while acquiring and installing the // provider since it might take a long time to run and it could also potentially // be re-entrant in the case where the provider is in the same process. ContentProviderHolder holder = null; try { synchronized (getGetProviderLock(auth, userId)) { //使用AMS获取ContentProvider对象 holder = ActivityManager.getService().getContentProvider( getApplicationThread(), c.getOpPackageName(), auth, userId, stable); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } if (holder == null) { ... return null; } // Install provider will increment the reference count for us, and break // any ties in the race. //安装ContentProvider holder = installProvider(c, holder, holder.info, true /*noisy*/, holder.noReleaseNeeded, stable); return holder.provider; }这个方法大概做了以下几件事:首先从缓存中尝试获取IContentProvider对象使用AMS获取ContentProviderHolder对象安装ContentProvider返回IContentProvider对象ActivityThread.acquireExistingProvider我们首先看通过acquireExistingProvider方法尝试从缓存中获取IContentProvider对象public final IContentProvider acquireExistingProvider( Context c, String auth, int userId, boolean stable) { synchronized (mProviderMap) { //从缓存Map中查找 final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { return null; } IContentProvider provider = pr.mProvider; IBinder jBinder = provider.asBinder(); //判断远端进程是否已被杀死 if (!jBinder.isBinderAlive()) { // The hosting process of the provider has died; we can't // use this one. //清理ContentProvider handleUnstableProviderDiedLocked(jBinder, true); return null; } // Only increment the ref count if we have one. If we don't then the // provider is not reference counted and never needs to be released. ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc != null) { //更新引用计数 incProviderRefLocked(prc, stable); } return provider; } }首先通过Authority和userId来从Map中查找是否已存在对应的ProviderClientRecord对象,然后从中取出IContentProvider对象,再检查其中的远程Binder对象是否已被杀死,最后一切无误,增加ContentProvider的引用计数AMS.getContentProvider如果这一步没有获取到,程序会继续从AMS获取ContentProviderpublic final ContentProviderHolder getContentProvider( IApplicationThread caller, String callingPackage, String name, int userId, boolean stable) { if (caller == null) { String msg = "null IApplicationThread when getting content provider " + name; Slog.w(TAG, msg); throw new SecurityException(msg); } // The incoming user check is now handled in checkContentProviderPermissionLocked() to deal // with cross-user grant. final int callingUid = Binder.getCallingUid(); if (callingPackage != null && mAppOpsService.checkPackage(callingUid, callingPackage) != AppOpsManager.MODE_ALLOWED) { throw new SecurityException("Given calling package " + callingPackage + " does not match caller's uid " + callingUid); } return getContentProviderImpl(caller, name, null, callingUid, callingPackage, null, stable, userId); }经过一些检查后调用getContentProviderImpl方法,这个方法有点长,我们分段来看private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; ProviderInfo cpi = null; boolean providerRunning = false; synchronized(this) { //获取调用方所在进程记录 ProcessRecord r = null; if (caller != null) { r = getRecordForAppLocked(caller); if (r == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when getting content provider " + name); } } boolean checkCrossUser = true; // First check if this content provider has been published... //检查需要的ContentProvider是否已被发布 cpr = mProviderMap.getProviderByName(name, userId); // If that didn't work, check if it exists for user 0 and then // verify that it's a singleton provider before using it. //如果没找到,尝试从系统用户中查找已发布的ContentProvider //并确保它是可用的单例组件,条件如下: //是用户级应用程序且组件设置了单例flag且拥有INTERACT_ACROSS_USERS权限 或 App运行在system进程中 或 组件设置了单例flag且是同一个App if (cpr == null && userId != UserHandle.USER_SYSTEM) { cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM); if (cpr != null) { cpi = cpr.info; if (isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags) && isValidSingletonCall(r == null ? callingUid : r.uid, cpi.applicationInfo.uid)) { userId = UserHandle.USER_SYSTEM; checkCrossUser = false; } else { cpr = null; cpi = null; } } } //判断ContentProvider所在进程是否已死亡 ProcessRecord dyingProc = null; if (cpr != null && cpr.proc != null) { providerRunning = !cpr.proc.killed; // Note if killedByAm is also set, this means the provider process has just been // killed by AM (in ProcessRecord.kill()), but appDiedLocked() hasn't been called // yet. So we need to call appDiedLocked() here and let it clean up. // (See the commit message on I2c4ba1e87c2d47f2013befff10c49b3dc337a9a7 to see // how to test this case.) if (cpr.proc.killed && cpr.proc.killedByAm) { Slog.wtf(TAG, cpr.proc.toString() + " was killed by AM but isn't really dead"); // Now we are going to wait for the death before starting the new process. dyingProc = cpr.proc; } } ... } ... }首先,第一部分,检查目标ContentProvider是否已被发布并记录在了mProviderMap中,注意这里的mProviderMap是AMS中的一个成员变量,一系列Map的一个集合,和ActivityThread中的mProviderMap不是一个东西。如果在当前用户中找不到,且当前用户不是系统用户(UserHandle.USER_SYSTEM == 0),则尝试从系统用户中查找合法可用的单例ContentProvider,符合以下任一一个条件的ContentProvider即可被视作单例ContentProvider:App是用户级应用程序(uid >= 10000)且ContentProvider组件设置了单例flag(android:singleUser)且App拥有INTERACT_ACROSS_USERS权限App运行在system进程中ContentProvider组件设置了单例flag(android:singleUser)且是同一个App至于为什么跨用户访问需要单例这个条件,这个和多用户相关,我也不是很清楚,以后如果分析到了多用户这块再回来补充。目前国内厂商的应用分身、手机分身功能大部分用的就是多用户技术接着通过目标ContentProviderRecord是否存在和其所在进程是否还存活判断目标ContentProvider是否在运行中 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; ProviderInfo cpi = null; boolean providerRunning = false; synchronized(this) { ... //ContentProvider正在运行中 if (providerRunning) { cpi = cpr.info; //如果此ContentProvider可以在调用者进程中直接运行(同一个App的同进程 或 同一个App且Provider组件支持多进程) //直接返回一个新的ContentProviderHolder让调用者进程自己启动ContentProvider if (r != null && cpr.canRunHere(r)) { ... //权限检查 // This provider has been published or is in the process // of being published... but it is also allowed to run // in the caller's process, so don't make a connection // and just let the caller instantiate its own instance. ContentProviderHolder holder = cpr.newHolder(null); // don't give caller the provider object, it needs // to make its own. holder.provider = null; return holder; } // Don't expose providers between normal apps and instant apps try { if (AppGlobals.getPackageManager() .resolveContentProvider(name, 0 /*flags*/, userId) == null) { return null; } } catch (RemoteException e) { } ... //权限检查 final long origId = Binder.clearCallingIdentity(); // In this case the provider instance already exists, so we can // return it right away. //获取连接并更新引用计数 conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag, stable); if (conn != null && (conn.stableCount+conn.unstableCount) == 1) { if (cpr.proc != null && r != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { // If this is a perceptible app accessing the provider, // make sure to count it as being accessed and thus // back up on the LRU list. This is good because // content providers are often expensive to start. //更新进程优先级 mProcessList.updateLruProcessLocked(cpr.proc, false, null); } } final int verifiedAdj = cpr.proc.verifiedAdj; //更新进程adj boolean success = updateOomAdjLocked(cpr.proc, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER); // XXX things have changed so updateOomAdjLocked doesn't actually tell us // if the process has been successfully adjusted. So to reduce races with // it, we will check whether the process still exists. Note that this doesn't // completely get rid of races with LMK killing the process, but should make // them much smaller. if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) { success = false; } maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name); // NOTE: there is still a race here where a signal could be // pending on the process even though we managed to update its // adj level. Not sure what to do about this, but at least // the race is now smaller. if (!success) { // Uh oh... it looks like the provider's process // has been killed on us. We need to wait for a new // process to be started, and make sure its death // doesn't kill our process. Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); //ContentProvider所在进程被杀了,更新引用计数 boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); //仍有别的地方对这个ContentProvider有引用,直接返回null(需要等待进程清理干净才能重启) if (!lastRef) { // This wasn't the last ref our process had on // the provider... we will be killed during cleaning up, bail. return null; } // We'll just start a new process to host the content provider //将运行状态标为false,使得重新启动ContentProvider所在进程 providerRunning = false; conn = null; dyingProc = cpr.proc; } else { cpr.proc.verifiedAdj = cpr.proc.setAdj; } Binder.restoreCallingIdentity(origId); } ... } ... }private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; ProviderInfo cpi = null; boolean providerRunning = false; synchronized(this) { ... //ContentProvider正在运行中 if (providerRunning) { cpi = cpr.info; //如果此ContentProvider可以在调用者进程中直接运行(同一个App的同进程 或 同一个App且Provider组件支持多进程) //直接返回一个新的ContentProviderHolder让调用者进程自己启动ContentProvider if (r != null && cpr.canRunHere(r)) { ... //权限检查 // This provider has been published or is in the process // of being published... but it is also allowed to run // in the caller's process, so don't make a connection // and just let the caller instantiate its own instance. ContentProviderHolder holder = cpr.newHolder(null); // don't give caller the provider object, it needs // to make its own. holder.provider = null; return holder; } // Don't expose providers between normal apps and instant apps try { if (AppGlobals.getPackageManager() .resolveContentProvider(name, 0 /*flags*/, userId) == null) { return null; } } catch (RemoteException e) { } ... //权限检查 final long origId = Binder.clearCallingIdentity(); // In this case the provider instance already exists, so we can // return it right away. //获取连接并更新引用计数 conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag, stable); if (conn != null && (conn.stableCount+conn.unstableCount) == 1) { if (cpr.proc != null && r != null && r.setAdj <= ProcessList.PERCEPTIBLE_LOW_APP_ADJ) { // If this is a perceptible app accessing the provider, // make sure to count it as being accessed and thus // back up on the LRU list. This is good because // content providers are often expensive to start. //更新进程优先级 mProcessList.updateLruProcessLocked(cpr.proc, false, null); } } final int verifiedAdj = cpr.proc.verifiedAdj; //更新进程adj boolean success = updateOomAdjLocked(cpr.proc, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER); // XXX things have changed so updateOomAdjLocked doesn't actually tell us // if the process has been successfully adjusted. So to reduce races with // it, we will check whether the process still exists. Note that this doesn't // completely get rid of races with LMK killing the process, but should make // them much smaller. if (success && verifiedAdj != cpr.proc.setAdj && !isProcessAliveLocked(cpr.proc)) { success = false; } maybeUpdateProviderUsageStatsLocked(r, cpr.info.packageName, name); // NOTE: there is still a race here where a signal could be // pending on the process even though we managed to update its // adj level. Not sure what to do about this, but at least // the race is now smaller. if (!success) { // Uh oh... it looks like the provider's process // has been killed on us. We need to wait for a new // process to be started, and make sure its death // doesn't kill our process. Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); //ContentProvider所在进程被杀了,更新引用计数 boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); //仍有别的地方对这个ContentProvider有引用,直接返回null(需要等待进程清理干净才能重启) if (!lastRef) { // This wasn't the last ref our process had on // the provider... we will be killed during cleaning up, bail. return null; } // We'll just start a new process to host the content provider //将运行状态标为false,使得重新启动ContentProvider所在进程 providerRunning = false; conn = null; dyingProc = cpr.proc; } else { cpr.proc.verifiedAdj = cpr.proc.setAdj; } Binder.restoreCallingIdentity(origId); } ... } ... }第二部分,如果目标ContentProvider正在运行中,首先检查目标ContentProvider是否可以在调用者进程中直接运行,需要满足以下任一一个条件:调用者和目标ContentProvider是同一个App中的同进程调用者和目标ContentProvider属同一个App且ContentProvider组件支持多进程(android:multiprocess)在这种情况下,直接返回一个新的ContentProviderHolder让调用者进程自己处理获得ContentProvider即可,具体逻辑在ActivityThread.installProvider方法中,后面会分析如果不满足这种情况,即调用方进程和目标ContentProvider不在一个进程中,需要跨进程调用,获取ContentProviderConnection连接并更新引用计数 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; ProviderInfo cpi = null; boolean providerRunning = false; synchronized(this) { ... //ContentProvider未在运行 if (!providerRunning) { //通过PMS获取ContentProvider信息 try { cpi = AppGlobals.getPackageManager(). resolveContentProvider(name, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, userId); } catch (RemoteException ex) { } if (cpi == null) { return null; } // If the provider is a singleton AND // (it's a call within the same user || the provider is a // privileged app) // Then allow connecting to the singleton provider boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags) && isValidSingletonCall(r == null ? callingUid : r.uid, cpi.applicationInfo.uid); if (singleton) { userId = UserHandle.USER_SYSTEM; } cpi.applicationInfo = getAppInfoForUser(cpi.applicationInfo, userId); ... //各项检查 ComponentName comp = new ComponentName(cpi.packageName, cpi.name); //通过Class(android:name属性)获取ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId); //此ContentProvider是第一次运行 boolean firstClass = cpr == null; if (firstClass) { final long ident = Binder.clearCallingIdentity(); ... //权限处理 try { //获取应用信息 ApplicationInfo ai = AppGlobals.getPackageManager(). getApplicationInfo( cpi.applicationInfo.packageName, STOCK_PM_FLAGS, userId); if (ai == null) { Slog.w(TAG, "No package info for content provider " + cpi.name); return null; } ai = getAppInfoForUser(ai, userId); //新建ContentProvider记录 cpr = new ContentProviderRecord(this, cpi, ai, comp, singleton); } catch (RemoteException ex) { // pm is in same process, this will never happen. } finally { Binder.restoreCallingIdentity(ident); } } else if (dyingProc == cpr.proc && dyingProc != null) { // The old stable connection's client should be killed during proc cleaning up, // so do not re-use the old ContentProviderRecord, otherwise the new clients // could get killed unexpectedly. //旧的ContentProvider进程在死亡过程中,不要复用旧的ContentProviderRecord,避免出现预期之外的问题 cpr = new ContentProviderRecord(cpr); // This is sort of "firstClass" firstClass = true; } //如果此ContentProvider可以在调用者进程中直接运行(同一个App的同进程 或 同一个App且Provider组件支持多进程) //直接返回一个新的ContentProviderHolder让调用者进程自己启动ContentProvider if (r != null && cpr.canRunHere(r)) { // If this is a multiprocess provider, then just return its // info and allow the caller to instantiate it. Only do // this if the provider is the same user as the caller's // process, or can run as root (so can be in any process). return cpr.newHolder(null); } // This is single process, and our app is now connecting to it. // See if we are already in the process of launching this // provider. //查找正在启动中的ContentProvider final int N = mLaunchingProviders.size(); int i; for (i = 0; i < N; i++) { if (mLaunchingProviders.get(i) == cpr) { break; } } // If the provider is not already being launched, then get it // started. //目标ContentProvider不在启动中 if (i >= N) { final long origId = Binder.clearCallingIdentity(); try { // Content provider is now in use, its package can't be stopped. //将App状态置为unstopped,设置休眠状态为false try { AppGlobals.getPackageManager().setPackageStoppedState( cpr.appInfo.packageName, false, userId); } catch (RemoteException e) { } catch (IllegalArgumentException e) { Slog.w(TAG, "Failed trying to unstop package " + cpr.appInfo.packageName + ": " + e); } // Use existing process if already started //获取目标ContentProvider所在进程记录 ProcessRecord proc = getProcessRecordLocked( cpi.processName, cpr.appInfo.uid, false); if (proc != null && proc.thread != null && !proc.killed) { //进程存活 if (!proc.pubProviders.containsKey(cpi.name)) { //将ContentProviderRecord保存到进程已发布ContentProvider列表中 proc.pubProviders.put(cpi.name, cpr); try { //调度ActivityThread直接安装ContentProvider proc.thread.scheduleInstallProvider(cpi); } catch (RemoteException e) { } } } else { //进程死亡 //启动App(App启动过程中会自动启动ContentProvider) proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, new HostingRecord("content provider", new ComponentName(cpi.applicationInfo.packageName, cpi.name)), ZYGOTE_POLICY_FLAG_EMPTY, false, false, false); if (proc == null) { ... return null; } } cpr.launchingApp = proc; //将目标ContentProvider添加到启动中列表 mLaunchingProviders.add(cpr); } finally { Binder.restoreCallingIdentity(origId); } } // Make sure the provider is published (the same provider class // may be published under multiple names). if (firstClass) { mProviderMap.putProviderByClass(comp, cpr); } mProviderMap.putProviderByName(name, cpr); //获取连接并更新引用计数 conn = incProviderCountLocked(r, cpr, token, callingUid, callingPackage, callingTag, stable); if (conn != null) { conn.waiting = true; } } grantImplicitAccess(userId, null /*intent*/, callingUid, UserHandle.getAppId(cpi.applicationInfo.uid)); } ... }第三部分,如果目标ContentProvider未在运行,先通过PMS获取ContentProvider信息,接着尝试通过Class(android:name属性)获取ContentProviderRecord,如果获取不到,说明这个ContentProvider是第一次运行(开机后),这种情况下需要新建ContentProviderRecord,如果获取到了,但是其所在进程被标记为正在死亡,此时同样需要新建ContentProviderRecord,不要复用旧的ContentProviderRecord,避免出现预期之外的问题接下来同样检查目标ContentProvider是否可以在调用者进程中直接运行,如果可以直接返回一个新的ContentProviderHolder让调用者进程自己启动获取ContentProvider接着检查正在启动中的ContentProvider列表,如果不在列表中,我们可能需要手动启动它,此时又有两种情况:ContentProvider所在进程已启动:如果进程已发布ContentProvider列表中不包含这个ContentProviderRecord,则将其添加到列表中,然后调用目标进程中的ApplicationThread.scheduleInstallProvider方法安装启动ContentProviderContentProvider所在进程未启动:启动目标进程,目标进程启动过程中会自动安装启动ContentProvider(ActivityThread.handleBindApplication方法中)最后更新mProviderMap,获取ContentProviderConnection连接并更新引用计数 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ContentProviderRecord cpr; ContentProviderConnection conn = null; ProviderInfo cpi = null; boolean providerRunning = false; // Wait for the provider to be published... final long timeout = SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS; boolean timedOut = false; synchronized (cpr) { while (cpr.provider == null) { //ContentProvider启动过程中进程死亡,返回null if (cpr.launchingApp == null) { ... return null; } try { //计算最大等待时间 final long wait = Math.max(0L, timeout - SystemClock.uptimeMillis()); if (conn != null) { conn.waiting = true; } //释放锁,等待ContentProvider启动完成 cpr.wait(wait); //等待时间已过,ContentProvider还是没能启动完成并发布,超时 if (cpr.provider == null) { timedOut = true; break; } } catch (InterruptedException ex) { } finally { if (conn != null) { conn.waiting = false; } } } } if (timedOut) { ... //超时处理 return null; } //返回新的ContentProviderHolder return cpr.newHolder(conn); }第四部分,如果ContentProvider已存在,直接新建一个ContentProviderHolder返回,如果ContentProvider之前不存在,现在正在启动中,则以当前时间加上CONTENT_PROVIDER_READY_TIMEOUT_MILLIS推算出一个超时时间,给目标ContentProviderRecord上锁后,调用wait方法等待,直到ContentProvider成功发布后notify解除wait状态(在AMS.publishContentProviders方法中,之后会分析到),或一直等待直到超时。wait状态解除后,判断内部ContentProvider是否已被赋值,如果没有,则可以断定超时,此时返回null,如有,则返回一个新的ContentProviderHolderActivityThread.installProvider由于这个方法同时包含了启动安装本地ContentProvider和获取安装远程ContentProvider的逻辑,所以放到后面启动ContentProvider章节里一起分析启动ContentProvider从前面的章节获取ContentProvider中,我们已经归纳出ContentProvider的启动分为两种情况,接着我们就来分析在这两种情况下,ContentProvider的启动路径进程已启动在进程已启动的情况下,如果进程已发布ContentProvider列表中不包含这个ContentProviderRecord,则将其添加到列表中,然后调用目标进程中的ApplicationThread.scheduleInstallProvider方法安装启动ContentProviderApplicationThread.scheduleInstallProvider会通过Hander发送一条what值为H.INSTALL_PROVIDER的消息,我们根据这个what值搜索,发现会走到ActivityThread.handleInstallProvider方法中,在这个方法内又会调用installContentProviders方法安装启动ContentProvider进程未启动在进程未启动的情况下,直接启动目标进程,在之前的文章 Android源码分析 - Activity启动流程(中) 里,我们分析了App的启动流程,其中有两个地方对启动ContentProvider至关重要AMS.attachApplicationLocked在这个方法中会调用generateApplicationProvidersLocked方法private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { ... //normalMode一般情况下均为true List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; ... } private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) { List<ProviderInfo> providers = null; try { //通过PMS获取App中同一个进程内的所有的ContentProvider组件信息 providers = AppGlobals.getPackageManager() .queryContentProviders(app.processName, app.uid, STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/ null) .getList(); } catch (RemoteException ex) { } int userId = app.userId; if (providers != null) { int N = providers.size(); //有必要的情况下进行Map扩容 app.pubProviders.ensureCapacity(N + app.pubProviders.size()); for (int i=0; i<N; i++) { // TODO: keep logic in sync with installEncryptionUnawareProviders ProviderInfo cpi = (ProviderInfo)providers.get(i); //对于单例ContentProvider,需要在默认用户中启动,如果不是默认用户的话则直接将其丢弃掉,不启动 boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags); if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) { // This is a singleton provider, but a user besides the // default user is asking to initialize a process it runs // in... well, no, it doesn't actually run in this process, // it runs in the process of the default user. Get rid of it. providers.remove(i); N--; i--; continue; } ComponentName comp = new ComponentName(cpi.packageName, cpi.name); ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId); if (cpr == null) { //新建ContentProviderRecord并将其加入到缓存中 cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton); mProviderMap.putProviderByClass(comp, cpr); } //将ContentProviderRecord保存到进程已发布ContentProvider列表中 app.pubProviders.put(cpi.name, cpr); if (!cpi.multiprocess || !"android".equals(cpi.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添加至进程中运行的包列表中 app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.longVersionCode, mProcessStats); } notifyPackageUse(cpi.applicationInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER); } } return providers; }这个方法主要是获取需要启动的ContentProvider的ContentProviderRecord,如果是第一次启动这个ContentProvider则需要新建一个ContentProviderRecord并将其存入缓存,然后将其保存到进程已发布ContentProvider列表中,以供后面使用。同时这个方法返回了需要启动的ProviderInfo列表,AMS.attachApplicationLocked方法可以根据这个列表判断是否有需要启动的ContentProvider并设置ContentProvider启动超时检测ActivityThread.handleBindApplicationprivate void handleBindApplication(AppBindData data) { ... try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. //创建Application app = data.info.makeApplication(data.restrictedBackupMode, null); ... mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class //在非受限模式下启动ContentProvider if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { installContentProviders(app, data.providers); } } ... //执行Application的onCreate方法 try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { ... } } finally { // If the app targets < O-MR1, or doesn't change the thread policy // during startup, clobber the policy to maintain behavior of b/36951662 if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1 || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) { StrictMode.setThreadPolicy(savedPolicy); } } ... }可以看到,在这个方法中直接调用了installContentProviders方法安装启动ContentProvider另外提一点,为什么我要把Application的创建和onCreate也放进来呢?现在市面上有很多库,包括很多教程告诉我们,可以通过注册ContentProvider的方式初始化SDK,获取全局Context,比如说著名的内存泄漏检测工具LeakCanary的新版本,想要使用它,直接添加它的依赖就行了,不需要对代码做哪怕一点的改动,究其原理,就是因为ContentProvider的启动时机是在Application创建后,Application.onCreate调用前,并且ContentProvider内的Context成员变量大概率就是Application,大家以后在开发过程中也可以妙用这一点ActivityThread.installContentProviders好了,现在这两种情况最终都走到了ActivityThread.installContentProviders方法中,那我们接下来就好好分析ContentProvider实际的启动安装流程private void installContentProviders( Context context, List<ProviderInfo> providers) { final ArrayList<ContentProviderHolder> results = new ArrayList<>(); for (ProviderInfo cpi : providers) { //逐个启动 ContentProviderHolder cph = installProvider(context, null, cpi, false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/); if (cph != null) { cph.noReleaseNeeded = true; results.add(cph); } } try { //发布ContentProvider ActivityManager.getService().publishContentProviders( getApplicationThread(), results); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } }这个方法很简单,便利所有待启动的ContentProvider信息列表,逐个启动安装ContentProvider,最后一起发布ActivityThread.installProvider我们先看installProvider方法,我们在上一章中分析到,获取ContentProvider的时候也会调用这个方法,这次我们就结合起来一起分析通过上文的代码,我们发现,有两处地方会调用installProvider方法,方法的入参有三种形式,分别为:holder不为null,info不为null,holder.provider为null:在ActivityThread.acquireProvider方法中被调用,路径为 没有获取到已存在的ContentProvider -> AMS.getContentProvider -> AMS.getContentProviderImpl -> 发现目标ContentProvider可以在调用者进程中直接运行 -> 直接返回一个新的ContentProviderHolder(包含ProviderInfo) -> ActivityThread.installProvider,在这种情况下installProvider方法会在本地启动安装ContentProviderholder为null,info不为null:在ActivityThread.installContentProviders方法中被调用,两条路径,一是App进程启动后自动执行,二是在AMS.getContentProvider方法中发现目标进程已启动但是ContentProvider未启动,调用ActivityThread.scheduleInstallProvider方法执行,在这种情况下installProvider方法会在本地启动安装ContentProviderholder不为null,holder.provider不为null:在ActivityThread.acquireProvider方法中被调用,路径为 没有获取到已存在的ContentProvider -> AMS.getContentProvider -> AMS.getContentProviderImpl -> 获取到目标进程的远程ContentProvider引用 -> 包装成ContentProviderHolder返回 -> ActivityThread.installProvider,在这种情况下installProvider方法直接可以获取到远程ContentProvider引用,然后进行处理我们将这三种情况分成两种case分别分析本地启动ContentProviderprivate ContentProviderHolder installProvider(Context context, ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) { ContentProvider localProvider = null; IContentProvider provider; if (holder == null || holder.provider == null) { //启动本地ContentProvider Context c = null; ApplicationInfo ai = info.applicationInfo; //首先获取Context,一般情况下就是Application if (context.getPackageName().equals(ai.packageName)) { c = context; } else if (mInitialApplication != null && mInitialApplication.getPackageName().equals(ai.packageName)) { c = mInitialApplication; } else { try { c = context.createPackageContext(ai.packageName, Context.CONTEXT_INCLUDE_CODE); } catch (PackageManager.NameNotFoundException e) { // Ignore } } if (c == null) { return null; } //Split Apks动态加载相关 if (info.splitName != null) { try { c = c.createContextForSplit(info.splitName); } catch (NameNotFoundException e) { throw new RuntimeException(e); } } try { final java.lang.ClassLoader cl = c.getClassLoader(); //获取应用信息 LoadedApk packageInfo = peekPackageInfo(ai.packageName, true); if (packageInfo == null) { // System startup case. packageInfo = getSystemContext().mPackageInfo; } //通过AppComponentFactory实例化ContentProvider localProvider = packageInfo.getAppFactory() .instantiateProvider(cl, info.name); //Transport类,继承自ContentProviderNative(Binder服务端) provider = localProvider.getIContentProvider(); if (provider == null) { return null; } // XXX Need to create the correct context for this provider. //初始化ContentProvider,调用其onCreate方法 localProvider.attachInfo(c, info); } catch (java.lang.Exception e) { if (!mInstrumentation.onException(null, e)) { throw new RuntimeException( "Unable to get provider " + info.name + ": " + e.toString(), e); } return null; } } else { //获取外部ContentProvider ... } ContentProviderHolder retHolder; synchronized (mProviderMap) { //对于本地ContentProvider来说,这里的实际类型是Transport,继承自ContentProviderNative(Binder服务端) IBinder jBinder = provider.asBinder(); if (localProvider != null) { //本地启动ContentProvider的情况 ComponentName cname = new ComponentName(info.packageName, info.name); ProviderClientRecord pr = mLocalProvidersByName.get(cname); if (pr != null) { //如果已经存在相应的ContentProvider记录,使用其内部已存在的ContentProvider provider = pr.mProvider; } else { //否则使用新创建的ContentProvider holder = new ContentProviderHolder(info); holder.provider = provider; //对于本地ContentProvider来说,不存在释放引用这种情况 holder.noReleaseNeeded = true; //创建ProviderClientRecord并将其保存到mProviderMap本地缓存中 pr = installProviderAuthoritiesLocked(provider, localProvider, holder); //保存ProviderClientRecord到本地缓存中 mLocalProviders.put(jBinder, pr); mLocalProvidersByName.put(cname, pr); } retHolder = pr.mHolder; } else { //获取远程ContentProvider的情况 ... } } return retHolder; }我们在这里找到了ContentProvider创建并启动的入口,首先通过传入的Context(实际上就是Application)判断并确定创建并给ContentProvider使用的的Context是什么(一般情况下也是Application),然后获取到应用信息LoadedApk,再通过它得到AppComponentFactory(前面的文章中介绍过,如果没有在AndroidManifest中设置android:appComponentFactory属性,使用的便是默认的AppComponentFactory),接着通过AppComponentFactory.instantiateProvider方法实例化ContentProvider对象 public @NonNull ContentProvider instantiateProvider(@NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (ContentProvider) cl.loadClass(className).newInstance(); }默认的话就是通过ClassName反射调用默认构造函数实例化ContentProvider对象,最后再调用ContentProvider.attachInfo方法初始化public void attachInfo(Context context, ProviderInfo info) { attachInfo(context, info, false); } private void attachInfo(Context context, ProviderInfo info, boolean testing) { ... if (mContext == null) { mContext = context; ... ContentProvider.this.onCreate(); } }详细内容我们就不分析了,只需要知道这里给mContext赋了值,然后调用了ContentProvider.onCreate方法就可以了到了这一步,ContentProvider就算是启动完成了,接下来需要执行一些安装步骤,其实也就是对缓存等进行一些处理。在ContentProvider实例化后,会调用其getIContentProvider方法给provider变量赋值,这里获得的对象其实是一个Transport对象,继承自ContentProviderNative,是一个Binder服务端对象,在ContentProvider初始化后,会对Transport对象调用asBinder方法获得Binder对象,这里获得的其实还是自己本身,接着从缓存中尝试获取ProviderClientRecord对象,如果获取到了,说明已经存在了相应的ContentProvider,使用ProviderClientRecord内部的ContentProvider,刚刚新创建的那个就可以丢弃了,如果没获取到,就去新建ContentProviderHolder以及ProviderClientRecord,然后将他们添加到各种缓存中,至此,ContentProvider的安装过程也到此结束获取处理远程ContentProviderprivate ContentProviderHolder installProvider(Context context, ContentProviderHolder holder, ProviderInfo info, boolean noisy, boolean noReleaseNeeded, boolean stable) { ContentProvider localProvider = null; IContentProvider provider; if (holder == null || holder.provider == null) { //启动本地ContentProvider ... } else { //获取外部ContentProvider //实际类型为ContentProviderProxy provider = holder.provider; } ContentProviderHolder retHolder; synchronized (mProviderMap) { //对于外部ContentProvider来说,这里的实际类型是BinderProxy IBinder jBinder = provider.asBinder(); if (localProvider != null) { //本地启动ContentProvider的情况 ... } else { //获取远程ContentProvider的情况 ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc != null) { //如果ContentProvider引用已存在 // We need to transfer our new reference to the existing // ref count, releasing the old one... but only if // release is needed (that is, it is not running in the // system process). //对于远程ContentProvider来说,如果目标App为system应用(UID为ROOT_UID或SYSTEM_UID) //并且目标App不为设置(包名不为com.android.settings),则noReleaseNeeded为true if (!noReleaseNeeded) { //增加已存在的ContentProvider引用的引用计数 incProviderRefLocked(prc, stable); try { //释放传入的引用,移除ContentProviderConnection相关信息,更新引用计数 ActivityManager.getService().removeContentProvider( holder.connection, stable); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { //创建ProviderClientRecord并将其保存到mProviderMap本地缓存中 ProviderClientRecord client = installProviderAuthoritiesLocked( provider, localProvider, holder); if (noReleaseNeeded) { //同上,目标App为system应用,不需要释放引用 //新建一个ProviderRefCount,但引用计数初始化为一个较大的数值 //这样后续无论调用方进程的ContentProvider引用计数如何变动都不会影响到AMS prc = new ProviderRefCount(holder, client, 1000, 1000); } else { //需要释放引用的情况下 //正常的新建初始化一个ProviderRefCount prc = stable ? new ProviderRefCount(holder, client, 1, 0) : new ProviderRefCount(holder, client, 0, 1); } //保存至缓存 mProviderRefCountMap.put(jBinder, prc); } retHolder = prc.holder; } } return retHolder; }对于holder.provider不为null的情况,直接获取远程ContentProvider引用,然后进行处理就可以了。这里获取到的IContentProvider的实际类型是ContentProviderProxy,然后对其调用asBinder方法,获取到的是BinderProxy对象,接着从缓存中尝试获取ProviderRefCount对象,如果缓存中已经有相应的引用对象了,则在需要释放引用(!noReleaseNeeded)的情况下使用原有的引用,释放参数传入进来的ContentProvider引用这里noReleaseNeeded是在ContentProviderRecord构造时赋值的,为true的条件是目标App为system应用(UID为ROOT_UID或SYSTEM_UID)并且目标App不为设置(包名不为com.android.settings)如果缓存中没有查找到相应的ProviderRefCount对象,新建ProviderClientRecord和ProviderRefCount对象,并将他们保存到缓存中,至于为什么在noReleaseNeeded的情况下,新建的ProviderRefCount的引用计数初始值为1000,我猜测是因为noReleaseNeeded代表了不需要释放引用,所以这里干脆设置一个比较大的值,这样无论调用方进程的ContentProvider引用计数怎样变动,都不会再调用到AMS的方法中去处理引用的变化,在非常早期的Android版本中(Android 4.0.1),这个值曾被设置为10000至此,远程ContentProvider的安装也结束了ActivityThread.installProviderAuthoritiesLocked接下来我们再简单的看一下两种case都会走到的installProviderAuthoritiesLocked方法吧private ProviderClientRecord installProviderAuthoritiesLocked(IContentProvider provider, ContentProvider localProvider, ContentProviderHolder holder) { final String auths[] = holder.info.authority.split(";"); final int userId = UserHandle.getUserId(holder.info.applicationInfo.uid); ... final ProviderClientRecord pcr = new ProviderClientRecord( auths, provider, localProvider, holder); for (String auth : auths) { final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord existing = mProviderMap.get(key); if (existing != null) { Slog.w(TAG, "Content provider " + pcr.mHolder.info.name + " already published as " + auth); } else { mProviderMap.put(key, pcr); } } return pcr; }这个方法很简单,新建了一个ProviderClientRecord并将其添加到mProviderMap缓存中,这里的操作对应着最前面的acquireExistingProvider方法,有了这个缓存,以后就可以直接拿,而不用再复杂的经过一系列的AMS跨进程操作了AMS.publishContentProvidersContentProvider全部启动安装完后,便要调用AMS.publishContentProviders将他们发布出去,供外部使用了public final void publishContentProviders(IApplicationThread caller, List<ContentProviderHolder> providers) { if (providers == null) { return; } synchronized (this) { final ProcessRecord r = getRecordForAppLocked(caller); if (r == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when publishing content providers"); } final long origId = Binder.clearCallingIdentity(); final int N = providers.size(); for (int i = 0; i < N; i++) { ContentProviderHolder src = providers.get(i); if (src == null || src.info == null || src.provider == null) { continue; } //App进程启动时或AMS.getContentProvider中已经将相应ContentProviderRecord添加到了pubProviders中 ContentProviderRecord dst = r.pubProviders.get(src.info.name); if (dst != null) { //保存至缓存中 ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); mProviderMap.putProviderByClass(comp, dst); String names[] = dst.info.authority.split(";"); for (int j = 0; j < names.length; j++) { mProviderMap.putProviderByName(names[j], dst); } //ContentProvider已经启动完毕,将其从正在启动的ContentProvider列表中移除 int launchingCount = mLaunchingProviders.size(); int j; boolean wasInLaunchingProviders = false; for (j = 0; j < launchingCount; j++) { if (mLaunchingProviders.get(j) == dst) { mLaunchingProviders.remove(j); wasInLaunchingProviders = true; j--; launchingCount--; } } //移除ContentProvider启动超时监听 if (wasInLaunchingProviders) { mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r); } // Make sure the package is associated with the process. // XXX We shouldn't need to do this, since we have added the package // when we generated the providers in generateApplicationProvidersLocked(). // But for some reason in some cases we get here with the package no longer // added... for now just patch it in to make things happy. r.addPackage(dst.info.applicationInfo.packageName, dst.info.applicationInfo.longVersionCode, mProcessStats); synchronized (dst) { dst.provider = src.provider; dst.setProcess(r); //让出锁,通知其他wait的地方 //对应着AMS.getContentProvider的第四部分:等待ContentProvider启动完成 dst.notifyAll(); } dst.mRestartCount = 0; updateOomAdjLocked(r, true, OomAdjuster.OOM_ADJ_REASON_GET_PROVIDER); maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority); } } Binder.restoreCallingIdentity(origId); } }遍历整个待发布的ContentProvider列表,从ProcessRecord.pubProviders中查找相对应的ContentProviderRecord,我们在之前的章节中已经分析过了,App进程启动时或AMS.getContentProvider中已经将相应ContentProviderRecord添加到了pubProviders中,然后就是将其保存到各个缓存中,由于ContentProvider已经启动完毕,所以需要将其从正在启动的ContentProvider列表中移除,在ContentProvider正常启动的情况下,我们需要将ContentProvider的启动超时监听移除,最后,获取ContentProviderRecord同步锁,将准备好的ContentProvider赋值到ContentProviderRecord中,接着调用notifyAll方法通知其他调用过wait的地方,将锁让出,这里对应的就是AMS.getContentProvider的第四部分:等待ContentProvider启动完成 private ContentProviderHolder getContentProviderImpl(IApplicationThread caller, String name, IBinder token, int callingUid, String callingPackage, String callingTag, boolean stable, int userId) { ... //这里的cpr和在publishContentProviders获得的dst是一个对象 synchronized (cpr) { while (cpr.provider == null) { ... //释放锁,等待ContentProvider启动完成 cpr.wait(wait); ... } } ... }这样,ContentProvider一发布,这里就会收到通知,解除wait状态,获得到ContentProvider,返回出去,是不是感觉一切都串起来了?ContentProvider引用计数ContentProvider的获取与启动分析完了,接下来我们聊聊它的引用计数,为下一小节分析ContentProvider死亡杀死调用方进程的过程做准备ActivityThread层的引用计数是和AMS层的引用计数分开的,ActivityThread记录的是目标ContentProvider在本进程中有多少处正在使用,而AMS记录的是目标ContentProvider正在被多少个进程使用ActivityThread层的引用计数增加引用计数我们先从ActivityThread层增加引用计数开始说起,在ActivityThread获取ContentProvider时,便会调用incProviderRefLocked方法来增加引用计数,具体的时机为acquireExistingProvider或installProvider时,代码我就不重复放了,大家看前面几个小节就行(后同) private final void incProviderRefLocked(ProviderRefCount prc, boolean stable) { if (stable) { //增加ActivityThread的stable引用计数 prc.stableCount += 1; //本进程对目标ContentProvider产生了stable引用关系 if (prc.stableCount == 1) { // We are acquiring a new stable reference on the provider. int unstableDelta; //正在移除ContentProvider引用中(释放ContentProvider后发现stable和unstable引用计数均为0) if (prc.removePending) { // We have a pending remove operation, which is holding the // last unstable reference. At this point we are converting // that unstable reference to our new stable reference. //当ActivityThread释放一个stable的ContentProvider时,如果释放完后, //发现stable和unstable引用计数均为0,则会暂时保留一个unstable引用 //所以这里需要为 -1 ,将这个unstable引用移除 unstableDelta = -1; // Cancel the removal of the provider. prc.removePending = false; // There is a race! It fails to remove the message, which // will be handled in completeRemoveProvider(). //取消移除ContentProvider引用 mH.removeMessages(H.REMOVE_PROVIDER, prc); } else { //对于正常情况,只需要增加stable引用计数,不需要动unstable引用计数 unstableDelta = 0; } try { //AMS层修改引用计数 ActivityManager.getService().refContentProvider( prc.holder.connection, 1, unstableDelta); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { //增加ActivityThread的unstable引用计数 prc.unstableCount += 1; //本进程对目标ContentProvider产生了unstable引用关系 if (prc.unstableCount == 1) { // We are acquiring a new unstable reference on the provider. //正在移除ContentProvider引用中(释放ContentProvider后发现stable和unstable引用计数均为0) if (prc.removePending) { // Oh look, we actually have a remove pending for the // provider, which is still holding the last unstable // reference. We just need to cancel that to take new // ownership of the reference. //取消移除ContentProvider引用 prc.removePending = false; mH.removeMessages(H.REMOVE_PROVIDER, prc); } else { // First unstable ref, increment our count in the // activity manager. try { //增加AMS层的unstable引用计数 ActivityManager.getService().refContentProvider( prc.holder.connection, 0, 1); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } } }这里的逻辑需要配合着ContentProvider释放引用那里一起看才好理解,我先提前解释一下首先,removePending这个变量表示此ContentProvider正在移除中,当ActivityThread减少引用计数,检查到stable和unstable引用计数均为0后被赋值为true,并且会向Handler发送一条what值为REMOVE_PROVIDER的延时消息,在一定时间后便会触发ContentProvider移除操作,清理本地缓存,再将removePending重新置为false,所以当这里removePending为true则说明此ContentProvider还没完全被移除,我们把这个消息取消掉继续使用这个ContentProvider对于stable引用的情况下,当ActivityThread减少引用计数,检查到stable和unstable引用计数均为0后,会暂时保留一个unstable引用,等到后面真正触发到了移除ContentProvider的时候再将这个unstable引用移除,所以在增加引用计数的时候需要考虑到这一点,在这种情况下要将AMS层的unstable引用计数减一对于其他的情况就是正常的增加ActivityThread层引用计数,然后调用AMS.refContentProvider方法操作AMS层的引用计数减少引用计数ContentProvider使用完后会调用ActivityThread.releaseProvider方法,以query方法为例,最后会调用releaseUnstableProvider和releaseProvider方法,最终都会走到这里来public final boolean releaseProvider(IContentProvider provider, boolean stable) { if (provider == null) { return false; } IBinder jBinder = provider.asBinder(); synchronized (mProviderMap) { ProviderRefCount prc = mProviderRefCountMap.get(jBinder); if (prc == null) { // The provider has no ref count, no release is needed. return false; } boolean lastRef = false; if (stable) { //引用计数已经为0,无法再减了 if (prc.stableCount == 0) { return false; } //减少ActivityThread的stable引用计数 prc.stableCount -= 1; if (prc.stableCount == 0) { // What we do at this point depends on whether there are // any unstable refs left: if there are, we just tell the // activity manager to decrement its stable count; if there // aren't, we need to enqueue this provider to be removed, // and convert to holding a single unstable ref while // doing so. lastRef = prc.unstableCount == 0; try { //如果是最后的引用,则暂时保留一个unstable引用 ActivityManager.getService().refContentProvider( prc.holder.connection, -1, lastRef ? 1 : 0); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } else { //引用计数已经为0,无法再减了 if (prc.unstableCount == 0) { return false; } //减少ActivityThread的unstable引用计数 prc.unstableCount -= 1; if (prc.unstableCount == 0) { // If this is the last reference, we need to enqueue // this provider to be removed instead of telling the // activity manager to remove it at this point. lastRef = prc.stableCount == 0; //如果是最后的引用,则不进入到这里,暂时保留一个unstable引用 if (!lastRef) { try { //减少AMS引用计数 ActivityManager.getService().refContentProvider( prc.holder.connection, 0, -1); } catch (RemoteException e) { //do nothing content provider object is dead any way } } } } if (lastRef) { if (!prc.removePending) { // Schedule the actual remove asynchronously, since we don't know the context // this will be called in. //表面此ContentProvider正在移除中 prc.removePending = true; //发送延时消息,等待一定时间后移除ContentProvider Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc); mH.sendMessageDelayed(msg, CONTENT_PROVIDER_RETAIN_TIME); } else { Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name); } } return true; } }可以看到,在减完引用计数后,如果发现是最后一个引用,即stable和unstable引用计数均为0,此时无论是stable还是unstable都会让AMS暂时保留一个unstable引用,然后发送一条what值为REMOVE_PROVIDER的延时消息,等待一定时间后移除ContentProvider,当时间到了触发这条消息时,会调用到ActivityThread.completeRemoveProvider方法 final void completeRemoveProvider(ProviderRefCount prc) { synchronized (mProviderMap) { if (!prc.removePending) { // There was a race! Some other client managed to acquire // the provider before the removal was completed. // Abort the removal. We will do it later. return; } // More complicated race!! Some client managed to acquire the // provider and release it before the removal was completed. // Continue the removal, and abort the next remove message. prc.removePending = false; //移除缓存 final IBinder jBinder = prc.holder.provider.asBinder(); ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder); if (existingPrc == prc) { mProviderRefCountMap.remove(jBinder); } //移除缓存 for (int i=mProviderMap.size()-1; i>=0; i--) { ProviderClientRecord pr = mProviderMap.valueAt(i); IBinder myBinder = pr.mProvider.asBinder(); if (myBinder == jBinder) { mProviderMap.removeAt(i); } } } try { //处理AMS层引用计数 ActivityManager.getService().removeContentProvider( prc.holder.connection, false); } catch (RemoteException e) { //do nothing content provider object is dead any way } }这个方法将进程内所持有的ContentProvider相关缓存清除,然后调用AMS.removeContentProvider方法通知AMS移除ContentProvider,处理相应的引用计数。这里我们发现,调用AMS.removeContentProvider方法传入的最后一个参数stable为false,因为我们之前在stable和unstable引用计数均为0的情况下,保留了一个unstable引用,所以这时移除的ContentProvider引用也是unstable引用AMS层的引用计数接着我们来看AMS层的引用计数AMS.refContentProvider我们就先从我们刚刚分析的ActivityThread层的引用计数修改后续:refContentProvider 看起public boolean refContentProvider(IBinder connection, int stable, int unstable) { ContentProviderConnection conn; ... conn = (ContentProviderConnection)connection; ... synchronized (this) { if (stable > 0) { conn.numStableIncs += stable; } stable = conn.stableCount + stable; if (stable < 0) { throw new IllegalStateException("stableCount < 0: " + stable); } if (unstable > 0) { conn.numUnstableIncs += unstable; } unstable = conn.unstableCount + unstable; if (unstable < 0) { throw new IllegalStateException("unstableCount < 0: " + unstable); } if ((stable+unstable) <= 0) { throw new IllegalStateException("ref counts can't go to zero here: stable=" + stable + " unstable=" + unstable); } conn.stableCount = stable; conn.unstableCount = unstable; return !conn.dead; } }这个方法很简单,应该不需要再多做分析了吧?就是简单的修改ContentProviderConnection的引用计数值AMS.incProviderCountLocked接下来我们看AMS层引用计数的增加,AMS.incProviderCountLocked这个方法的触发时机是在AMS.getContentProviderImpl方法中ContentProviderConnection incProviderCountLocked(ProcessRecord r, final ContentProviderRecord cpr, IBinder externalProcessToken, int callingUid, String callingPackage, String callingTag, boolean stable) { if (r != null) { for (int i=0; i<r.conProviders.size(); i++) { ContentProviderConnection conn = r.conProviders.get(i); //如果连接已存在,在其基础上增加引用计数 if (conn.provider == cpr) { if (stable) { conn.stableCount++; conn.numStableIncs++; } else { conn.unstableCount++; conn.numUnstableIncs++; } return conn; } } //新建ContentProviderConnection连接 ContentProviderConnection conn = new ContentProviderConnection(cpr, r, callingPackage); //建立关联 conn.startAssociationIfNeeded(); if (stable) { conn.stableCount = 1; conn.numStableIncs = 1; } else { conn.unstableCount = 1; conn.numUnstableIncs = 1; } //添加连接 cpr.connections.add(conn); r.conProviders.add(conn); //建立关联 startAssociationLocked(r.uid, r.processName, r.getCurProcState(), cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); return conn; } cpr.addExternalProcessHandleLocked(externalProcessToken, callingUid, callingTag); return null; }如果调用方进程已存在对应ContentProviderConnection连接,则在其基础上增加引用计数,否则新建连接,然后初始化引用计数值AMS.decProviderCountLocked然后是减少引用计数,之前在ActivityThread减引用到0后,会延时调用ActivityThread.completeRemoveProvider方法,在这个方法中会调用到AMS.removeContentProvider方法public void removeContentProvider(IBinder connection, boolean stable) { long ident = Binder.clearCallingIdentity(); try { synchronized (this) { ContentProviderConnection conn = (ContentProviderConnection)connection; ... //减少引用计数 if (decProviderCountLocked(conn, null, null, stable)) { //更新进程优先级 updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER); } } } finally { Binder.restoreCallingIdentity(ident); } }在这个方法中便会调用AMS.decProviderCountLocked减少引用计数,然后更新进程优先级boolean decProviderCountLocked(ContentProviderConnection conn, ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) { if (conn != null) { cpr = conn.provider; //减少引用计数值 if (stable) { conn.stableCount--; } else { conn.unstableCount--; } if (conn.stableCount == 0 && conn.unstableCount == 0) { //停止关联 conn.stopAssociation(); //移除连接 cpr.connections.remove(conn); conn.client.conProviders.remove(conn); if (conn.client.setProcState < PROCESS_STATE_LAST_ACTIVITY) { // The client is more important than last activity -- note the time this // is happening, so we keep the old provider process around a bit as last // activity to avoid thrashing it. if (cpr.proc != null) { cpr.proc.lastProviderTime = SystemClock.uptimeMillis(); } } //停止关联 stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); return true; } return false; } cpr.removeExternalProcessHandleLocked(externalProcessToken); return false; }减少引用计数值,如果stable和unstable引用计数均为0,则将这个连接移除ContentProvider死亡杀死调用方进程的过程我们前面提到过,ContentProvider所在进程死亡会将与其所有有stable关联的调用方进程杀死,这是怎么做到的呢?在之前的文章中,我们介绍过进程启动时,在调用AMS.attachApplicationLocked时会注册一个App进程死亡回调,我们就从进程死亡,触发死亡回调开始分析 private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { ... //注册App进程死亡回调 AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; ... }注册了死亡回调后,如果对应binder进程死亡,便会回调IBinder.DeathRecipient.binderDied方法,我们来看一下AppDeathRecipient对这个方法的实现private final class AppDeathRecipient implements IBinder.DeathRecipient { final ProcessRecord mApp; final int mPid; final IApplicationThread mAppThread; AppDeathRecipient(ProcessRecord app, int pid, IApplicationThread thread) { mApp = app; mPid = pid; mAppThread = thread; } @Override public void binderDied() { synchronized(ActivityManagerService.this) { appDiedLocked(mApp, mPid, mAppThread, true, null); } } }直接转手调用AMS.appDiedLocked方法,然后经过handleAppDiedLocked调用到cleanUpApplicationRecordLocked方法中final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index, boolean replacingPid) { ... boolean restart = false; // Remove published content providers. //清除已发布的ContentProvider for (int i = app.pubProviders.size() - 1; i >= 0; i--) { ContentProviderRecord cpr = app.pubProviders.valueAt(i); if (cpr.proc != app) { // If the hosting process record isn't really us, bail out continue; } final boolean alwaysRemove = app.bad || !allowRestart; final boolean inLaunching = removeDyingProviderLocked(app, cpr, alwaysRemove); if (!alwaysRemove && inLaunching && cpr.hasConnectionOrHandle()) { // We left the provider in the launching list, need to // restart it. restart = true; } cpr.provider = null; cpr.setProcess(null); } app.pubProviders.clear(); // Take care of any launching providers waiting for this process. //清除正在启动中的ContentProvider if (cleanupAppInLaunchingProvidersLocked(app, false)) { mProcessList.noteProcessDiedLocked(app); restart = true; } // Unregister from connected content providers. //清除已连接的ContentProvider if (!app.conProviders.isEmpty()) { for (int i = app.conProviders.size() - 1; i >= 0; i--) { ContentProviderConnection conn = app.conProviders.get(i); conn.provider.connections.remove(conn); stopAssociationLocked(app.uid, app.processName, conn.provider.uid, conn.provider.appInfo.longVersionCode, conn.provider.name, conn.provider.info.processName); } app.conProviders.clear(); } ... }可以看到,这个方法中遍历了ProcessRecord.pubProviders,逐个对发布的ContentProvider调用removeDyingProviderLocked方法执行移除操作private final boolean removeDyingProviderLocked(ProcessRecord proc, ContentProviderRecord cpr, boolean always) { boolean inLaunching = mLaunchingProviders.contains(cpr); if (inLaunching && !always && ++cpr.mRestartCount > ContentProviderRecord.MAX_RETRY_COUNT) { // It's being launched but we've reached maximum attempts, force the removal always = true; } if (!inLaunching || always) { synchronized (cpr) { cpr.launchingApp = null; cpr.notifyAll(); } final int userId = UserHandle.getUserId(cpr.uid); // Don't remove from provider map if it doesn't match // could be a new content provider is starting //移除缓存 if (mProviderMap.getProviderByClass(cpr.name, userId) == cpr) { mProviderMap.removeProviderByClass(cpr.name, userId); } String names[] = cpr.info.authority.split(";"); for (int j = 0; j < names.length; j++) { // Don't remove from provider map if it doesn't match // could be a new content provider is starting //移除缓存 if (mProviderMap.getProviderByName(names[j], userId) == cpr) { mProviderMap.removeProviderByName(names[j], userId); } } } for (int i = cpr.connections.size() - 1; i >= 0; i--) { ContentProviderConnection conn = cpr.connections.get(i); if (conn.waiting) { // If this connection is waiting for the provider, then we don't // need to mess with its process unless we are always removing // or for some reason the provider is not currently launching. if (inLaunching && !always) { continue; } } ProcessRecord capp = conn.client; conn.dead = true; if (conn.stableCount > 0) { if (!capp.isPersistent() && capp.thread != null && capp.pid != 0 && capp.pid != MY_PID) { //当调用方与被杀死的目标ContentProvider进程间有stable连接 //并且调用方App进程非persistent进程并且非system_server进程中的情况下 //杀死调用方进程 capp.kill("depends on provider " + cpr.name.flattenToShortString() + " in dying proc " + (proc != null ? proc.processName : "??") + " (adj " + (proc != null ? proc.setAdj : "??") + ")", ApplicationExitInfo.REASON_DEPENDENCY_DIED, ApplicationExitInfo.SUBREASON_UNKNOWN, true); } } else if (capp.thread != null && conn.provider.provider != null) { try { //通知调用方移除ContentProvider capp.thread.unstableProviderDied(conn.provider.provider.asBinder()); } catch (RemoteException e) { } // In the protocol here, we don't expect the client to correctly // clean up this connection, we'll just remove it. //移除连接 cpr.connections.remove(i); if (conn.client.conProviders.remove(conn)) { stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); } } } if (inLaunching && always) { mLaunchingProviders.remove(cpr); cpr.mRestartCount = 0; inLaunching = false; } return inLaunching; }可以看到,在这个方法中遍历了ContentProvider下的所有连接,当发现有其他进程与自己建立了stable连接(conn.stableCount > 0),且调用方进程不是persistent进程(常驻进程,只有拥有系统签名的App设置这个属性才生效),也不是运行在system_server进程,调用ProcessRecord.kill方法直接杀死进程,对于没有建立stable连接的调用方进程,调用IApplicationThread.unstableProviderDied方法通知调用方进程移除相应的ContentProvider所以,使用ContentProvider是有一定风险的,大家要注意规避

0
0
0
浏览量1925
万码学说

面试的时候该怎么做?小心面试的5大雷区!

“你对我们公司的行业有什么了解?”“没了解,第一次接触。” “你对我们公司有什么了解?”“没了解,是你们叫我来面试的。” “你对我们的岗位有什么了解?”“没了解,应该和我之前做的差不多吧。”日常招聘过程中,这种精准踩在面试官雷区的情况并不少见,今天就来梳理盘点,那些在面试官雷区拼命蹦跶的情形。 初级踩雷:我对贵司一无所知如前文所示,前来面试不提前了解公司情况,无疑是精准踩在面试官的雷区。有的候选人还精心打扮,在个人的形象、着装方面大做文章,固然会让人眼前一亮,但是基本知识都不提前准备的,真的会很减分。哪怕是没有提前认真准备、了解,至少招聘网站的公司介绍、公司官网、岗位JD看一眼也不至于一问三不知。 中级踩雷:我的情况如简历所示/十分钟的自我介绍大家都知道,面试的第一个问题基本都是自我介绍。自我介绍是方便双方进入面试情景的重要环节,是给候选人缓冲时间,也是给面试官缓冲时间。不是所有面试官都会提前看简历,对新晋面试官而言,需要一点时间了解人选的基本情况;也不是所有面试官都需要看简历,很多资深面试官已经自成体系,能经过前期面试的人员已经满足基本条件,后面轮次的面试官不太关注简历写的内容了。最好的自我介绍是1-3分钟,避免太短双方没有进入状态,又避免太长让面试官听的乏味。 高级踩雷:我有很多offer,但也想看看贵司机会       也许求职者想通过多offer表现自己的优秀,通过放弃offer表现自己的加入意愿,但是这种行为却成功踩在面试官的雷区,与工作机会失之交臂。用人企业可能会对候选人心存顾虑:”他还在职,拿了十几个offer,每个offer面试三轮,是不是上班时间去面试了?还是打着出差的名义去见下家?“”他拿了那么多offer,还没定下来,对自己的认知和定位,是否有问题?一个关键岗位的人选连自己的定位都摸不准,把业务交给他不放心。“”与其把机会给一个不一定会来的人选,不如给确定性强的更合适。“ 究极踩雷:我和XX很熟,他的业绩还不如我有一些候选人,满嘴爬火车,张口就来。这也有几种情况:第一种是刚好撞到了面试官枪口的。比如面试官刚好来自于候选人目前所在的公司或曾经任职的公司,问及公司的一些情况时,候选人侃侃而谈,却风马牛不相及,直接被否掉。第二种是掩耳盗铃式。简历可能有水分或者完全造假,问及当时情况时就说“涉及公司保密信息,我不能透露”,“事情过的有点久了,虽然是我主导的,但我记不大清楚了”。第三种是对面试官的背调能力毫不知情,问及是否可以背调时还镇定自若,却不知道还没走出会议室就已经完成了背调,所谓的和人很熟,业绩很好,全都被调查得一览无遗。      不诚信,品德有问题的候选人,不管再怎么伪装,也只剩下淘汰的结局。      面试是个技术活,不是张张嘴聊聊天就是面试;而面试过程中,也确实会遇到很多候选人踩雷的行为。这些行为的之所以会成为雷区,折射的是面试官根据公司用人标准、评估要素进行的面试评判。希望广大候选人们,不要在面试官的雷区蹦跶。   那么面试很糟糕,就真的没机会了吗?其实不然,敢于主动的人,可能为自己创造翻盘机会。求职时想让自己脱颖而出的一个关键要素,就是主动。给大家分享几个案例:方法一:直接拦人360老板在乌镇的时候,被几位来自河北师范大学的学生拦住塞简历,学生们是信息安全相关专业的,很明显是早有预谋。周老板平时少见非985背景的毕业生简历吧,这非常规路径非常符合互联网公司的精神,更符合CEO的个性。引得周老板当天就在微博上发表了感言。这种专业(能力)针对性强、路径简单粗暴的方式通常有效。方法二:自我广告一位毕业于湘潭大学的湖南小伙今年春节在广州地铁出口处的广告栏投简历,展示了他所获得的一些奖项,右下角附上了他的微信二维码,左边放上了一张被挡住脸的照片。据说这一广告5天1000元,有30多家公司联络了他。 方法三:毛遂自荐在传统媒体多年的王记者,眼看着杂志社要关了,拿了遣散费的他微信了曾经采访过一次的企业老板,自荐自己有人脉,可以介绍客户,想来公司谋个的职位。王记者成为王经理后,果然凭借之前采访累积的人脉资源,在跨行业打下了一片天地,成为公司里的业务冠军,年薪百万,老板还直夸自己“英明决策”。正是他们的积极主动,让他们获得了那些看似不可能的机会。除了求职时主动出击,我们在面试后这么做也能带来事半功倍的效果: 如果没有主动去接触部门领导,就不会知道被拒绝的原因是什么,也就没机会提出解决方案,打消对方的顾虑。在面试官结束发问后,他通常会问求职者“你还有什么想问我的吗?”,这是个主动了解面试情况的好机会。我们可以向面试官请教自己在面试中有哪些不足,刚刚面试中的哪个问题还不太清楚等等。面对你真诚的态度,一般面试官都不会拒绝跟你交流一些想法。这样不仅能够帮助我们更好的评估自己的面试表现,在下次面试中有针对性的进行改善;同时也给了我们再次争取的机会,解释误解、消除顾虑,说不定就能扭转乾坤拿到offer呢。除此之外,如果到了约定的结果通知日还没消息,一定要主动询问,说不定只是HR在走流程,或是忘了通知你面试通过,就算没被录用,知道结果也能帮助我们更好的为下一次面试做准备。       复盘的概念,源自中国围棋,指的是双方棋手在每次博弈结束后,重新在棋盘上把刚才的对局再重复一遍,看看哪些地方下的好,哪些地方下的不好,是否还有别的走法,不同的走法对棋局有什么样的影响。运用在我们的面试中,就是通过还原整个面试场景,仔细分析每一环节,比如我们可以从面试目标、准备工作、对岗位/公司/行业的了解、面试沟通表达情况、简历这几个方面进行逐个复盘。重点关注面试官问了你哪些问题,哪些问题你回答的不好,找出影响结果的因素,进而确定出下一步的改进方向。对于那些表现出色的地方,总结规律和技巧,不断地将其运用在以后的面试中,沉淀经验,提高效率,提升自己在面试中的表现。              《高效能人士的7个习惯》里第一个就是积极主动,主动去争取自己想要的结果,哪怕主动碰壁,反弹回来的也会是一个全新的你。

2
0
1
浏览量656
chole

Android源码分析 - Service启动流程

开篇本篇以android-11.0.0_r25作为基础解析在之前的文章中,我们已经分析过了四大组件中Activity和ContentProvider的启动流程,这次我们就来讲讲四大组件之一的Service是如何启动和绑定的流程图在查阅资料的过程中,我发现有些博主会将梳理好的流程图贴在开头,我觉得这样有助于从宏观上去理解源码的整个流程和设计理念,所以以后的文章我都会尽量将源码梳理成流程图,以便大家理解入口启动Service有两种方式,一是startService,一是bindService,它们最终的实现都在ContextImpl中Context.startService当Service通过这种方式启动后,会一直运行下去,直到外部调用了stopService或内部调用stopSelf//frameworks/base/core/java/android/app/ContextImpl.java public ComponentName startService(Intent service) { warnIfCallingFromSystemProcess(); return startServiceCommon(service, false, mUser); } private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) { try { //确保Intent有效 validateServiceIntent(service); //跨进程准备 service.prepareToLeaveProcess(this); //调用AMS.startService ComponentName cn = ActivityManager.getService().startService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), requireForeground, getOpPackageName(), getAttributionTag(), user.getIdentifier()); //通过AMS层返回的ComponentName.packageName来判断是否出错以及错误类型 if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( "Not allowed to start service " + service + " without permission " + cn.getClassName()); } else if (cn.getPackageName().equals("!!")) { throw new SecurityException( "Unable to start service " + service + ": " + cn.getClassName()); } else if (cn.getPackageName().equals("?")) { throw new IllegalStateException( "Not allowed to start service " + service + ": " + cn.getClassName()); } } return cn; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }从代码可以看出,这里就是做了一下简单的校验,然后便调用了AMS.startService启动Service,最终通过返回的ComponentName中的packageName来判断是否出错以及错误类型//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, boolean requireForeground, String callingPackage, String callingFeatureId, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("startService"); // Refuse possible leaked file descriptors //校验Intent,不允许其携带fd if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } //调用方包名不能为空 if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } synchronized(this) { final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); ComponentName res; try { //调用ActiveServices.startServiceLocked方法 res = mServices.startServiceLocked(caller, service, resolvedType, callingPid, callingUid, requireForeground, callingPackage, callingFeatureId, userId); } finally { Binder.restoreCallingIdentity(origId); } return res; } }同样,这里做了一些简单的检查,然后调用ActiveServices.startServiceLocked方法,ActiveServices是一个辅助AMS进行Service管理的类,包括Service的启动、绑定和停止等//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId) throws TransactionTooLargeException { return startServiceLocked(caller, service, resolvedType, callingPid, callingUid, fgRequired, callingPackage, callingFeatureId, userId, false); } ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, boolean fgRequired, String callingPackage, @Nullable String callingFeatureId, final int userId, boolean allowBackgroundActivityStarts) throws TransactionTooLargeException { //判断调用方是否为前台 final boolean callerFg; if (caller != null) { final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting service " + service); } callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; } else { callerFg = true; } //查找待启动Service ServiceLookupResult res = retrieveServiceLocked(service, null, resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg, false, false); //如果找不到待启动Service,直接返回null if (res == null) { return null; } //如果待启动的Service所在package和uid无法与调用方package和uid建立关联,则无法启动Service //返回异常ComponentName,由上层抛出SecurityException异常 if (res.record == null) { return new ComponentName("!", res.permission != null ? res.permission : "private to package"); } ServiceRecord r = res.record; //试图用一个不存在的用户启动Service if (!mAm.mUserController.exists(r.userId)) { Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId); return null; } // If we're starting indirectly (e.g. from PendingIntent), figure out whether // we're launching into an app in a background state. This keys off of the same // idleness state tracking as e.g. O+ background service start policy. //Service所在应用未启动或处在后台 final boolean bgLaunch = !mAm.isUidActiveLocked(r.appInfo.uid); // If the app has strict background restrictions, we treat any bg service // start analogously to the legacy-app forced-restrictions case, regardless // of its target SDK version. //检查Service所在应用后台启动限制 boolean forcedStandby = false; if (bgLaunch && appRestrictedAnyInBackground(r.appInfo.uid, r.packageName)) { forcedStandby = true; } // If this is a direct-to-foreground start, make sure it is allowed as per the app op. boolean forceSilentAbort = false; if (fgRequired) { //作为前台服务启动 //权限检查 final int mode = mAm.getAppOpsManager().checkOpNoThrow( AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName); switch (mode) { //默认和允许都可以作为前台服务启动 case AppOpsManager.MODE_ALLOWED: case AppOpsManager.MODE_DEFAULT: // All okay. break; //不允许的话,回退到作为普通后台服务启动 case AppOpsManager.MODE_IGNORED: // Not allowed, fall back to normal start service, failing siliently // if background check restricts that. Slog.w(TAG, "startForegroundService not allowed due to app op: service " + service + " to " + r.shortInstanceName + " from pid=" + callingPid + " uid=" + callingUid + " pkg=" + callingPackage); fgRequired = false; forceSilentAbort = true; break; //错误的话直接返回,由上层抛出SecurityException异常 default: return new ComponentName("!!", "foreground not allowed as per app op"); } } // If this isn't a direct-to-foreground start, check our ability to kick off an // arbitrary service //如果不是从前台启动 //startRequested表示Service是否由startService方式所启动,fgRequired表示作为前台服务启动 if (forcedStandby || (!r.startRequested && !fgRequired)) { // Before going further -- if this app is not allowed to start services in the // background, then at this point we aren't going to let it period. //服务是否允许在后台启动 final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName, r.appInfo.targetSdkVersion, callingPid, false, false, forcedStandby); //如果不允许,则无法启动服务 if (allowed != ActivityManager.APP_START_MODE_NORMAL) { //静默的停止启动 if (allowed == ActivityManager.APP_START_MODE_DELAYED || forceSilentAbort) { // In this case we are silently disabling the app, to disrupt as // little as possible existing apps. return null; } if (forcedStandby) { // This is an O+ app, but we might be here because the user has placed // it under strict background restrictions. Don't punish the app if it's // trying to do the right thing but we're denying it for that reason. if (fgRequired) { return null; } } // This app knows it is in the new model where this operation is not // allowed, so tell it what has happened. //明确的告知不允许启动,上层抛出异常 UidRecord uidRec = mAm.mProcessList.getUidRecordLocked(r.appInfo.uid); return new ComponentName("?", "app is in background uid " + uidRec); } } // At this point we've applied allowed-to-start policy based on whether this was // an ordinary startService() or a startForegroundService(). Now, only require that // the app follow through on the startForegroundService() -> startForeground() // contract if it actually targets O+. //对于targetSdk 26以下(Android 8.0以下)的应用来说,不需要作为前台服务启动 if (r.appInfo.targetSdkVersion < Build.VERSION_CODES.O && fgRequired) { fgRequired = false; } //检查通过Intent被临时授权的Uris NeededUriGrants neededGrants = mAm.mUgmInternal.checkGrantUriPermissionFromIntent( service, callingUid, r.packageName, r.userId); // If permissions need a review before any of the app components can run, // we do not start the service and launch a review activity if the calling app // is in the foreground passing it a pending intent to start the service when // review is completed. // XXX This is not dealing with fgRequired! //如果待启动的Service需要相应权限,则需要用户手动确认权限后,再进行启动 if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage, callingFeatureId, callingUid, service, callerFg, userId)) { return null; } //取消之前的Service重启任务(如果有) if (unscheduleServiceRestartLocked(r, callingUid, false)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); } r.lastActivity = SystemClock.uptimeMillis(); //表示Service是否由startService方式所启动的 r.startRequested = true; r.delayedStop = false; //是否作为前台服务启动 r.fgRequired = fgRequired; //构造启动参数 r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), service, neededGrants, callingUid)); //作为前台服务启动 if (fgRequired) { // We are now effectively running a foreground service. ... //使用ServiceState记录 ... //通过AppOpsService监控 } final ServiceMap smap = getServiceMapLocked(r.userId); boolean addToStarting = false; //对于后台启动的非前台服务,需要判断其是否需要延迟启动 if (!callerFg && !fgRequired && r.app == null && mAm.mUserController.hasStartedUserState(r.userId)) { //获取Service所处进程信息 ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false); //没有对应进程或进程状态级别低于 [进程在后台运行Receiver] if (proc == null || proc.getCurProcState() > ActivityManager.PROCESS_STATE_RECEIVER) { // If this is not coming from a foreground caller, then we may want // to delay the start if there are already other background services // that are starting. This is to avoid process start spam when lots // of applications are all handling things like connectivity broadcasts. // We only do this for cached processes, because otherwise an application // can have assumptions about calling startService() for a service to run // in its own process, and for that process to not be killed before the // service is started. This is especially the case for receivers, which // may start a service in onReceive() to do some additional work and have // initialized some global state as part of that. //对于之前已经设置为延迟启动的服务,直接返回 if (r.delayed) { // This service is already scheduled for a delayed start; just leave // it still waiting. return r.name; } //如果当前正在后台启动的Service数大于等于允许同时在后台启动的最大服务数 //将这个Service设置为延迟启动 if (smap.mStartingBackground.size() >= mMaxStartingBackground) { // Something else is starting, delay! smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } //添加到正在启动服务列表中 addToStarting = true; } else if (proc.getCurProcState() >= ActivityManager.PROCESS_STATE_SERVICE) { //进程状态为 [正在运行Service的后台进程] 或 [正在运行Receiver的后台进程] 时 // We slightly loosen when we will enqueue this new service as a background // starting service we are waiting for, to also include processes that are // currently running other services or receivers. //添加到正在启动服务列表中 addToStarting = true; } } //如果允许Service后台启动Activity,则将其加入到白名单中 if (allowBackgroundActivityStarts) { r.whitelistBgActivityStartsOnServiceStart(); } //继续启动Service ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting); //检查是否允许前台服务使用while-in-use权限 if (!r.mAllowWhileInUsePermissionInFgs) { r.mAllowWhileInUsePermissionInFgs = shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, callingPid, callingUid, service, r, allowBackgroundActivityStarts); } return cmp; }这个方法涉及到很多前后台判断,我想这里的前后台其实分为三个概念,一是调用方App是否在前台,二是Service方App是否在前台,三是Service是否作为前台服务启动,当然,大部分情况启动的都是App内的Service,即一二中的前后台状态是一致的,但也不排除启动其他App的Service这种情况,所以这里还是需要好好区分开来这个方法看起来很长,但总之都是一些Service启动前的预处理工作,主要做了以下几点工作:判断调用方进程是否在前台(callerFg):对于调用方在后台启动的Service,需要判断其是否需要延迟启动调用retrieveServiceLocked查找待启动Service信息(ServiceRecord)各种检查,一旦发现不满足启动条件就终止启动Service检查Service所在应用的前后台状态以及后台启动限制,不符合条件则终止启动Service判断是否可以作为前台服务启动如果待启动的Service需要相应权限,则需要用户手动确认权限后,再进行启动取消之前的Service重启任务(如果有)设置ServiceRecord状态,包括上次活动时间,是否由startService方式所启动的,是否作为前台服务启动等如果作为前台服务启动,则需要进行记录和监控对于后台启动的非前台服务,需要判断其是否需要延迟启动调用startServiceInnerLocked继续启动Service //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException { ... //记录 //启动前初始化 r.callStart = false; ... //记录 //拉起服务,如果服务未启动,则会启动服务并调用其onCreate和onStartCommand方法 //如果服务已启动,由于之前构造了启动参数,则会直接调用其onStartCommand方法 String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false); if (error != null) { return new ComponentName("!!", error); } if (r.startRequested && addToStarting) { //对于后台启动服务的情况 //是否为第一个后台启动的服务 boolean first = smap.mStartingBackground.size() == 0; //添加到正在后台启动服务列表中 smap.mStartingBackground.add(r); //设置后台启动服务超时时间(默认15秒) r.startingBgTimeout = SystemClock.uptimeMillis() + mAm.mConstants.BG_START_TIMEOUT; //如果为第一个后台启动的服务,则代表后面暂时没有正在后台启动的服务了 //此时将之前设置为延迟启动的服务调度出来后台启动 if (first) { smap.rescheduleDelayedStartsLocked(); } } else if (callerFg || r.fgRequired) { //对于调用方进程为前台或作为前台服务启动的情况 //将此Service从正在后台启动服务列表和延迟启动服务列表中移除 //如果正在后台启动服务列表中存在此服务的话,将之前设置为延迟启动的服务调度出来后台启动 smap.ensureNotStartingBackgroundLocked(r); } return r.name; }在这个方法中,首先会调用bringUpServiceLocked方法拉起服务,然后根据服务是否为前台启动,分别调用ServiceMap.rescheduleDelayedStartsLocked和ServiceMap.ensureNotStartingBackgroundLocked方法从后台延迟启动服务列表mDelayedStartList中不断地调度启动服务这个方法看起来长,其实做的事情并不多:如果Service已经启动,则调用sendServiceArgsLocked方法直接拉起Service.onStartCommand方法各种检查准备操作(待重启、用户是否启动等,具体见注释)如果Service所在进程已启动,调用realStartServiceLocked方法接着启动Service如果Service所在进程未启动,调用AMS.startProcessLocked方法启动进程将要启动的Service添加到mPendingServices列表中,对于Service所在进程未启动的这种情况,在进程的启动过程中会检查此列表并启动需要启动的Service(即此Service)从这里可以看出来,Service的启动分为两个分支,一个是进程已启动,一个是进程未启动进程未启动在进程未启动的情况下,这里会调用AMS.startProcessLocked方法启动进程,接着等待进程启动完成后,会调用到AMS.attachApplicationLocked方法,在这个方法中有一段关于Service启动的代码://frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java private boolean attachApplicationLocked(@NonNull IApplicationThread thread, int pid, int callingUid, long startSeq) { ... // Find any services that should be running in this process... //检查是否有Services等待启动 if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { badApp = true; } } ... }可以看到,在这里调用了ActiveServices.attachApplicationLocked方法去启动待启动的Service关于App进程启动的流程详见我之前的文章 Android源码分析 - Activity启动流程(中) ,这里就不赘述了ActiveServices.attachApplicationLocked//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java boolean attachApplicationLocked(ProcessRecord proc, String processName) throws RemoteException { boolean didSomething = false; // Update the app background restriction of the caller //更新Service所在App后台限制 proc.mState.setBackgroundRestricted(appRestrictedAnyInBackground( proc.uid, proc.info.packageName)); // Collect any services that are waiting for this process to come up. //启动mPendingServices列表内,该进程下的所有Service if (mPendingServices.size() > 0) { ServiceRecord sr = null; try { for (int i=0; i<mPendingServices.size(); i++) { sr = mPendingServices.get(i); if (proc != sr.isolationHostProc && (proc.uid != sr.appInfo.uid || !processName.equals(sr.processName))) { continue; } final IApplicationThread thread = proc.getThread(); final int pid = proc.getPid(); final UidRecord uidRecord = proc.getUidRecord(); mPendingServices.remove(i); i--; //将App添加至进程中运行的包列表中 proc.addPackage(sr.appInfo.packageName, sr.appInfo.longVersionCode, mAm.mProcessStats); //启动Service realStartServiceLocked(sr, proc, thread, pid, uidRecord, sr.createdFromFg, true); didSomething = true; //如果此Service不再需要了,则停止它 //e.g. 通过bindService启动的服务,但此时调用bindService的Activity已死亡 if (!isServiceNeededLocked(sr, false, false)) { // We were waiting for this service to start, but it is actually no // longer needed. This could happen because bringDownServiceIfNeeded // won't bring down a service that is pending... so now the pending // is done, so let's drop it. bringDownServiceLocked(sr, true); } /* Will be a no-op if nothing pending */ //更新进程优先级 mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE); } } catch (RemoteException e) { throw e; } } // Also, if there are any services that are waiting to restart and // would run in this process, now is a good time to start them. It would // be weird to bring up the process but arbitrarily not let the services // run at this point just because their restart time hasn't come up. //App被杀重启机制,后续文章再详细说明 if (mRestartingServices.size() > 0) { ... } return didSomething; }这个方法会从mPendingServices列表内寻找该进程下的所有待启动Service,然后调用ActiveServices.realStartServiceLocked方法启动它进程已启动对于进程已启动的情况,我们通过ActiveServices.bringUpServiceLocked方法也可以得知,调用了ActiveServices.realStartServiceLocked方法,所以不管进程是否启动,最终都会殊途同归走到ActiveServices.realStartServiceLocked方法启动ServiceActiveServices.realStartServiceLocked//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java /** * Note the name of this method should not be confused with the started services concept. * The "start" here means bring up the instance in the client, and this method is called * from bindService() as well. */ private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) throws RemoteException { //IApplicationThread不存在则抛移除 //即确保ActivityThread存在 if (app.thread == null) { throw new RemoteException(); } //为ServiceRecord设置所属进程 r.setProcess(app); r.restartTime = r.lastActivity = SystemClock.uptimeMillis(); //在此进程中将Service记录为运行中 //返回值为此Service是否之前未启动 final boolean newService = app.startService(r); //记录Service执行操作并设置超时回调 //前台服务超时时间为20s,后台服务超时时间为200s bumpServiceExecutingLocked(r, execInFg, "create"); //更新进程优先级 mAm.updateLruProcessLocked(app, false, null); updateServiceForegroundLocked(r.app, /* oomAdj= */ false); mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); boolean created = false; try { ... //记录 //记录信息 mAm.notifyPackageUse(r.serviceInfo.packageName, PackageManager.NOTIFY_PACKAGE_USE_SERVICE); //设置进程状态 app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); //回到App进程,调度创建Service app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo), app.getReportedProcState()); //显示前台服务通知 r.postNotification(); created = true; } catch (DeadObjectException e) { //杀死进程 mAm.appDiedLocked(app, "Died when creating service"); throw e; } finally { //如果没能成功创建Service if (!created) { // Keep the executeNesting count accurate. //保证executeNesting计数的准确 final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); // Cleanup. //停止服务,清除信息 if (newService) { app.stopService(r); r.setProcess(null); } // Retry. //重试 if (!inDestroying) { scheduleServiceRestartLocked(r, false); } } } //允许管理白名单,如省电模式白名单 if (r.whitelistManager) { app.whitelistManager = true; } //执行Service.onBind方法(通过bindService启动的情况下) requestServiceBindingsLocked(r, execInFg); //更新是否有与Service建立连接的Activity updateServiceClientActivitiesLocked(app, null, true); //添加绑定到Service所在进程的UID if (newService && created) { app.addBoundClientUidsOfNewService(r); } // If the service is in the started state, and there are no // pending arguments, then fake up one so its onStartCommand() will // be called. //如果Service已经启动,并且没有启动项,则构建一个假的启动参数供onStartCommand使用 if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) { r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(), null, null, 0)); } //拉起Service.onStartCommand方法 sendServiceArgsLocked(r, execInFg, true); //走到这里,需要确保此服务不再被视为延迟启动,同时将其从延迟启动服务列表中移除 if (r.delayed) { getServiceMapLocked(r.userId).mDelayedStartList.remove(r); r.delayed = false; } //Service被要求stop,停止服务 if (r.delayedStop) { // Oh and hey we've already been asked to stop! r.delayedStop = false; if (r.startRequested) { stopServiceLocked(r); } } }创建Service到了这一步,进程理应启动和初始化完成了,接下来就该实际的去创建Service并启动它了,首先创建Service这一块我们看app.thread.scheduleCreateService方法,这里的app是ProcessRecord,里面的thread是IApplicationThread,ActivityThread中的内部类 //frameworks/base/core/java/android/app/ActivityThread.java public final void scheduleCreateService(IBinder token, ServiceInfo info, CompatibilityInfo compatInfo, int processState) { //更新进程状态 updateProcessState(processState, false); //将创建Service的必要信息包装 CreateServiceData s = new CreateServiceData(); s.token = token; s.info = info; s.compatInfo = compatInfo; //通过Handler发送Message sendMessage(H.CREATE_SERVICE, s); }这里将创建Service的必要信息包装成CreateServiceData对象后,通过Handler发送Message处理服务创建//frameworks/base/core/java/android/app/ActivityThread.java public void handleMessage(Message msg) { switch (msg.what) { ... case CREATE_SERVICE: handleCreateService((CreateServiceData)msg.obj); break; ... } ... }ActivityThread的Handler在接收到CREATE_SERVICE消息后调用了handleCreateService方法//frameworks/base/core/java/android/app/ActivityThread.java private void handleCreateService(CreateServiceData data) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. //此时不要进行GC unscheduleGcIdler(); LoadedApk packageInfo = getPackageInfoNoCheck( data.info.applicationInfo, data.compatInfo); Service service = null; try { //创建Context ContextImpl context = ContextImpl.createAppContext(this, packageInfo); //创建或获取Application(到了这里进程的初始化应该都完成了,所以是直接获取Application) Application app = packageInfo.makeApplication(false, mInstrumentation); java.lang.ClassLoader cl = packageInfo.getClassLoader(); //通过AppComponentFactory反射创建Service实例 service = packageInfo.getAppFactory() .instantiateService(cl, data.info.name, data.intent); // Service resources must be initialized with the same loaders as the application // context. //加载资源 context.getResources().addLoaders( app.getResources().getLoaders().toArray(new ResourcesLoader[0])); context.setOuterContext(service); //初始化 service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); //执行onCreate回调 service.onCreate(); //保存运行中的Service mServices.put(data.token, service); try { //Service相关任务执行完成 //这一步中会把之前的启动超时定时器取消 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(service, e)) { throw new RuntimeException( "Unable to create service " + data.info.name + ": " + e.toString(), e); } } }可以看到,Service的创建和之前文章中所分析的Activity的创建流程基本一致,都是创建Context,通过AppComponentFactory反射实例化对象,然后加载资源,attach做绑定,最后执行onCreate回调//frameworks/base/core/java/android/app/AppComponentFactory.java public @NonNull Service instantiateService(@NonNull ClassLoader cl, @NonNull String className, @Nullable Intent intent) throws InstantiationException, IllegalAccessException, ClassNotFoundException { return (Service) cl.loadClass(className).newInstance(); }如果没有特别在AndroidManifest.xml中设置android:appComponentFactory的话,默认的实现就是这样,通过传进来的ClassLoader和className反射实例化Service对象//frameworks/base/core/java/android/app/Service.java public final void attach( Context context, ActivityThread thread, String className, IBinder token, Application application, Object activityManager) { //绑定BaseContext attachBaseContext(context); mThread = thread; // NOTE: unused - remove? mClassName = className; //保存ServiceRecord mToken = token; mApplication = application; mActivityManager = (IActivityManager)activityManager; //启动兼容性设置 mStartCompatibility = getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.ECLAIR; //设置内容捕获功能 setContentCaptureOptions(application.getContentCaptureOptions()); }attach方法也很简单,做了一些绑定Context等基本操作最后调用onCreate方法,这个方法默认是个空实现,让继承Service的类去实现这个方法启动ServiceService创建完成后就该启动它了,这里对应着ActiveServices.realStartServiceLocked方法中调用的sendServiceArgsLocked方法//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg, boolean oomAdjusted) throws TransactionTooLargeException { //如果待启动项列表中没有内容则直接返回 final int N = r.pendingStarts.size(); if (N == 0) { return; } ArrayList<ServiceStartArgs> args = new ArrayList<>(); //遍历待启动项 while (r.pendingStarts.size() > 0) { ServiceRecord.StartItem si = r.pendingStarts.remove(0); //如果在多个启动项中有假启动项,则跳过假启动项 //但如果这个假启动项是唯一的启动项则不要跳过它,这是为了支持onStartCommand(null)的情况 if (si.intent == null && N > 1) { // If somehow we got a dummy null intent in the middle, // then skip it. DO NOT skip a null intent when it is // the only one in the list -- this is to support the // onStartCommand(null) case. continue; } si.deliveredTime = SystemClock.uptimeMillis(); r.deliveredStarts.add(si); si.deliveryCount++; //处理Uri权限 if (si.neededGrants != null) { mAm.mUgmInternal.grantUriPermissionUncheckedFromIntent(si.neededGrants, si.getUriPermissionsLocked()); } //授权访问权限 mAm.grantImplicitAccess(r.userId, si.intent, si.callingId, UserHandle.getAppId(r.appInfo.uid) ); //记录Service执行操作并设置超时回调 //前台服务超时时间为20s,后台服务超时时间为200s bumpServiceExecutingLocked(r, execInFg, "start"); if (!oomAdjusted) { oomAdjusted = true; mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_START_SERVICE); } //如果是以前台服务的方式启动的Service(startForegroundService),并且之前没有设置启动前台服务超时回调 if (r.fgRequired && !r.fgWaiting) { //如果当前服务还没成为前台服务,设置启动前台服务超时回调 //在10s内需要调用Service.startForeground成为前台服务,否则停止服务 //注:Android 11这个超时时间是10s,在后面的Android版本中这个时间有变化 if (!r.isForeground) { scheduleServiceForegroundTransitionTimeoutLocked(r); } else { r.fgRequired = false; } } int flags = 0; if (si.deliveryCount > 1) { flags |= Service.START_FLAG_RETRY; } if (si.doneExecutingCount > 0) { flags |= Service.START_FLAG_REDELIVERY; } //添加启动项 args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent)); } //构建出一个支持Binder跨进程传输大量数据的列表来传输启动参数数据 ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args); slice.setInlineCountLimit(4); try { //回到App进程,调度启动Service r.app.thread.scheduleServiceArgs(r, slice); } catch ... }这个方法中有几个比较重要的点需要注意:pendingStarts中至少要有一个启动项才会执行onStartCommand,所以在前面的ActiveServices.realStartServiceLocked方法中才会有这样一段代码:如果Service已经启动,并且没有启动项,则构建一个假的启动参数供onStartCommand使用如果在多个启动项中有假启动项,则跳过假启动项,但如果这个假启动项是唯一的启动项则不要跳过它,这是为了支持onStartCommand方法的第一个参数Intent未null的情况如果服务是以前台服务的方式启动的(startForegroundService),如果当前服务还没成为前台服务,则需要设置一个启动前台服务的超时回调,如果在限制的时间范围内还没有成为前台服务(调用Service.startForeground方法),则会触发超时逻辑,停止服务,这个时间在Android 11上是10s,在后面的Android版本中有变化最后将所有的启动项放到一个支持Binder跨进程传输大量数据的列表中,然后调用App进程中的ActivityThread$ApplicationThread.scheduleServiceArgs方法 //frameworks/base/core/java/android/app/ActivityThread.java public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) { List<ServiceStartArgs> list = args.getList(); for (int i = 0; i < list.size(); i++) { ServiceStartArgs ssa = list.get(i); ServiceArgsData s = new ServiceArgsData(); s.token = token; s.taskRemoved = ssa.taskRemoved; s.startId = ssa.startId; s.flags = ssa.flags; s.args = ssa.args; sendMessage(H.SERVICE_ARGS, s); } }和前面一样,这里也是将启动Service的必要信息包装成一个个ServiceStartArgs对象后,通过Handler依次发送Message处理服务启动,这里最终调用的是ActivityThread.handleServiceArgs方法//frameworks/base/core/java/android/app/ActivityThread.java private void handleServiceArgs(ServiceArgsData data) { Service s = mServices.get(data.token); if (s != null) { try { //Intent跨进程处理 if (data.args != null) { data.args.setExtrasClassLoader(s.getClassLoader()); data.args.prepareToEnterProcess(); } int res; if (!data.taskRemoved) { //正常情况调用 res = s.onStartCommand(data.args, data.flags, data.startId); } else { //用户关闭Task栈时调用 s.onTaskRemoved(data.args); res = Service.START_TASK_REMOVED_COMPLETE; } //确保其他异步任务执行完成 QueuedWork.waitToFinish(); try { //Service相关任务执行完成 //这一步会根据onStartCommand的返回值,调整Service死亡重建策略 //同时会把之前的启动超时定时器取消 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }这里首先判断taskRemoved标志,这个标志为true则代表用户之前从最近任务界面里划掉了这个任务栈或者在最近任务界面里点击了清理,此时会调用Service.onTaskRemoved方法(从最近任务界面关闭应用,进程不一定会被杀死,而且Service具有死亡重建机制),在正常情况下则是调用Service.onStartCommand处理服务启动当任务执行完成后,会调用AMS.serviceDoneExecuting方法告知,在这个方法中会根据onStartCommand的返回值(或执行完onTaskRemoved被赋值为START_TASK_REMOVED_COMPLETE),调整Service的死亡重建策略,并且会把之前的启动超时定时器取消onStartCommand可以有以下几种返回值:START_STICKY_COMPATIBILITY:targetSdkVersion < 5 (Android 2.0) 的App默认会返回这个,Service被杀后会被重建,但onStartCommand方法不会被执行START_STICKY:targetSdkVersion >= 5 (Android 2.0) 的App默认会返回这个,Service被杀后会被重建,onStartCommand方法也会被执行,但此时onStartCommand方法的第一个参数Intent为nullSTART_NOT_STICKY:Service被杀后不会被重建START_REDELIVER_INTENT:Service被杀后会被重建,onStartCommand方法也会被执行,此时onStartCommand方法的第一个参数Intent为Service被杀死前最后一次调用onStartCommand方法时传递的Intent在这里我们只摆出结论,暂时不分析原理,如果感兴趣的话我会在后面的文章中再去详细分析Context.bindService到这里,Service通过startService路径的启动流程我们就基本分析完了,接着我们看另一条路径,bindService//frameworks/base/core/java/android/app/ContextImpl.java public boolean bindService(Intent service, ServiceConnection conn, int flags) { warnIfCallingFromSystemProcess(); return bindServiceCommon(service, conn, flags, null, mMainThread.getHandler(), null, getUser()); } private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, String instanceName, Handler handler, Executor executor, UserHandle user) { // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser. //获取LoadedApk$ServiceDispatcher$IServiceConnection //这个类是用来后续连接建立完成后发布连接,回调ServiceConnection各种方法的 IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (handler != null && executor != null) { throw new IllegalArgumentException("Handler and Executor both supplied"); } if (mPackageInfo != null) { if (executor != null) { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags); } else { sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags); } } else { throw new RuntimeException("Not supported in system context"); } //确保Intent有效 validateServiceIntent(service); try { //获取ActivityRecord的远程Binder对象 IBinder token = getActivityToken(); //targetSdkVersion < 14 (Android 4.0)的情况下,如果没有设置BIND_AUTO_CREATE //则该Service的优先级将会被视为等同于后台任务 if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null && mPackageInfo.getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { flags |= BIND_WAIVE_PRIORITY; } //跨进程准备 service.prepareToLeaveProcess(this); //跨进程使用AMS绑定Service int res = ActivityManager.getService().bindIsolatedService( mMainThread.getApplicationThread(), getActivityToken(), service, service.resolveTypeIfNeeded(getContentResolver()), sd, flags, instanceName, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); } return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }这个方法主要就做了两件事:创建或获取IServiceConnection:这里实际获取到的是LoadedApk中的内部类ServiceDispatcher中的内部类InnerConnection,这个类主要是用来后面建立或断开连接后,回调ServiceConnection接口的各个方法的跨进程调用AMS.bindIsolatedService方法绑定Service //frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public int bindIsolatedService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, String instanceName, String callingPackage, int userId) throws TransactionTooLargeException { enforceNotIsolatedCaller("bindService"); // Refuse possible leaked file descriptors //校验Intent,不允许其携带fd if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } //校验调用方包名 if (callingPackage == null) { throw new IllegalArgumentException("callingPackage cannot be null"); } // Ensure that instanceName, which is caller provided, does not contain // unusual characters. if (instanceName != null) { for (int i = 0; i < instanceName.length(); ++i) { char c = instanceName.charAt(i); if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '.')) { throw new IllegalArgumentException("Illegal instanceName"); } } } synchronized(this) { return mServices.bindServiceLocked(caller, token, service, resolvedType, connection, flags, instanceName, callingPackage, userId); } }这里仅仅做了一些简单的校验,然后将绑定服务的任务转交给了ActiveServices.bindServiceLocked方法//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, String callingPackage, final int userId) throws TransactionTooLargeException { //获取调用方进程记录 final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when binding service " + service); } ActivityServiceConnectionsHolder<ConnectionRecord> activity = null; //token不为空表示是从Activity发起的,token实际为ActivityRecord的远程Binder对象 if (token != null) { //获取Activity与Service的连接记录 activity = mAm.mAtmInternal.getServiceConnectionsHolder(token); //ServiceConnectionsHolder为null说明调用方Activity不在栈中,直接异常返回 if (activity == null) { return 0; } } int clientLabel = 0; PendingIntent clientIntent = null; final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID; //如果调用方为系统级应用 if (isCallerSystem) { // Hacky kind of thing -- allow system stuff to tell us // what they are, so we can report this elsewhere for // others to know why certain services are running. service.setDefusable(true); clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT); if (clientIntent != null) { clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0); if (clientLabel != 0) { // There are no useful extras in the intent, trash them. // System code calling with this stuff just needs to know // this will happen. service = service.cloneFilter(); } } } //像对待Activity一样对待该Service //需要校验调用方应用是否具有MANAGE_ACTIVITY_STACKS权限 if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "BIND_TREAT_LIKE_ACTIVITY"); } //此标志仅用于系统调整IMEs(以及与顶层App密切合作的其他跨进程的用户可见组件)的调度策略,仅限系统级App使用 if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 && !isCallerSystem) { throw new SecurityException("Non-system caller (pid=" + Binder.getCallingPid() + ") set BIND_SCHEDULE_LIKE_TOP_APP when binding service " + service); } //允许绑定Service的应用程序管理白名单,仅限系统级App使用 if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) { throw new SecurityException( "Non-system caller " + caller + " (pid=" + Binder.getCallingPid() + ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service); } //允许绑定到免安装应用提供的服务,仅限系统级App使用 if ((flags & Context.BIND_ALLOW_INSTANT) != 0 && !isCallerSystem) { throw new SecurityException( "Non-system caller " + caller + " (pid=" + Binder.getCallingPid() + ") set BIND_ALLOW_INSTANT when binding service " + service); } //允许Service后台启动Activity //需要校验调用方应用是否具有START_ACTIVITIES_FROM_BACKGROUND权限 if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) { mAm.enforceCallingPermission( android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND, "BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS"); } //判断调用方是否为前台 final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND; final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0; final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0; //查找相应的Service ServiceLookupResult res = retrieveServiceLocked(service, instanceName, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant); if (res == null) { return 0; } if (res.record == null) { return -1; } ServiceRecord s = res.record; boolean permissionsReviewRequired = false; // If permissions need a review before any of the app components can run, // we schedule binding to the service but do not start its process, then // we launch a review activity to which is passed a callback to invoke // when done to start the bound service's process to completing the binding. //如果需要用户手动确认授权 if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired( s.packageName, s.userId)) { permissionsReviewRequired = true; // Show a permission review UI only for binding from a foreground app //只有调用方进程在前台才可以显示授权弹窗 if (!callerFg) { return 0; } final ServiceRecord serviceRecord = s; final Intent serviceIntent = service; //用户手动确认授权后执行的回调 RemoteCallback callback = new RemoteCallback( new RemoteCallback.OnResultListener() { @Override public void onResult(Bundle result) { synchronized(mAm) { final long identity = Binder.clearCallingIdentity(); try { if (!mPendingServices.contains(serviceRecord)) { return; } // If there is still a pending record, then the service // binding request is still valid, so hook them up. We // proceed only if the caller cleared the review requirement // otherwise we unbind because the user didn't approve. //二次检查权限 if (!mAm.getPackageManagerInternalLocked() .isPermissionsReviewRequired( serviceRecord.packageName, serviceRecord.userId)) { try { //拉起服务,如果服务未创建,则会创建服务并调用其onCreate方法 //如果服务已创建则什么都不会做 bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false); } catch (RemoteException e) { /* ignore - local call */ } } else { //无相应权限则解绑Service unbindServiceLocked(connection); } } finally { Binder.restoreCallingIdentity(identity); } } } }); final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName); intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback); //弹出授权弹窗 mAm.mHandler.post(new Runnable() { @Override public void run() { mAm.mContext.startActivityAsUser(intent, new UserHandle(userId)); } }); } final long origId = Binder.clearCallingIdentity(); try { //取消之前的Service重启任务(如果有) if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: " + s); } if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); //如果是第一次绑定的话,设置跟踪器 if (!s.hasAutoCreateConnections()) { // This is the first binding, let the tracker know. ServiceState stracker = s.getTracker(); if (stracker != null) { stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(), s.lastActivity); } } } //绑定的服务代表受保护的系统组件,因此必须对其应用关联做限制 if ((flags & Context.BIND_RESTRICT_ASSOCIATIONS) != 0) { mAm.requireAllowedAssociationsLocked(s.appInfo.packageName); } //建立调用方与服务方之间的关联 mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.getCurProcState(), s.appInfo.uid, s.appInfo.longVersionCode, s.instanceName, s.processName); // Once the apps have become associated, if one of them is caller is ephemeral // the target app should now be able to see the calling app mAm.grantImplicitAccess(callerApp.userId, service, callerApp.uid, UserHandle.getAppId(s.appInfo.uid)); //查询App绑定信息 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp); //创建连接信息 ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent, callerApp.uid, callerApp.processName, callingPackage); IBinder binder = connection.asBinder(); //添加连接 s.addConnection(binder, c); b.connections.add(c); if (activity != null) { activity.addConnection(c); } b.client.connections.add(c); //建立关联 c.startAssociationIfNeeded(); //表示此服务比发起绑定的应用重要性更高 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) { b.client.hasAboveClient = true; } //允许绑定Service的应用程序管理白名单 if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) { s.whitelistManager = true; } //允许Service后台启动Activity if ((flags & Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS) != 0) { s.setHasBindingWhitelistingBgActivityStarts(true); } //更新是否有与Service建立连接的Activity if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c, true); } //更新连接列表 ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); if (clist == null) { clist = new ArrayList<>(); mServiceConnections.put(binder, clist); } clist.add(c); //绑定存在就会自动创建服务 if ((flags&Context.BIND_AUTO_CREATE) != 0) { s.lastActivity = SystemClock.uptimeMillis(); //拉起服务,如果服务未创建,则会创建服务并调用其onCreate方法 //如果服务已创建则什么都不会做 if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) { return 0; } } //检查是否允许前台服务使用while-in-use权限 if (!s.mAllowWhileInUsePermissionInFgs) { s.mAllowWhileInUsePermissionInFgs = shouldAllowWhileInUsePermissionInFgsLocked(callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), service, s, false); } //更新flag以及进程优先级 if (s.app != null) { if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { s.app.treatLikeActivity = true; } if (s.whitelistManager) { s.app.whitelistManager = true; } // This could have made the service more important. mAm.updateLruProcessLocked(s.app, (callerApp.hasActivitiesOrRecentTasks() && s.app.hasClientActivities()) || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0), b.client); mAm.updateOomAdjLocked(s.app, OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE); } if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. //如果服务之前就已经在运行,即Service.onBind方法已经被执行,返回的IBinder对象也已经被保存 //调用LoadedApk$ServiceDispatcher$InnerConnection.connected方法 //回调ServiceConnection.onServiceConnected方法 c.conn.connected(s.name, b.intent.binder, false); // If this is the first app connected back to this binding, // and the service had previously asked to be told when // rebound, then do so. //当服务解绑,调用到Service.onUnbind方法时返回true,此时doRebind变量就会被赋值为true //此时,当再次建立连接时,服务会回调Service.onRebind方法 if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) { //如果服务是因这次绑定而创建的 //请求执行Service.onBind方法,获取返回的IBinder对象 //发布Service,回调ServiceConnection.onServiceConnected方法 requestServiceBindingLocked(s, b.intent, callerFg, false); } maybeLogBindCrossProfileService(userId, callingPackage, callerApp.info.uid); //将此Service从正在后台启动服务列表和延迟启动服务列表中移除 //如果正在后台启动服务列表中存在此服务的话,将之前设置为延迟启动的服务调度出来后台启动 getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s); } finally { Binder.restoreCallingIdentity(origId); } //返回值大于0则视为成功 return 1; }这个方法做的事就比较多了,我们挑重点来说:获取或创建各种连接记录(ActivityServiceConnectionsHolder、AppBindRecord、ConnectionRecord等)校验各种flags查找相应的Service检查是否需要用户手动确认权限并弹出权限确认弹窗向各个连接记录类中添加ConnectionRecord连接信息如果flags设置了BIND_AUTO_CREATE便会调用bringUpServiceLocked方法尝试拉起服务,如果服务未创建,则会创建服务并调用其onCreate方法,如果服务已创建,则什么都不会做:这里和startService路径一样都调用到了bringUpServiceLocked方法,但最终调用的结果却不太一样,这是因为startService路径中,ServiceRecord.startRequested为true并且向ServiceRecord.pendingStarts中添加了启动项,而bindService路径不会向ServiceRecord.pendingStarts中添加启动项,并且由于ServiceRecord.startRequested为false,因此也不会去添加假的启动项,所以和startService不同,最终不会回调Service.onStartCommand方法如果服务之前就已经在运行,则表示Service.onBind方法已经被执行,返回的IBinder对象也已经被保存,此时直接调用LoadedApk$ServiceDispatcher$InnerConnection.connected方法,在这个方法中会回调ServiceConnection.onServiceConnected方法如果服务是因这次绑定而创建的,则调用requestServiceBindingLocked方法请求执行Service.onBind方法,获取返回的IBinder对象,然后发布Service,回调ServiceConnection.onServiceConnected方法最后调用ActiveServices$ServiceMap.ensureNotStartingBackgroundLocked方法继续调度后台Service的启动bringUpServiceLocked方法我们之前已经分析过了,我们接下来看服务创建后所要调用的requestServiceBindingLocked方法//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean execInFg, boolean rebind) throws TransactionTooLargeException { if (r.app == null || r.app.thread == null) { // If service is not currently running, can't yet bind. return false; } if ((!i.requested || rebind) && i.apps.size() > 0) { try { //记录Service执行操作并设置超时回调 //前台服务超时时间为20s,后台服务超时时间为200s bumpServiceExecutingLocked(r, execInFg, "bind"); //设置进程状态 r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE); //回到App进程,调度执行Service的bind操作 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.getReportedProcState()); //请求绑定完成 if (!rebind) { i.requested = true; } i.hasBound = true; i.doRebind = false; } catch (TransactionTooLargeException e) { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); throw e; } catch (RemoteException e) { // Keep the executeNesting count accurate. final boolean inDestroying = mDestroyingServices.contains(r); serviceDoneExecutingLocked(r, inDestroying, inDestroying); return false; } } return true; }和之前一样,这里也是调用App进程中的ActivityThread$ApplicationThread.scheduleBindService方法进行绑定操作//frameworks/base/core/java/android/app/ActivityThread.java public final void scheduleBindService(IBinder token, Intent intent, boolean rebind, int processState) { //更新进程信息 updateProcessState(processState, false); BindServiceData s = new BindServiceData(); s.token = token; s.intent = intent; s.rebind = rebind; sendMessage(H.BIND_SERVICE, s); }将绑定Service的必要信息包装成BindServiceData对象后,通过Handler依次发送Message处理服务启动,这里最终调用的是ActivityThread.handleBindService方法//frameworks/base/core/java/android/app/ActivityThread.java private void handleBindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); try { if (!data.rebind) { //正常情况下回调Service.onBind方法,获得控制Service的IBinder对象 IBinder binder = s.onBind(data.intent); //发布Service ActivityManager.getService().publishService( data.token, data.intent, binder); } else { //当服务解绑,调用到Service.onUnbind方法时返回true,此时doRebind变量就会被赋值为true //此时,当再次建立连接时,服务会回调Service.onRebind方法 s.onRebind(data.intent); //Service相关任务执行完成 //这一步中会把之前的启动超时定时器取消 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to bind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }在这个方法里面调用了Service.onBind方法,获得到了控制Service的IBinder对象,然后再调用AMS.publishService发布服务//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public void publishService(IBinder token, Intent intent, IBinder service) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { if (!(token instanceof ServiceRecord)) { throw new IllegalArgumentException("Invalid service token"); } //转交给ActiveServices处理 mServices.publishServiceLocked((ServiceRecord)token, intent, service); } } //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); //获取Intent绑定记录 IntentBindRecord b = r.bindings.get(filter); if (b != null && !b.received) { //保存控制Service的IBinder对象 b.binder = service; //请求绑定完成 b.requested = true; //IBinder对象获取完成 b.received = true; //遍历所有与此服务绑定的客户端连接 ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections(); for (int conni = connections.size() - 1; conni >= 0; conni--) { ArrayList<ConnectionRecord> clist = connections.valueAt(conni); for (int i=0; i<clist.size(); i++) { ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { continue; } //调用LoadedApk$ServiceDispatcher$IServiceConnection.connected方法 //回调ServiceConnection.onServiceConnected方法 c.conn.connected(r.name, service, false); } } } //Service相关任务执行完成 //这一步中会把之前的启动超时定时器取消 serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false); } } finally { Binder.restoreCallingIdentity(origId); } }在这个方法中,首先将通过Service.onBind获得到的控制Service的IBinder对象保存在IntentBindRecord中,这样之后再有其他client绑定服务,就只需要用它作为参数回调ServiceConnection.onServiceConnected方法就可以了接下来遍历所有与此服务绑定的客户端连接,对符合条件的连接执行LoadedApk$ServiceDispatcher$IServiceConnection.connected方法 //frameworks/base/core/java/android/app/LoadedApk.java public void connected(ComponentName name, IBinder service, boolean dead) throws RemoteException { //mDispatcher是对ServiceDispatcher的弱引用 LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if (sd != null) { //调用ServiceDispatcher.connected方法 sd.connected(name, service, dead); } } public void connected(ComponentName name, IBinder service, boolean dead) { //RunConnection里也是调用了doConnected方法 if (mActivityExecutor != null) { mActivityExecutor.execute(new RunConnection(name, service, 0, dead)); } else if (mActivityThread != null) { mActivityThread.post(new RunConnection(name, service, 0, dead)); } else { doConnected(name, service, dead); } } public void doConnected(ComponentName name, IBinder service, boolean dead) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; synchronized (this) { if (mForgotten) { // We unbound before receiving the connection; ignore // any connection received. return; } old = mActiveConnections.get(name); //如果旧的连接信息中的IBinder对象和本次调用传入的IBinder对象是同一个对象 if (old != null && old.binder == service) { // Huh, already have this one. Oh well! return; } if (service != null) { // A new service is being connected... set it all up. //建立一个新的连接信息 info = new ConnectionInfo(); info.binder = service; info.deathMonitor = new DeathMonitor(name, service); try { //注册Binder死亡通知 service.linkToDeath(info.deathMonitor, 0); //保存本次连接信息 mActiveConnections.put(name, info); } catch (RemoteException e) { // This service was dead before we got it... just // don't do anything with it. //服务已死亡,移除连接信息 mActiveConnections.remove(name); return; } } else { // The named service is being disconnected... clean up. mActiveConnections.remove(name); } //移除Binder死亡通知 if (old != null) { old.binder.unlinkToDeath(old.deathMonitor, 0); } } // If there was an old service, it is now disconnected. //回调ServiceConnection.onServiceDisconnected //通知client之前的连接已被断开 if (old != null) { mConnection.onServiceDisconnected(name); } //如果Service死亡需要回调ServiceConnection.onBindingDied通知client服务死亡 if (dead) { mConnection.onBindingDied(name); } // If there is a new viable service, it is now connected. if (service != null) { //回调ServiceConnection.onServiceConnected方法 //告知client已建立连接 mConnection.onServiceConnected(name, service); } else { // The binding machinery worked, but the remote returned null from onBind(). //当Service.onBind方法返回null时,回调ServiceConnection.onNullBinding方法 mConnection.onNullBinding(name); } }可以看到,在这个方法里最终执行了ServiceConnection.onServiceConnected回调,通知客户端已与Service建立连接至此,整个bindService的流程就结束了

0
0
0
浏览量1681
chole

Android源码分析 - Binder概述

开篇本篇无源码分析,只对Binder做通信过程和基础架构的介绍Binder是Android中最重要的一种进程间通信机制,基于开源的OpenBinderGeorge Hoffman当时任Be公司的工程师,他启动了一个名为OpenBinder的项目,在Be公司被ParmSource公司收购后,OpenBinder由Dinnie Hackborn继续开发,后来成为管理ParmOS6 Cobalt OS的进程的基础。在Hackborn加入谷歌后,他在OpenBinder的基础上开发出了Android Binder(以下简称Binder),用来完成Android的进程通信。为什么需要学习Binder作为一名Android开发,我们每天都在和Binder打交道,虽然可能有的时候不会注意到,譬如:startActivity的时候,会获取AMS服务,调用AMS服务的startActivity方法startActivity传递的对象为什么需要序列化bindService为什么回调的是一个Ibinder对象多进程应用,各个进程之间如何通信AIDL的使用...它们都和Binder有着莫切关系,当碰到上面的场景,或者一些疑难问题的时候,理解Binder机制是非常有必要的为什么Android选择Binder这就要从进程间通信开始说起了,我们先看看比较常见的几种进程间通信方式常见进程间通信共享内存共享内存是进程间通信中最简单的方式之一,共享内存允许两个或更多进程访问同一块内存,当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改,它的原理如下图所示:因为共享内存是访问同一块内存,所以数据不需要进行任何复制,是IPC几种方式中最快,性能最好的方式。但相对应的,共享内存未提供同步机制,需要我们手动控制内存间的互斥操作,较容易发生问题。同时共享内存由于能任意的访问和修改内存中的数据,如果有恶意程序去针对某个程序设计代码,很可能导致隐私泄漏或者程序崩溃,所以安全性较差。管道管道分为命名管道和无名管道,它是以一种特殊的文件作为中间介质,我们称为管道文件,它具有固定的读端和写端,写进程通过写段向管道文件里写入数据,读进程通过读段从读进程中读出数据,构成一条数据传递的流水线,它的原理如下图所示:管道一次通信需要经历2次数据复制(进程A -> 管道文件,管道文件 -> 进程B)。管道的读写分阻塞和非阻塞,管道创建会分配一个缓冲区,而这个缓冲区是有限的,如果传输的数据大小超过缓冲区上限,或者在阻塞模式下没有安排好数据的读写,会出现阻塞的情况。管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式。消息队列消息队列是存放在内核中的消息链表,每个消息队列由消息队列标识符表示。消息队列允许多个进程同时读写消息,发送方与接收方要约定好,消息体的数据类型与大小。消息队列克服了信号承载信息量少、管道只能承载无格式字节流等缺点,消息队列一次通信同样需要经历2次数据复制(进程A -> 消息队列,消息队列 -> 进程B),它的原理如下图所示:SocketSocket原本是为了网络设计的,但也可以通过本地回环地址 (127.0.0.1) 进行进程间通信,后来在Socket的框架上更是发展出一种IPC机制,名叫UNIX Domain Socket。Socket是一种典型的C/S架构,一个Socket会拥有两个缓冲区,一读一写,由于发送/接收消息需要将一个Socket缓冲区中的内容拷贝至另一个Socket缓冲区,所以Socket一次通信也是需要经历2次数据复制,它的原理如下图所示:Binder了解了常见进程间通信的方式,我们再来看一下Binder的原理Binder是基于内存映射mmap设计实现的,我们需要先了解一下mmap的概念mmapmmap是一种内存映射的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。Linux内核不会主动将mmap修改后的内容同步到磁盘文件中,有4个时机会触发mmap映射同步到磁盘:调用 msync 函数主动进行数据同步(主动)调用 munmap 函数对文件进行解除映射关系时(主动)进程退出时(被动)系统关机时(被动)通过这种方式,直接操作映射的这一部分内存,可以避免一些数据复制,从而获得更好的性能原理一次Binder IPC通信的过程分为以下几个步骤:首先,Binder驱动在内核空间中开辟出一个数据接收缓冲区接着,在内核空间中开辟出一个内核缓冲区将内核缓冲区与数据接收缓冲区建立映射关系将数据接收缓冲区与接收进程的用户空间地址建立映射关系发送方进程通过copy_from_user将数据从用户空间复制到内核缓冲区由于内核缓冲区与数据接收缓冲区有映射关系,同时数据接收缓冲区与接收进程的用户空间地址有映射关系,所以在接收进程中可以直接获取到这段数据这样便完成了一次Binder IPC通信,它的原理如下图所示:可以看到,通过mmap,Binder通信时,只需要经历一次数据复制,性能要优于管道/消息队列/socket等方式,在安全性,易用性方面又优于共享内存。鉴于上述原因,Android选择了这种折中的IPC方式,来满足系统对稳定性、传输性能和安全性方面的要求Binder架构Binder也是一种C/S架构,分为BpBinder(客户端)和BBinder(服务端),他们都派生自IBinder。其中BpBinder中的p表示proxy,即代理。BpBinder通过transact来发送事务请求,BBinder通过onTransact来接收相应的事务Binder一次通信的时序图如下:Binder采用分层架构设计总结至此,我们大概了解了一下Android选用Binder的原因,以及Binder的基本结构和通信过程,为之后深入源码层分析Binder做了准备

0
0
0
浏览量1432
chole

Android源码分析 - Service的停止与重建

开篇本篇以android-11.0.0_r25作为基础解析在上一篇文章 Android源码分析 - Service启动流程 中,我们分析了一个Service是怎么启动的,这次我们再来看看一个Service是如何被停止的,什么情况下Service会被重建以及它的重建过程流程图由于Service的停止与重建在实际情况下会收到各种条件影响产生不同的情况,所以这里的流程图我也只画最简路径,以供大家参考主动停止首先,我们来看主动停止的情况,主动停止也分三种:Service自己调用stopSelf或stopSelfResult方法停止使用startService启动的Service,使用stopService方法停止使用bindService启动的Service,使用unbindService方法解除绑定,当没有任何Client和Service绑定时,Service就会自行停止Service.stopSelf 或 Service.stopSelfResultstopSelf和stopSelfResult方法唯一的区别是一个没返回值,一个会返回是否成功//frameworks/base/core/java/android/app/Service.java public final void stopSelf() { stopSelf(-1); } public final void stopSelf(int startId) { if (mActivityManager == null) { return; } try { mActivityManager.stopServiceToken( new ComponentName(this, mClassName), mToken, startId); } catch (RemoteException ex) { } } public final boolean stopSelfResult(int startId) { if (mActivityManager == null) { return false; } try { return mActivityManager.stopServiceToken( new ComponentName(this, mClassName), mToken, startId); } catch (RemoteException ex) { } return false; }这个方法也是直接调用了AMS.stopServiceToken方法//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public boolean stopServiceToken(ComponentName className, IBinder token, int startId) { synchronized(this) { return mServices.stopServiceTokenLocked(className, token, startId); } }然后AMS转手调用了ActiveServices.stopServiceTokenLocked方法//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java boolean stopServiceTokenLocked(ComponentName className, IBinder token, int startId) { //通过className查找相应的ServiceRecord //在Service启动过程中调用的retrieveServiceLocked方法会查找Service,创建ServiceRecord //并将其添加到Map中,findServiceLocked方法只需要从这个Map中去获取即可 ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId()); if (r != null) { if (startId >= 0) { // Asked to only stop if done with all work. Note that // to avoid leaks, we will take this as dropping all // start items up to and including this one. //查找startId所对应的已分发的启动项 ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false); //从已分发启动请求列表中移除 if (si != null) { while (r.deliveredStarts.size() > 0) { ServiceRecord.StartItem cur = r.deliveredStarts.remove(0); cur.removeUriPermissionsLocked(); if (cur == si) { break; } } } //如果传入的启动ID不是Service最后一次启动的ID,则不能停止服务 //ps:每次启动Service,startId都会递增,初始值为1 if (r.getLastStartId() != startId) { return false; } } ... //记录 //重置启动状态(重要,后文中会分析) r.startRequested = false; r.callStart = false; final long origId = Binder.clearCallingIdentity(); //接着停止Service bringDownServiceIfNeededLocked(r, false, false); Binder.restoreCallingIdentity(origId); return true; } return false; }startId机制这里要说一下Service的startId机制,每次启动Service时,ActiveServices.startServiceLocked方法会向ServiceRecord.pendingStarts列表中添加一个启动项ServiceRecord.StartItem,构建这个启动项需要提供一个startId,而这个startId是由ServiceRecord.makeNextStartId生成的//frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java public int makeNextStartId() { lastStartId++; if (lastStartId < 1) { lastStartId = 1; } return lastStartId; } 由于lastStartId的初始值为 0 ,所以第一次调用这个方法,得到的startId就是 1 ,即startId是从 1 开始递增的,由于当Service被停止后,ServiceRecord会从之前的缓存Map中移除,所以下一次再启动Service时会重新创建ServiceRecord,startId会被重置当我们调用stopSelf停止服务时,如果传入了大于等于 0 的startId,此时便会判断这个startId是不是最后一次启动所对应的startId,如果不是的话,则不能停止这个Service这个startId设计的意义是什么呢?我们从IntentService的设计中可以管中窥豹:IntentService是一个运行在另一个线程的,每次处理完任务都会自动停止的Service,但如果你调用多次startService会发现,IntentService.onDestroy方法只会调用一次,这是为什么呢?因为IntentService每次停止,调用stopSelf方法都是带上这次启动的startId的,这样如果一次性有多个启动请求,前面的任务执行完,停止时发现,此次启动请求的startId不是最后一个startId,这样就不会停止掉自身,直到最后一个任务处理完成,避免了Service的多次停止启动消耗系统资源接着,在这个方法的最后,调用bringDownServiceIfNeededLocked方法继续停止服务//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { //检查此服务是否还被需要 //在用stopSelf停止服务的这种情况下 //检查的就是是否有auto-create的连接(flag为BIND_AUTO_CREATE) //如有则不能停止服务 if (isServiceNeededLocked(r, knowConn, hasConn)) { return; } // Are we in the process of launching? //不要停止正在启动中的Service if (mPendingServices.contains(r)) { return; } //继续停止服务 bringDownServiceLocked(r); }这个方法主要就做了一些能否停止服务的检查,主要的停止操作都在下一个bringDownServiceLocked方法中//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final void bringDownServiceLocked(ServiceRecord r) { ... //处理Client与Serivce的连接,进行断开连接以及解除绑定操作 // Check to see if the service had been started as foreground, but being // brought down before actually showing a notification. That is not allowed. //如果此Service是以前台服务的形式启动,并且当前还尚未成为前台服务 if (r.fgRequired) { r.fgRequired = false; r.fgWaiting = false; ... //记录 //将前台服务的超时回调取消 mAm.mHandler.removeMessages( ActivityManagerService.SERVICE_FOREGROUND_TIMEOUT_MSG, r); //这种情况直接令App崩溃,杀死应用 if (r.app != null) { Message msg = mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_FOREGROUND_CRASH_MSG); msg.obj = r.app; msg.getData().putCharSequence( ActivityManagerService.SERVICE_RECORD_KEY, r.toString()); mAm.mHandler.sendMessage(msg); } } //记录销毁时间 r.destroyTime = SystemClock.uptimeMillis(); //从缓存中移除ServiceRecord final ServiceMap smap = getServiceMapLocked(r.userId); ServiceRecord found = smap.mServicesByInstanceName.remove(r.instanceName); // Note when this method is called by bringUpServiceLocked(), the service is not found // in mServicesByInstanceName and found will be null. if (found != null && found != r) { // This is not actually the service we think is running... this should not happen, // but if it does, fail hard. //如果找到的服务不是我们目前停止的服务,应该是一个不可能的情况 //碰到这种情况,将ServiceRecord重新放回去并抛出异常 smap.mServicesByInstanceName.put(r.instanceName, found); throw new IllegalStateException("Bringing down " + r + " but actually running " + found); } //清除ServiceRecord smap.mServicesByIntent.remove(r.intent); r.totalRestartCount = 0; //取消之前的Service重启任务(如果有) unscheduleServiceRestartLocked(r, 0, true); // Also make sure it is not on the pending list. //从待启动Service列表中移除 for (int i=mPendingServices.size()-1; i>=0; i--) { if (mPendingServices.get(i) == r) { mPendingServices.remove(i); } } //关闭前台服务通知 cancelForegroundNotificationLocked(r); //对于已经成为前台服务的Service if (r.isForeground) { //修改应用的活动前台计数,如果计数小于等于0,将其从mActiveForegroundApps列表中移除 decActiveForegroundAppLocked(smap, r); ... //更新统计信息 } //各种清理操作 r.isForeground = false; r.foregroundId = 0; r.foregroundNoti = null; r.mAllowWhileInUsePermissionInFgs = false; // Clear start entries. r.clearDeliveredStartsLocked(); r.pendingStarts.clear(); smap.mDelayedStartList.remove(r); if (r.app != null) { synchronized (r.stats.getBatteryStats()) { r.stats.stopLaunchedLocked(); } //从ProcessRecord中移除Service记录 r.app.stopService(r); //更新服务进程绑定的应用uids r.app.updateBoundClientUids(); //允许绑定Service的应用程序管理白名单 if (r.whitelistManager) { updateWhitelistManagerLocked(r.app); } if (r.app.thread != null) { //更新进程前台服务信息 updateServiceForegroundLocked(r.app, false); try { //记录Service执行操作并设置超时回调 //前台服务超时时间为20s,后台服务超时时间为200s bumpServiceExecutingLocked(r, false, "destroy"); //添加到销毁中Service列表中 mDestroyingServices.add(r); //标记正在销毁中 r.destroying = true; //更新进程优先级 mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); //回到App进程,调度执行Service的stop操作 r.app.thread.scheduleStopService(r); } catch (Exception e) { serviceProcessGoneLocked(r); } } } //清除连接 if (r.bindings.size() > 0) { r.bindings.clear(); } //对于主动停止的Service,不需要重启 if (r.restarter instanceof ServiceRestarter) { ((ServiceRestarter)r.restarter).setService(null); } ... //记录 //将此Service从正在后台启动服务列表和延迟启动服务列表中移除 //如果正在后台启动服务列表中存在此服务的话,将之前设置为延迟启动的服务调度出来后台启动 smap.ensureNotStartingBackgroundLocked(r); }这个方法主要做了以下几件事:处理Client与Serivce的连接,进行断开连接以及解除绑定操作(具体等到后面分析unbindService时再说)对于以前台服务形式启动,并且当前还尚未成为前台服务的Service,直接杀死App各种重置,清理操作关闭前台服务通知将Service添加到销毁中服务列表,并调度执行停止操作,最终回调Service.onDestroy将ServiceRestarter内的ServiceRecord变量设为null,避免其后续重启我们重点看第5步,在这个方法中调用了ActivityThread$ApplicationThread.scheduleStopService去调度执行停止服务操作我们重点看第5步,在这个方法中调用了ActivityThread$ApplicationThread.scheduleStopService去调度执行停止服务操作 //frameworks/base/core/java/android/app/ActivityThread.java public final void scheduleStopService(IBinder token) { sendMessage(H.STOP_SERVICE, token); }同样的,也是通过Handler发送Message处理服务停止,这里最终调用的是ActivityThread.handleStopService方法//frameworks/base/core/java/android/app/ActivityThread.java private void handleStopService(IBinder token) { //从Service列表中取出并移除此服务 Service s = mServices.remove(token); if (s != null) { try { //调用Service.onDestroy s.onDestroy(); //解绑以及清理(解除对ServiceRecord的Binder远程对象的引用) s.detachAndCleanUp(); //执行清理操作,具体来说就是断开其他客户端与Service的连接以及解除绑定 Context context = s.getBaseContext(); if (context instanceof ContextImpl) { final String who = s.getClassName(); ((ContextImpl) context).scheduleFinalCleanup(who, "Service"); } //确保其他异步任务执行完成 QueuedWork.waitToFinish(); try { //Service相关任务执行完成 //这一步中会把之前的超时定时器取消 ActivityManager.getService().serviceDoneExecuting( token, SERVICE_DONE_EXECUTING_STOP, 0, 0); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to stop service " + s + ": " + e.toString(), e); } } } }可以看到,这里首先从mServices列表中取出并移除此服务,然后触发Service.onDestroy回调,之后还需要调用ContextImpl.scheduleFinalCleanup方法执行一些清理工作,这一部分的分析我们留到后面unbindService章节里再讲,这样,整个Service的停止流程就到此结束了stopService接下来我们来看一下调用方调用stopService停止服务的情况//frameworks/base/core/java/android/app/ContextImpl.java public boolean stopService(Intent service) { warnIfCallingFromSystemProcess(); return stopServiceCommon(service, mUser); } private boolean stopServiceCommon(Intent service, UserHandle user) { try { //验证Intent有效性 validateServiceIntent(service); //跨进程处理 service.prepareToLeaveProcess(this); //调用AMS.stopService int res = ActivityManager.getService().stopService( mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to stop service " + service); } return res != 0; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }这里基本上是直接调用AMS.stopService进入系统进程处理服务停止//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public int stopService(IApplicationThread caller, Intent service, String resolvedType, int userId) { enforceNotIsolatedCaller("stopService"); // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { //转交给ActiveServices处理 return mServices.stopServiceLocked(caller, service, resolvedType, userId); } } //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java int stopServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int userId) { final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); if (caller != null && callerApp == null) { throw new SecurityException( "Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when stopping service " + service); } // If this service is active, make sure it is stopped. //查找相应的Service,其中入参createIfNeeded为false,所以如果从缓存中找不到ServiceRecord的话则会直接返回null ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, null, Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false, false); if (r != null) { if (r.record != null) { final long origId = Binder.clearCallingIdentity(); try { //接着处理停止服务 stopServiceLocked(r.record); } finally { Binder.restoreCallingIdentity(origId); } return 1; } return -1; } return 0; } private void stopServiceLocked(ServiceRecord service) { if (service.delayed) { // If service isn't actually running, but is being held in the // delayed list, then we need to keep it started but note that it // should be stopped once no longer delayed. service.delayedStop = true; return; } ... //统计信息记录 //重置启动状态(重要,后文中会分析) service.startRequested = false; service.callStart = false; //和上文一样,停止Service bringDownServiceIfNeededLocked(service, false, false); }可以看到,这里和上文中分析的以stopSelf方式停止服务一样,先重置启动状态,然后调用bringDownServiceIfNeededLocked停止服务unbindService接下来的是通过bindService方法,并且flag为BIND_AUTO_CREATE启动的Service,我们需要通过unbindService方法解除绑定,当最终没有任何flag为BIND_AUTO_CREATE的客户端与Service绑定,这个Service就会被停止 //frameworks/base/core/java/android/app/ContextImpl.java public void unbindService(ServiceConnection conn) { if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { //将ServiceDispatcher的状态设置为forgotten,之后便不再会回调ServiceConnection任何方法 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher( getOuterContext(), conn); try { //调用AMS.unbindService方法 ActivityManager.getService().unbindService(sd); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } else { throw new RuntimeException("Not supported in system context"); } }这个方法中首先调用了LoadedApk.forgetServiceDispatcher方法//frameworks/base/core/java/android/app/LoadedApk.java public final IServiceConnection forgetServiceDispatcher(Context context, ServiceConnection c) { synchronized (mServices) { ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context); LoadedApk.ServiceDispatcher sd = null; if (map != null) { sd = map.get(c); if (sd != null) { //移除ServiceDispatcher map.remove(c); //清理连接并标记遗忘 sd.doForget(); if (map.size() == 0) { mServices.remove(context); } ... //debug return sd.getIServiceConnection(); } } ... //debug ... //异常 } }将ServiceDispatcher从缓存中移除并调用LoadedApk$ServiceDispatcher.doForget方法//frameworks/base/core/java/android/app/LoadedApk.java void doForget() { synchronized(this) { for (int i=0; i<mActiveConnections.size(); i++) { ServiceDispatcher.ConnectionInfo ci = mActiveConnections.valueAt(i); ci.binder.unlinkToDeath(ci.deathMonitor, 0); } mActiveConnections.clear(); mForgotten = true; } } 这里将所有连接的binder死亡回调移除,然后清除所有连接,再将mForgotten标记设为true接着我们会走到AMS.unbindService方法中//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public boolean unbindService(IServiceConnection connection) { synchronized (this) { return mServices.unbindServiceLocked(connection); } }同样的,将工作转交给ActiveServices//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java boolean unbindServiceLocked(IServiceConnection connection) { IBinder binder = connection.asBinder(); ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); //找不到连接记录,直接返回 if (clist == null) { return false; } final long origId = Binder.clearCallingIdentity(); try { //遍历连接 while (clist.size() > 0) { ConnectionRecord r = clist.get(0); //移除连接 removeConnectionLocked(r, null, null); //removeConnectionLocked方法会将此ConnectionRecord从连接列表中移除 //如果此ConnectionRecord仍然存在的话,是一个严重的错误,这里再移除一次 if (clist.size() > 0 && clist.get(0) == r) { // In case it didn't get removed above, do it now. Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder); clist.remove(0); } if (r.binding.service.app != null) { if (r.binding.service.app.whitelistManager) { updateWhitelistManagerLocked(r.binding.service.app); } // This could have made the service less important. if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { r.binding.service.app.treatLikeActivity = true; mAm.updateLruProcessLocked(r.binding.service.app, r.binding.service.app.hasClientActivities() || r.binding.service.app.treatLikeActivity, null); } } } //更新顶层应用进程优先级 mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); } finally { Binder.restoreCallingIdentity(origId); } return true; }没看到什么特别重要的逻辑,看来重点应该在removeConnectionLocked这个方法中了//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityServiceConnectionsHolder skipAct) { IBinder binder = c.conn.asBinder(); AppBindRecord b = c.binding; ServiceRecord s = b.service; //这里的clist是ServiceRecord中的列表,和上一个方法中的clist不是一个对象 ArrayList<ConnectionRecord> clist = s.getConnections().get(binder); //移除各种连接 if (clist != null) { clist.remove(c); if (clist.size() == 0) { s.removeConnection(binder); } } b.connections.remove(c); c.stopAssociation(); if (c.activity != null && c.activity != skipAct) { c.activity.removeConnection(c); } if (b.client != skipApp) { b.client.connections.remove(c); ... //各种flag的处理 //更新是否有与Service建立连接的Activity if (s.app != null) { updateServiceClientActivitiesLocked(s.app, c, true); } } //将连接从mServiceConnections列表中移除 //这个clist才是和上一个方法是同一个对象 clist = mServiceConnections.get(binder); if (clist != null) { clist.remove(c); if (clist.size() == 0) { mServiceConnections.remove(binder); } } mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.appInfo.longVersionCode, s.instanceName, s.processName); //如果调用方App没有其他连接和Service绑定 //则将整个AppBindRecord移除 if (b.connections.size() == 0) { b.intent.apps.remove(b.client); } if (!c.serviceDead) { //如果服务端进程存活并且没有其他连接绑定了,同时服务还处在绑定关系中(尚未回调过Service.onUnbind) if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { bumpServiceExecutingLocked(s, false, "unbind"); if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0 && s.app.setProcState <= ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { // If this service's process is not already in the cached list, // then update it in the LRU list here because this may be causing // it to go down there and we want it to start out near the top. mAm.updateLruProcessLocked(s.app, false, null); } mAm.updateOomAdjLocked(s.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); //标记为未绑定 b.intent.hasBound = false; // Assume the client doesn't want to know about a rebind; // we will deal with that later if it asks for one. b.intent.doRebind = false; //回到App进程,调度执行Service的unbind操作 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); } catch (Exception e) { serviceProcessGoneLocked(s); } } // If unbound while waiting to start and there is no connection left in this service, // remove the pending service if (s.getConnections().isEmpty()) { mPendingServices.remove(s); } if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { //是否有其他含有BIND_AUTO_CREATE标记的连接 boolean hasAutoCreate = s.hasAutoCreateConnections(); ... //记录 bringDownServiceIfNeededLocked(s, true, hasAutoCreate); } } }这个方法主要做了以下几件事:执行各种移除操作如果目标服务在此次解绑后不再有任何其他连接与其绑定,则调度执行Service的unbind操作如果此次断开的连接的flag中包含BIND_AUTO_CREATE,则调用bringDownServiceIfNeededLocked尝试停止服务2、3两点都很重要,我们首先看第2点,什么情况下会在这里调度执行Service的unbind操作,前面描述的其实不是很准确,准确的来说应该是目标服务在同一个IntentBindRecord下,此次解绑后不再有任何其他连接与其绑定。那么什么叫同一个IntentBindRecord呢?这和我们启动服务传入的Intent有关,IntentBindRecord的第一次创建是在我们调用bindService后,走到ActiveServices.bindServiceLocked方法中,其中有一段代码调用了ServiceRecord.retrieveAppBindingLocked方法产生的 //frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord i = bindings.get(filter); if (i == null) { i = new IntentBindRecord(this, filter); bindings.put(filter, i); } AppBindRecord a = i.apps.get(app); if (a != null) { return a; } a = new AppBindRecord(this, i, app); i.apps.put(app, a); return a; }在这个方法中,它将我们传入的Intent包装成了Intent.FilterComparison对象,然后尝试用它作为key从ArrayMap``bindings中取获取IntentBindRecord,如果获取不到则会创建一个新的,那么是否是同一个IntentBindRecord的判断标准就是包装后的Intent.FilterComparison对象的HashCode是否相等,我们来看一下它的HashCode是怎样计算的: //frameworks/base/core/java/android/content/Intent.java public static final class FilterComparison { private final Intent mIntent; private final int mHashCode; public FilterComparison(Intent intent) { mIntent = intent; mHashCode = intent.filterHashCode(); } ... @Override public int hashCode() { return mHashCode; } } public int filterHashCode() { int code = 0; if (mAction != null) { code += mAction.hashCode(); } if (mData != null) { code += mData.hashCode(); } if (mType != null) { code += mType.hashCode(); } if (mIdentifier != null) { code += mIdentifier.hashCode(); } if (mPackage != null) { code += mPackage.hashCode(); } if (mComponent != null) { code += mComponent.hashCode(); } if (mCategories != null) { code += mCategories.hashCode(); } return code; }可以看到,只有以上参数全部相等,才会被视为同一个Intent,而我们通常使用Intent只会设置它的mComponent,所以在一般情况下Service的onBind和onUnbind也只会触发一次(在Service没有被销毁的情况下)接着我们来看第3点,如果此次断开的连接的flag中包含BIND_AUTO_CREATE,首先会去查询是否有其他含有BIND_AUTO_CREATE标记的连接,然后以此作为参数调用bringDownServiceIfNeededLocked尝试停止服务 //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { //检查此服务是否还被需要 if (isServiceNeededLocked(r, knowConn, hasConn)) { return; } // Are we in the process of launching? //不要停止正在启动中的Service if (mPendingServices.contains(r)) { return; } //继续停止服务 bringDownServiceLocked(r); } private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn, boolean hasConn) { // Are we still explicitly being asked to run? //Service之前是否通过startService启动过并且未stop if (r.startRequested) { return true; } // Is someone still bound to us keeping us running? //这里我们传入的是true //因为我们之前已经做了检查,知道了是否还有其他auto-create的连接 if (!knowConn) { hasConn = r.hasAutoCreateConnections(); } //如果还有其他auto-create的连接 //则此服务还被需要 if (hasConn) { return true; } return false; }可以看到,经过上述检查,如果发现此Service确实可以被停止了,则会调用bringDownServiceLocked方法停止服务//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final void bringDownServiceLocked(ServiceRecord r) { //断开所有连接 ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections(); for (int conni = connections.size() - 1; conni >= 0; conni--) { ArrayList<ConnectionRecord> c = connections.valueAt(conni); for (int i=0; i<c.size(); i++) { ConnectionRecord cr = c.get(i); // There is still a connection to the service that is // being brought down. Mark it as dead. //将服务标记为死亡 cr.serviceDead = true; cr.stopAssociation(); //回调ServiceConnection各种方法 //通知client服务断开连接以及死亡 cr.conn.connected(r.name, null, true); } } // Tell the service that it has been unbound. //通知Service解除绑定 if (r.app != null && r.app.thread != null) { boolean needOomAdj = false; //遍历所有连接,解除绑定 for (int i = r.bindings.size() - 1; i >= 0; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); //如果还处在绑定关系中(尚未回调过Service.onUnbind) if (ibr.hasBound) { try { //记录Service执行操作并设置超时回调 //前台服务超时时间为20s,后台服务超时时间为200s bumpServiceExecutingLocked(r, false, "bring down unbind"); needOomAdj = true; //标记为未绑定 ibr.hasBound = false; ibr.requested = false; //回到App进程,调度执行Service的unbind操作 r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent()); } catch (Exception e) { needOomAdj = false; serviceProcessGoneLocked(r); break; } } } //更新服务端进程优先级 if (needOomAdj) { mAm.updateOomAdjLocked(r.app, true, OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE); } } ... //和上文相同 }这个方法我们在前面分析stopSelf的时候说过了,这次我们只看和绑定服务有关的部分首先断开所有连接,回调ServiceConnection各种方法,通知客户端服务断开连接以及死亡,这里需要注意的是,我们本次执行unbindService操作的连接已经在上一步中从ServiceRecord.connections列表中移除,所以并不会回调它的ServiceConnection的任何方法,这也是很多人对unbindService方法的误解(包括我自己),bindService方法在成功绑定服务后会回调ServiceConnection.onServiceConnected方法,但unbindService方法在成功解绑服务后并不会回调ServiceConnection.onServiceDisconnected以及任何其它方法,这些方法只会在Service被以其他方式停止(比如后面会分析的混合启动的服务如何停止)或者Service意外停止(比如服务端应用崩溃或被杀死)的情况才会被调用所以这里处理的是断开其他的连接,我们假设一个场景,使用同一个Intent和两个不同的ServiceConnection,一个使用BIND_AUTO_CREATE标记,一个使用其他标记,先绑定BIND_AUTO_CREATE标记的Service,然后再绑定其他标记的Service,接着我们对BIND_AUTO_CREATE标记的Serivce调用unbindService解绑,此时就会走到这个方法中,ServiceRecord.connections列表中会存在那个使用其他标记的连接,然后其内部成员变量conn的connected方法,这个conn是一个IServiceConnection类型,实际上的实现类为LoadedApk$ServiceDispatcher$InnerConnection,最终会调用到LoadedApk$ServiceDispatcher.doConnected方法 public void doConnected(ComponentName name, IBinder service, boolean dead) { ServiceDispatcher.ConnectionInfo old; ServiceDispatcher.ConnectionInfo info; synchronized (this) { //被标记为遗忘则不处理任何事情 //调用unbindService就会将这个标志设为true if (mForgotten) { // We unbound before receiving the connection; ignore // any connection received. return; } old = mActiveConnections.get(name); //如果旧的连接信息中的IBinder对象和本次调用传入的IBinder对象是同一个对象 if (old != null && old.binder == service) { // Huh, already have this one. Oh well! return; } if (service != null) { // A new service is being connected... set it all up. //建立一个新的连接信息 info = new ConnectionInfo(); info.binder = service; info.deathMonitor = new DeathMonitor(name, service); try { //注册Binder死亡通知 service.linkToDeath(info.deathMonitor, 0); //保存本次连接信息 mActiveConnections.put(name, info); } catch (RemoteException e) { // This service was dead before we got it... just // don't do anything with it. //服务已死亡,移除连接信息 mActiveConnections.remove(name); return; } } else { // The named service is being disconnected... clean up. mActiveConnections.remove(name); } //移除Binder死亡通知 if (old != null) { old.binder.unlinkToDeath(old.deathMonitor, 0); } } // If there was an old service, it is now disconnected. //回调ServiceConnection.onServiceDisconnected //通知client之前的连接已被断开 if (old != null) { mConnection.onServiceDisconnected(name); } //如果Service死亡需要回调ServiceConnection.onBindingDied通知client服务死亡 if (dead) { mConnection.onBindingDied(name); } // If there is a new viable service, it is now connected. if (service != null) { //回调ServiceConnection.onServiceConnected方法 //告知client已建立连接 mConnection.onServiceConnected(name, service); } else { // The binding machinery worked, but the remote returned null from onBind(). //当Service.onBind方法返回null,或者Service停止时 //回调ServiceConnection.onNullBinding方法 mConnection.onNullBinding(name); } }这个方法其实我们在上一篇文章中已经说过了,不过在上一篇文章中我们关注的是Service绑定的部分,而这次我们关注的是解绑的部分首先映入眼帘的就是对mForgotten变量的判断,它在客户端调用unbindService就会被设为true,然后便会直接返回,不再处理后续事项。当然,实际上执行完unbindService方法后,客户端与Service的连接会被移除,理论上应该也不会再走到这个方法里才对(这里我也感觉有点疑惑)根据这段代码,我们能看出来Service停止后,对客户端的回调是什么:当Service.onBind方法的返回不为null时,此时会依次回调ServiceConnection.onServiceDisconnected、ServiceConnection.onBindingDied和ServiceConnection.onNullBinding方法当Service.onBind方法的返回为null时,此时会依次回调ServiceConnection.onBindingDied和ServiceConnection.onNullBinding方法大家也可以自己写写Demo来检验一下我说的是否正确这一步处理完后,接下来要做的便是处理Service那边的解绑,遍历IntentBindRecord列表,调用ActivityThread$ApplicationThread.scheduleUnbindService去调度执行服务解绑操作,这里通过Handler最终调用的是ActivityThread.handleUnbindService方法 //frameworks/base/core/java/android/app/ActivityThread.java private void handleUnbindService(BindServiceData data) { Service s = mServices.get(data.token); if (s != null) { try { data.intent.setExtrasClassLoader(s.getClassLoader()); data.intent.prepareToEnterProcess(); //回调Service.onUnbind方法,如果返回值为true //当再次建立连接时,服务会回调Service.onRebind方法 boolean doRebind = s.onUnbind(data.intent); try { if (doRebind) { ActivityManager.getService().unbindFinished( data.token, data.intent, doRebind); } else { ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0); } } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to unbind to service " + s + " with " + data.intent + ": " + e.toString(), e); } } } }可以看到,这里回调了Service.onUnbind方法,它的返回值表示当Service后面再与其他客户端建立连接时,是否需要回调Service.onRebind方法,但是这有一个前提,那就是Service中途没有被停止,具体原因以及rebind流程我们稍后再分析到了这一步,解绑就完成了,接下来和之前在stopSelf章节里分析的后续流程就一样了,最终调用ActivityThread.handleStopService方法停止服务,还记得我们之前分析在这个方法中触发完Service.onDestroy回调,之后还需要调用ContextImpl.scheduleFinalCleanup方法吗?现在我们就来看看这个方法又做了什么事情 //frameworks/base/core/java/android/app/ContextImpl.java final void scheduleFinalCleanup(String who, String what) { mMainThread.scheduleContextCleanup(this, who, what); }这里的mMainThread就是应用的ActivityThread//frameworks/base/core/java/android/app/ActivityThread.java final void scheduleContextCleanup(ContextImpl context, String who, String what) { ContextCleanupInfo cci = new ContextCleanupInfo(); cci.context = context; cci.who = who; cci.what = what; sendMessage(H.CLEAN_UP_CONTEXT, cci); }还是老样子通过Handler发消息,最终调用的是ContextImpl.performFinalCleanup方法//frameworks/base/core/java/android/app/ContextImpl.java final void performFinalCleanup(String who, String what) { mPackageInfo.removeContextRegistrations(getOuterContext(), who, what); }然后调用LoadedApk.removeContextRegistrations方法执行清理操作//frameworks/base/core/java/android/app/LoadedApk.java public void removeContextRegistrations(Context context, String who, String what) { ... //清理广播接收器 synchronized (mServices) { ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = mServices.remove(context); if (smap != null) { for (int i = 0; i < smap.size(); i++) { LoadedApk.ServiceDispatcher sd = smap.valueAt(i); ... //报告ServiceConnection泄露 try { ActivityManager.getService().unbindService( sd.getIServiceConnection()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } sd.doForget(); } } mUnboundServices.remove(context); } }可能看到这里,有很多小伙伴会有疑问,为什么之前已经清理过了,这里还要再进行清理、这里为什么会有ServiceConnection泄露、这里为什么还要再次unbindService?那我们需要注意了,这里被调用的对象到底是谁?其实是Service的Context,假设我们在Serivce里调用bindService又绑定了一个其他Service,那这个Service被销毁后,它和另一个Service的连接怎么办?是不是就产生了泄露?为了防止这种情况,所以我们需要在Service销毁时调用一下这个方法解除它与其他Service的绑定而且这个方法不仅会在这里被调用到哦,在我们之前分析过的 Android源码分析 - Activity销毁流程 中,也存在它的身影,当Activity被销毁,走到handleDestroyActivity方法时,会调用到我们ContextImpl.scheduleFinalCleanup方法,进行广播接收器的清理以及服务的解绑至此,Service的主动停止流程我们都分析完了,还有一些细枝末节的事情可以说一说rebind流程之前我们说过,rebind的前提是Service中途没有被停止,为什么呢?带着疑问,我们来看之前没有分析的,当Service.onUnbind方法返回值为true时,会调用的AMS.unbindFinished方法//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public void unbindFinished(IBinder token, Intent intent, boolean doRebind) { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); } synchronized(this) { mServices.unbindFinishedLocked((ServiceRecord)token, intent, doRebind); } } 还是转交给ActiveServices去实现//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) { final long origId = Binder.clearCallingIdentity(); try { if (r != null) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); boolean inDestroying = mDestroyingServices.contains(r); if (b != null) { //服务unbind的前提就是IntentBindRecord.apps.size == 0 if (b.apps.size() > 0 && !inDestroying) { ... } else { // Note to tell the service the next time there is // a new client. //将doRebind标记置为true,下一次再次建立连接时 //服务会回调Service.onRebind方法 b.doRebind = true; } } serviceDoneExecutingLocked(r, inDestroying, false); } } finally { Binder.restoreCallingIdentity(origId); } }根据我们之前的分析,我们知道,回调Service.onUnbind的前提就是这个Service没有任何连接与其绑定了,即IntentBindRecord.apps.size == 0,在这个case下,这个方法会将IntentBindRecord的doRebind变量置为true此时让我们再回顾一下上一篇文章 Android源码分析 - Service启动流程 中分析的bindService流程,在ActiveServices.bindServiceLocked方法中有这么一段代码//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String instanceName, String callingPackage, final int userId) throws TransactionTooLargeException { ... if (s.app != null && b.intent.received) { // Service is already running, so we can immediately // publish the connection. //如果服务之前就已经在运行,即Service.onBind方法已经被执行,返回的IBinder对象也已经被保存 //调用LoadedApk$ServiceDispatcher$InnerConnection.connected方法 //回调ServiceConnection.onServiceConnected方法 c.conn.connected(s.name, b.intent.binder, false); // If this is the first app connected back to this binding, // and the service had previously asked to be told when // rebound, then do so. //当服务解绑,调用到Service.onUnbind方法时返回true,此时doRebind变量就会被赋值为true //此时,当再次建立连接时,服务会回调Service.onRebind方法 if (b.intent.apps.size() == 1 && b.intent.doRebind) { requestServiceBindingLocked(s, b.intent, callerFg, true); } } else if (!b.intent.requested) { //如果服务是因这次绑定而创建的 //请求执行Service.onBind方法,获取返回的IBinder对象 //发布Service,回调ServiceConnection.onServiceConnected方法 requestServiceBindingLocked(s, b.intent, callerFg, false); } ... } 如果Service被停止了,那么它相应的ServiceRecord会从缓存mServicesByInstanceName和mServicesByIntent中移除,那么等到重新启动Service时会新建出一个ServiceRecord,此时里面的变量全部被初始化,b.intent.received == false,b.intent.requested == false,b.intent.doRebind == false,在这种情况下,调用requestServiceBindingLocked方法的最后一个入参rebind为false,就会直接回调Service.onBind方法,而不会回调Service.onRebind方法如果Service没有被停止,且之前有被绑定过,那么b.intent.received == true,代表IBinder对象已获取到,此时如果之前的Service.onUnbind回调返回值为true,那么这里的b.intent.doRebind也为true,再加上如果这是Service断开所有连接后建立的第一次连接,即b.intent.apps.size() == 1,那么此时调用的requestServiceBindingLocked方法的最后一个入参rebind为true,就会直接回调Service.onRebind方法,而不会回调Service.onBind方法混合启动的Service该如何停止单一启动方式的Service的停止很简单,那么混合启动的Service该如何停止呢?何为混合启动?指的是通过startService方式启动Service并且以BIND_AUTO_CREATE标志调用bindService方法绑定Service,两者不分先后在上面的分析中,我们注意到,不管用哪种方式停止服务,最后都会走到bringDownServiceIfNeededLocked方法中,在这个方法里又会调用isServiceNeededLocked判断是否Service是否被需要,那被需要的条件是什么呢?Service.startRequested为true,并且没有标志为BIND_AUTO_CREATE的连接绑定,那么,只要不符合这两个条件,服务自然就可以被停止了没有标志为BIND_AUTO_CREATE的连接绑定这个简单,只需要把标记为BIND_AUTO_CREATE的连接全部解绑了就好,那么怎么让Service.startRequested为false呢?我们回顾一下之前对stopSelf和stopService的分析,在他们调用bringDownServiceIfNeededLocked方法之前,都会先将Service.startRequested设置为false,所以答案就很明显了:只要unbindService掉所有BIND_AUTO_CREATE的标志的连接,然后stopService就能停止掉混合启动的服务,当然你也可以先stopService,再unbindService掉所有BIND_AUTO_CREATE的标志的连接小测验经过以上一系列的分析,我给大家出几个小问题:先通过startService启动服务,然后再用BIND_AUTO_CREATE标志bindService(连接1),此时,Service的生命周期是怎样的?ServiceConnection会回调哪些方法?在上一题的基础上,再使用一个非BIND_AUTO_CREATE标志bindService(连接2),此时,Service的生命周期是怎样的?ServiceConnection会回调哪些方法?此时,使用unbindService解绑连接1,会发生什么?ServiceConnection会回调哪些方法?此时,使用unbindService解绑连接2,会发生什么?ServiceConnection会回调哪些方法?接着,再使用连接1bindService,会发生什么?ServiceConnection会回调哪些方法?然后,调用stopService停止服务,服务真的会被停止吗?Service的生命周期是怎样的?连接1的ServiceConnection会回调哪些方法?紧接着,再使用连接2bindService,会发生什么?连接2的ServiceConnection会回调哪些方法?最后,调用unbindService解绑连接1,会发生什么?Service的生命周期是怎样的?ServiceConnection会回调哪些方法?请大家思考片刻,可以去回顾之前的Service启动分析以及停止流程分析,如果以上问题能全部回答正确,证明你对Service已经有了一个很深刻的理解,接下来揭晓答案:生命周期:onCreate -> onStartCommand -> onBind,如果onBind的返回值不为null,ServiceConnection会回调onServiceConnected方法,如果onBind的返回值为null,ServiceConnection会回调onNullBinding方法生命周期不会发生变化,如果onBind的返回值不为null,ServiceConnection会回调onServiceConnected方法,如果onBind的返回值为null,ServiceConnection会回调onNullBinding方法生命周期不会发生变化,ServiceConnection不会回调任何方法生命周期:onUnbind,ServiceConnection不会回调任何方法如果之前onUnbind的返回值为true,则生命周期为:onRebind,否则生命周期不会发生变化,如果之前onBind的返回值不为null,ServiceConnection会回调onServiceConnected方法,如果之前onBind的返回值为null,ServiceConnection会回调onNullBinding方法不会真的被停止,生命周期不会发生变化,ServiceConnection不会回调任何方法生命周期不会发生变化,如果之前onBind的返回值不为null,ServiceConnection会回调onServiceConnected方法,如果之前onBind的返回值为null,ServiceConnection会回调onNullBinding方法服务会被停止,生命周期:onUnbind -> onDestroy,连接1的ServiceConnection不会回调任何方法,如果之前onBind的返回值不为null,连接2的ServiceConnection会回调onServiceDisconnected、onBindingDied以及onNullBinding方法,如果之前onBind的返回值为null,连接2的ServiceConnection会回调onBindingDied以及onNullBinding方法被动停止Service除了主动停止,还会因为各种情况导致被动停止用户手动从最近任务移除Task注:由于各家系统对进程或任务调度策略不同,所以这里的Task移除逻辑和Service停止逻辑可能会有些许不同,我们还是以原生Android为准分析不管用户是从最近任务划走了一个Task,还是点击了全部清除,最终都会走到ActivityStackSupervisor.removeTaskById方法 //frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java boolean removeTaskById(int taskId, boolean killProcess, boolean removeFromRecents, String reason) { //通过id查询Task final Task task = mRootWindowContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); if (task != null) { removeTask(task, killProcess, removeFromRecents, reason); return true; } return false; }这里的入参,killProcess为true,如果是移除单一Task,那么removeFromRecents为true,如果是清除全部Task,那么removeFromRecents为false先通过id,使用RootWindowContainer查询相应的Task,然后再调用removeTask方法继续移除Task //frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java void removeTask(Task task, boolean killProcess, boolean removeFromRecents, String reason) { //如果Task正在清理中则直接返回 if (task.mInRemoveTask) { // Prevent recursion. return; } //标记Task正在清理中 task.mInRemoveTask = true; try { //销毁此Task下所有Activity task.performClearTask(reason); //清理Task cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); //关闭屏幕固定 mService.getLockTaskController().clearLockedTask(task); //通知任务栈发生变化 mService.getTaskChangeNotificationController().notifyTaskStackChanged(); //启动任务持久化程序,将任何挂起的任务写入磁盘 if (task.isPersistable) { mService.notifyTaskPersisterLocked(null, true); } } finally { //取消标记 task.mInRemoveTask = false; } }这个方法最重要的有两个部分,一个是销毁此Task下所有Activity,对于我们本次而言不需要关注,另一个是调用cleanUpRemovedTaskLocked继续清理Task//frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { //从最近任务列表中移除 //对于清除全部Task而言,之前在RecentTasks中已经进行过移除操作了 //所以传入的removeFromRecents为false if (removeFromRecents) { mRecentTasks.remove(task); } ComponentName component = task.getBaseIntent().getComponent(); if (component == null) { return; } // Find any running services associated with this app and stop if needed. //清理和此Task有关联的服务 final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::cleanUpServices, mService.mAmInternal, task.mUserId, component, new Intent(task.getBaseIntent())); mService.mH.sendMessage(msg); //如果不需要杀死进程,到这里就为止了 if (!killProcess) { return; } // Determine if the process(es) for this task should be killed. final String pkg = component.getPackageName(); ArrayList<Object> procsToKill = new ArrayList<>(); ArrayMap<String, SparseArray<WindowProcessController>> pmap = mService.mProcessNames.getMap(); //遍历App进程,确定要杀死的进程 for (int i = 0; i < pmap.size(); i++) { SparseArray<WindowProcessController> uids = pmap.valueAt(i); for (int j = 0; j < uids.size(); j++) { WindowProcessController proc = uids.valueAt(j); //不要杀死其他用户下的进程 if (proc.mUserId != task.mUserId) { // Don't kill process for a different user. continue; } //不要杀死首页进程 //HomeProcess指的是含有分类为android.intent.category.HOME的进程 //也就是能成为首页Launcher的进程 if (proc == mService.mHomeProcess) { // Don't kill the home process along with tasks from the same package. continue; } //不要杀死和这个Task无关的进程 if (!proc.mPkgList.contains(pkg)) { // Don't kill process that is not associated with this task. continue; } //如果这个进程有Activity在不同的Task里,并且这个Task也在最近任务里 //或者有Activity还没有被停止,则不要杀死进程 if (!proc.shouldKillProcessForRemovedTask(task)) { // Don't kill process(es) that has an activity in a different task that is also // in recents, or has an activity not stopped. return; } //有前台服务的话不要杀死进程 if (proc.hasForegroundServices()) { // Don't kill process(es) with foreground service. return; } // Add process to kill list. procsToKill.add(proc); } } // Kill the running processes. Post on handle since we don't want to hold the service lock // while calling into AM. //杀死进程 final Message m = PooledLambda.obtainMessage( ActivityManagerInternal::killProcessesForRemovedTask, mService.mAmInternal, procsToKill); mService.mH.sendMessage(m); }这个方法主要做两件事,一是清理和此Task有关联的服务,二是杀死应该杀死的进程清理服务这一步用到了池化技术,这里大家不用管,就当做调用了mService.mAmInternal.cleanUpServices即可,这里的mService.mAmInternal是AMS里的一个内部类LocalService//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { synchronized(ActivityManagerService.this) { mServices.cleanUpServices(userId, component, baseIntent); } } 同样,关于Service的工作都转交给ActiveServices//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java void cleanUpServices(int userId, ComponentName component, Intent baseIntent) { ArrayList<ServiceRecord> services = new ArrayList<>(); //获得此用户下所有的活动Service ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(userId); //筛选出此Task下的所有活动Service for (int i = alls.size() - 1; i >= 0; i--) { ServiceRecord sr = alls.valueAt(i); if (sr.packageName.equals(component.getPackageName())) { services.add(sr); } } // Take care of any running services associated with the app. for (int i = services.size() - 1; i >= 0; i--) { ServiceRecord sr = services.get(i); if (sr.startRequested) { if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) { //如果在manifest里设置了stopWithTask,那么会直接停止Service stopServiceLocked(sr); } else { //如果没有设置stopWithTask的话,则会回调Service.onTaskRemoved方法 sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true, sr.getLastStartId(), baseIntent, null, 0)); if (sr.app != null && sr.app.thread != null) { // We always run in the foreground, since this is called as // part of the "remove task" UI operation. try { sendServiceArgsLocked(sr, true, false); } catch (TransactionTooLargeException e) { // Ignore, keep going. } } } } } }首先要获取到所有需要清理的Service记录,然后再对它们进行处理对于在manifest文件里设置了stopWithTask标识的Service,直接调用stopServiceLocked方法停止服务,而对于没有这个标识的Service,则是增加一个启动项,接着调用sendServiceArgsLocked处理这个启动项我们观察这个启动项的构建,第二个参数为true,我们可以去这个类的构造方法那里看到,第二个参数的名字为_taskRemoved,意思很明显了,然后根据我们在上一篇文章 Android源码分析 - Service启动流程 中分析的sendServiceArgsLocked方法可以知道,它最终会走到ActivityThread.handleServiceArgs方法中 //frameworks/base/core/java/android/app/ActivityThread.java private void handleServiceArgs(ServiceArgsData data) { ... int res; if (!data.taskRemoved) { //正常情况调用 res = s.onStartCommand(data.args, data.flags, data.startId); } else { //用户关闭Task栈时调用 s.onTaskRemoved(data.args); res = Service.START_TASK_REMOVED_COMPLETE; } ... }可以发现,当taskRemoved变量为true时,会回调Service.onTaskRemoved方法我们接着回到cleanUpRemovedTaskLocked方法中,当它清理完服务后,便会尝试杀死进程,这里面其他的判断条件我们都不用管,我们只需要关心其中的一段,有前台服务的话不要杀死进程以上是我根据AOSP源码分析得出的结果,在模拟器上也验证通过,但在我的小米MIX4上表现却完全不是这样,大家开发时还是要以实际为准内存不足当内存不足时,系统会通过OOM Killer或Low Memory Killer等手段杀死各种进程,如果被杀死的进程里有Service正在运行,那自然也会被停止重建当Service所在进程被杀死后,根据Service.onStartCommand的返回值,系统会决定是否重建,怎么重建。我们先把其可能的返回值以及产生的结果先列出来:START_STICKY_COMPATIBILITY:targetSdkVersion < 5 (Android 2.0) 的App默认会返回这个,Service被杀后会被重建,但onStartCommand方法不会被执行START_STICKY:targetSdkVersion >= 5 (Android 2.0) 的App默认会返回这个,Service被杀后会被重建,onStartCommand方法也会被执行,但此时onStartCommand方法的第一个参数Intent为nullSTART_NOT_STICKY:Service被杀后不会被重建START_REDELIVER_INTENT:Service被杀后会被重建,onStartCommand方法也会被执行,此时onStartCommand方法的第一个参数Intent为Service被杀死前最后一次调用onStartCommand方法时传递的Intent对于其返回值我们需要先了解一下是怎么处理的,这需要回顾一下上一篇文章分析的handleServiceArgs方法了 //frameworks/base/core/java/android/app/ActivityThread.java private void handleServiceArgs(ServiceArgsData data) { Service s = mServices.get(data.token); if (s != null) { try { ... int res; if (!data.taskRemoved) { //正常情况调用 res = s.onStartCommand(data.args, data.flags, data.startId); } else { //用户关闭Task栈时调用 s.onTaskRemoved(data.args); res = Service.START_TASK_REMOVED_COMPLETE; } //确保其他异步任务执行完成 QueuedWork.waitToFinish(); try { //Service相关任务执行完成 //这一步会根据onStartCommand的返回值,调整Service死亡重建策略 //同时会把之前的启动超时定时器取消 ActivityManager.getService().serviceDoneExecuting( data.token, SERVICE_DONE_EXECUTING_START, data.startId, res); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } catch (Exception e) { if (!mInstrumentation.onException(s, e)) { throw new RuntimeException( "Unable to start service " + s + " with " + data.args + ": " + e.toString(), e); } } } }可以看到,这里从Service.onStartCommand得到返回值后以其作为参数调用了AMS.serviceDoneExecuting方法//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java public void serviceDoneExecuting(IBinder token, int type, int startId, int res) { synchronized(this) { ... mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res); } }转交给了ActiveServices.serviceDoneExecutingLocked方法//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) { boolean inDestroying = mDestroyingServices.contains(r); if (r != null) { if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) { // This is a call from a service start... take care of // book-keeping. r.callStart = true; switch (res) { case Service.START_STICKY_COMPATIBILITY: case Service.START_STICKY: { // We are done with the associated start arguments. r.findDeliveredStart(startId, false, true); // Don't stop if killed. r.stopIfKilled = false; break; } case Service.START_NOT_STICKY: { // We are done with the associated start arguments. r.findDeliveredStart(startId, false, true); if (r.getLastStartId() == startId) { // There is no more work, and this service // doesn't want to hang around if killed. r.stopIfKilled = true; } break; } case Service.START_REDELIVER_INTENT: { // We'll keep this item until they explicitly // call stop for it, but keep track of the fact // that it was delivered. ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false); if (si != null) { si.deliveryCount = 0; si.doneExecutingCount++; // Don't stop if killed. r.stopIfKilled = true; } break; } case Service.START_TASK_REMOVED_COMPLETE: { // Special processing for onTaskRemoved(). Don't // impact normal onStartCommand() processing. r.findDeliveredStart(startId, true, true); break; } default: throw new IllegalArgumentException( "Unknown service start result: " + res); } if (res == Service.START_STICKY_COMPATIBILITY) { r.callStart = false; } } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) { ... } ... } else { ... } }我们就只看对Service.onStartCommand的返回值进行处理的部分首先,不管返回值是什么,都会调用ServiceRecord.findDeliveredStart方法,只不过入参不同//frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java public StartItem findDeliveredStart(int id, boolean taskRemoved, boolean remove) { final int N = deliveredStarts.size(); for (int i=0; i<N; i++) { StartItem si = deliveredStarts.get(i); if (si.id == id && si.taskRemoved == taskRemoved) { if (remove) deliveredStarts.remove(i); return si; } } return null; }前两个参数,不管返回值是什么,传进来的都是一样的,而第三个参数remove就不同了,当返回值为START_REDELIVER_INTENT的时候,它为false,其他情况都为true,意味着要删除这个已分发的启动项,START_REDELIVER_INTENT由于需要保留最后一次调用onStartCommand时的Intent,所以它不应该被删除接着我们回到serviceDoneExecutingLocked方法,可以发现,START_STICKY和START_STICKY_COMPATIBILITY情况下的ServiceRecord.stopIfKilled被置为了false,其他则被置为了true,这和我们之前对结果的描述不同啊?不是说好了返回START_REDELIVER_INTENT也会重启吗?这是因为START_REDELIVER_INTENT比较特殊,它的重启不需要看stopIfKilled这个标志位,这个等到我们后面分析到怎么判断是否应该停止服务时就知道了以上的内容我们先记下来,会在后面的重启流程中发挥作用然后我们来看进程死亡后会发生什么,我们曾在之前的文章 Android源码分析 - Activity启动流程(中) 中提到过,当App启动时,AMS会为其注册一个App进程死亡回调AppDeathRecipient,当App进程死亡后便会回调其binderDied方法 //frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java private final class AppDeathRecipient implements IBinder.DeathRecipient { final ProcessRecord mApp; final int mPid; final IApplicationThread mAppThread; AppDeathRecipient(ProcessRecord app, int pid, IApplicationThread thread) { mApp = app; mPid = pid; mAppThread = thread; } @Override public void binderDied() { synchronized(ActivityManagerService.this) { appDiedLocked(mApp, mPid, mAppThread, true, null); } } }接着便会调用appDiedLocked方法处理进程死亡//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread, boolean fromBinderDied, String reason) { // First check if this ProcessRecord is actually active for the pid. //检查pid所属ProcessRecord是否与传入ProcessRecord相符 synchronized (mPidsSelfLocked) { ProcessRecord curProc = mPidsSelfLocked.get(pid); if (curProc != app) { return; } } ... //记录电池统计信息 //如果App进程尚未死亡的话,杀死进程 if (!app.killed) { if (!fromBinderDied) { killProcessQuiet(pid); mProcessList.noteAppKill(app, ApplicationExitInfo.REASON_OTHER, ApplicationExitInfo.SUBREASON_UNKNOWN, reason); } ProcessList.killProcessGroup(app.uid, pid); app.killed = true; } // Clean up already done if the process has been re-started. if (app.pid == pid && app.thread != null && app.thread.asBinder() == thread.asBinder()) { //一般情况下非自动化测试,先置为true boolean doLowMem = app.getActiveInstrumentation() == null; boolean doOomAdj = doLowMem; if (!app.killedByAm) { //不通过AMS杀死的进程,一般就是被 Low Memory Killer (LMK) 杀死的 ... //报告信息 //被LMK杀死,说明系统内存不足 mAllowLowerMemLevel = true; } else { //通过AMS杀死的进程 // Note that we always want to do oom adj to update our state with the // new number of procs. mAllowLowerMemLevel = false; //正常情况下非内存不足 doLowMem = false; } ... //事件记录 //继续处理App进程死亡 handleAppDiedLocked(app, false, true); //调整进程优先级 if (doOomAdj) { updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END); } //当因为内存不足而杀死App进程时 //调用App层各处的的onLowMemory方法,释放内存 if (doLowMem) { doLowMemReportIfNeededLocked(app); } } else if (app.pid != pid) { //新进程已启动 // A new process has already been started. ... //报告记录信息 } ... }这里的其他代码我们都不用关心,直接看handleAppDiedLocked方法继续处理App进程死亡//frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { ... //清理进程的主要方法 boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, false /*replacingPid*/); ... } final boolean cleanUpApplicationRecordLocked(ProcessRecord app, boolean restarting, boolean allowRestart, int index, boolean replacingPid) { ... mServices.killServicesLocked(app, allowRestart); ... }可以看到,这里调用了ActiveServices.killServicesLocked方法停止还在运行中的服务final void killServicesLocked(ProcessRecord app, boolean allowRestart) { // Clean up any connections this application has to other services. //清理所有连接 for (int i = app.connections.size() - 1; i >= 0; i--) { ConnectionRecord r = app.connections.valueAt(i); removeConnectionLocked(r, app, null); } updateServiceConnectionActivitiesLocked(app); app.connections.clear(); app.whitelistManager = false; // Clear app state from services. //遍历所有正在运行中的服务 for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) { ServiceRecord sr = app.getRunningServiceAt(i); synchronized (sr.stats.getBatteryStats()) { sr.stats.stopLaunchedLocked(); } if (sr.app != app && sr.app != null && !sr.app.isPersistent()) { //记录服务已停止 sr.app.stopService(sr); //更新绑定的客户端uids sr.app.updateBoundClientUids(); } sr.setProcess(null); sr.isolatedProc = null; sr.executeNesting = 0; sr.forceClearTracker(); if (mDestroyingServices.remove(sr)) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr); } final int numClients = sr.bindings.size(); for (int bindingi=numClients-1; bindingi>=0; bindingi--) { IntentBindRecord b = sr.bindings.valueAt(bindingi); //释放对服务Binder的引用 b.binder = null; //重置 b.requested = b.received = b.hasBound = false; // If this binding is coming from a cached process and is asking to keep // the service created, then we'll kill the cached process as well -- we // don't want to be thrashing around restarting processes that are only // there to be cached. ... //遍历客户端进程(实际上没做任何事) } } ServiceMap smap = getServiceMapLocked(app.userId); // Now do remaining service cleanup. for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) { ServiceRecord sr = app.getRunningServiceAt(i); // Unless the process is persistent, this process record is going away, // so make sure the service is cleaned out of it. //非持久化进程 if (!app.isPersistent()) { //记录服务已停止 app.stopService(sr); //更新绑定的客户端uids app.updateBoundClientUids(); } // Sanity check: if the service listed for the app is not one // we actually are maintaining, just let it drop. //一致性检查 final ServiceRecord curRec = smap.mServicesByInstanceName.get(sr.instanceName); if (curRec != sr) { if (curRec != null) { Slog.wtf(TAG, "Service " + sr + " in process " + app + " not same as in map: " + curRec); } continue; } // Any services running in the application may need to be placed // back in the pending list. //允许重启,但Service崩溃的次数超出重试上限(默认为16),并且它不是系统应用 if (allowRestart && sr.crashCount >= mAm.mConstants.BOUND_SERVICE_MAX_CRASH_RETRY && (sr.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { ... //记录 //停止服务 bringDownServiceLocked(sr); } else if (!allowRestart || !mAm.mUserController.isUserRunning(sr.userId, 0)) { //不允许重启或者服务进程所在用户不在运行,停止服务 bringDownServiceLocked(sr); } else { //尝试调度重启服务 final boolean scheduled = scheduleServiceRestartLocked(sr, true /* allowCancel */); // Should the service remain running? Note that in the // extreme case of so many attempts to deliver a command // that it failed we also will stop it here. if (!scheduled) { //未调度重启 //停止服务 bringDownServiceLocked(sr); } else if (sr.canStopIfKilled(false /* isStartCanceled */)) { // Update to stopped state because the explicit start is gone. The service is // scheduled to restart for other reason (e.g. connections) so we don't bring // down it. //将服务的启动状态更新为停止 sr.startRequested = false; ... //记录 } } } //不允许重启的话 if (!allowRestart) { //停止所有服务 app.stopAllServices(); //清理绑定的客户端uids app.clearBoundClientUids(); // Make sure there are no more restarting services for this process. //确保这个进程不再会重启服务,清理所有待重启待启动的服务 for (int i=mRestartingServices.size()-1; i>=0; i--) { ServiceRecord r = mRestartingServices.get(i); if (r.processName.equals(app.processName) && r.serviceInfo.applicationInfo.uid == app.info.uid) { mRestartingServices.remove(i); clearRestartingIfNeededLocked(r); } } for (int i=mPendingServices.size()-1; i>=0; i--) { ServiceRecord r = mPendingServices.get(i); if (r.processName.equals(app.processName) && r.serviceInfo.applicationInfo.uid == app.info.uid) { mPendingServices.remove(i); } } } // Make sure we have no more records on the stopping list. //清理所有停止中的服务 int i = mDestroyingServices.size(); while (i > 0) { i--; ServiceRecord sr = mDestroyingServices.get(i); if (sr.app == app) { sr.forceClearTracker(); mDestroyingServices.remove(i); } } //清理所有执行中的服务 //这里的执行中指的是有事务正在运行,比如说正在停止过程中,不是指运行中 app.executingServices.clear(); }这里做了各种清理工作,客户端进程的清理呀,服务端进程的清理,然后就是Service重启的核心,scheduleServiceRestartLocked方法//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) { //系统正在关机,直接返回 if (mAm.mAtmInternal.isShuttingDown()) { return false; } //一致性检查 ServiceMap smap = getServiceMapLocked(r.userId); if (smap.mServicesByInstanceName.get(r.instanceName) != r) { ServiceRecord cur = smap.mServicesByInstanceName.get(r.instanceName); Slog.wtf(TAG, "Attempting to schedule restart of " + r + " when found in map: " + cur); return false; } final long now = SystemClock.uptimeMillis(); final String reason; if ((r.serviceInfo.applicationInfo.flags &ApplicationInfo.FLAG_PERSISTENT) == 0) { //对于非系统应用 //服务至少要过多长时间才能重启,默认1000ms long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION; //服务被杀死重启后需要运行多长时间,默认60s long resetTime = mAm.mConstants.SERVICE_RESET_RUN_DURATION; boolean canceled = false; // Any delivered but not yet finished starts should be put back // on the pending list. //对应着返回值为START_REDELIVER_INTENT的情况 final int N = r.deliveredStarts.size(); if (N > 0) { for (int i=N-1; i>=0; i--) { ServiceRecord.StartItem si = r.deliveredStarts.get(i); si.removeUriPermissionsLocked(); if (si.intent == null) { // We'll generate this again if needed. } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) { //如果该启动项的失败次数小于最大容忍次数 //MAX_DELIVERY_COUNT默认为3 //MAX_DONE_EXECUTING_COUNT默认为6 r.pendingStarts.add(0, si); //这种情况下延时是现在距离启动时间的两倍 long dur = SystemClock.uptimeMillis() - si.deliveredTime; dur *= 2; if (minDuration < dur) minDuration = dur; if (resetTime < dur) resetTime = dur; } else { //如果该启动项的失败次数大于等于最大容忍次数 canceled = true; } } r.deliveredStarts.clear(); } if (allowCancel) { //判断是否应该停止(只考虑非绑定启动的情况) final boolean shouldStop = r.canStopIfKilled(canceled); if (shouldStop && !r.hasAutoCreateConnections()) { // Nothing to restart. //如果应该停止,直接返回 return false; } reason = (r.startRequested && !shouldStop) ? "start-requested" : "connection"; } else { reason = "always"; } r.totalRestartCount++; if (r.restartDelay == 0) { //第一次重启的情况 r.restartCount++; r.restartDelay = minDuration; } else if (r.crashCount > 1) { //Service所在进程在Service运行过程中发生崩溃导致重启的话 //重启延时为 30min * (崩溃次数 - 1) r.restartDelay = mAm.mConstants.BOUND_SERVICE_CRASH_RESTART_DURATION * (r.crashCount - 1); } else { //非第一次重启的情况 // If it has been a "reasonably long time" since the service // was started, then reset our restart duration back to // the beginning, so we don't infinitely increase the duration // on a service that just occasionally gets killed (which is // a normal case, due to process being killed to reclaim memory). if (now > (r.restartTime+resetTime)) { //如果服务重启后运行达到了一定时间,则重启延时为 r.restartCount = 1; r.restartDelay = minDuration; } else { //如果服务重启后运行没有达到一定时间(短时间内又要重启) //则增长重启延时,默认因子为4 r.restartDelay *= mAm.mConstants.SERVICE_RESTART_DURATION_FACTOR; if (r.restartDelay < minDuration) { r.restartDelay = minDuration; } } } //确定重启时间 r.nextRestartTime = now + r.restartDelay; // Make sure that we don't end up restarting a bunch of services // all at the same time. //确保不会在同一时间启动大量服务 boolean repeat; do { repeat = false; final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; for (int i=mRestartingServices.size()-1; i>=0; i--) { ServiceRecord r2 = mRestartingServices.get(i); if (r2 != r && r.nextRestartTime >= (r2.nextRestartTime-restartTimeBetween) && r.nextRestartTime < (r2.nextRestartTime+restartTimeBetween)) { r.nextRestartTime = r2.nextRestartTime + restartTimeBetween; r.restartDelay = r.nextRestartTime - now; repeat = true; break; } } } while (repeat); } else { //对于系统进程,立马重启 // Persistent processes are immediately restarted, so there is no // reason to hold of on restarting their services. r.totalRestartCount++; r.restartCount = 0; r.restartDelay = 0; r.nextRestartTime = now; reason = "persistent"; } //添加到重启列表中 if (!mRestartingServices.contains(r)) { r.createdFromFg = false; mRestartingServices.add(r); r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now); } //取消前台服务通知 cancelForegroundNotificationLocked(r); //通过Handler调度重启 mAm.mHandler.removeCallbacks(r.restarter); mAm.mHandler.postAtTime(r.restarter, r.nextRestartTime); r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; ... //事件记录 return true; }这个方法主要做了几件事情,一是判断服务需不需要重启,二是计算服务的下次重启时间,最后通过Handler执行延时重启还记得我们前面说的当返回值为START_REDELIVER_INTENT时,不会从ServiceRecord.deliveredStarts中删除启动项吗?这里就体现出了这一点,遍历整个deliveredStarts列表,从中找出符合重启条件的启动项,将其加入到pendingStarts列表中,需要注意的是,在这种情况下,重启延时为现在距离启动时间的两倍,所以一般情况下START_REDELIVER_INTENT比START_STICKY重启的要更慢接下来便要判断服务需不需要重启,这里调用了ServiceRecord.canStopIfKilled方法 //frameworks/base/services/core/java/com/android/server/am/ServiceRecord.java boolean canStopIfKilled(boolean isStartCanceled) { return startRequested && (stopIfKilled || isStartCanceled) && pendingStarts.isEmpty(); }之前说过,如果返回值为START_STICKY或START_STICKY_COMPATIBILITY,那这里的stopIfKilled就为false,所以整体会返回false,而对于返回值START_REDELIVER_INTENT而言,之前已经进行过操作,将启动项添加到pendingStarts列表中了,所以只要这里为false,整体就为false,stopIfKilled的值就不重要了最后就是通过Handler执行延时重启了,这里Handler传入的Runnable是ServiceRecord.restarter,它是在服务启动,调用retrieveServiceLocked方法时被创建的 //frameworks/base/services/core/java/com/android/server/am/ActiveServices.java private class ServiceRestarter implements Runnable { private ServiceRecord mService; void setService(ServiceRecord service) { mService = service; } public void run() { synchronized(mAm) { performServiceRestartLocked(mService); } } }可以看到,在一定的延时后,会调用到performServiceRestartLocked方法重启服务//frameworks/base/services/core/java/com/android/server/am/ActiveServices.java final void performServiceRestartLocked(ServiceRecord r) { if (!mRestartingServices.contains(r)) { return; } if (!isServiceNeededLocked(r, false, false)) { // Paranoia: is this service actually needed? In theory a service that is not // needed should never remain on the restart list. In practice... well, there // have been bugs where this happens, and bad things happen because the process // ends up just being cached, so quickly killed, then restarted again and again. // Let's not let that happen. Slog.wtf(TAG, "Restarting service that is not needed: " + r); return; } try { //参考上一篇文章,Service启动流程 bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true, false); } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } }最终调用了bringUpServiceLocked方法启动服务,这一部分可以看上一篇文章 Android源码分析 - Service启动流程 中的分析,还记得上一篇文章中分析的realStartServiceLocked方法中,有一个逻辑是:如果Service已经启动,并且没有启动项,则构建一个假的启动参数供onStartCommand使用 吗?之前看到这个逻辑的时候我还有些疑惑为什么需要这样,现在就豁然开朗了,原来这是为Service重启做的逻辑,而对于返回值START_REDELIVER_INTENT而言,pendingStarts列表本身就不为空,直接正常执行启动任务就可以了

0
0
0
浏览量1337
chole

Android源码分析 - Zygote进程

开篇本篇以android-11.0.0_r25作为基础解析上一篇文章Android源码分析 - init进程,我们分析了Android第一个用户进程init进程的启动过程和之后的守护服务init进程启动了很多服务,例如Zygote,ServiceManager,MediaServer,SurfaceFlinger等,我们平常写Android应用都是使用Java语言,这次我们就先从Java世界的半边天:Zygote进程 开始分析介绍Zygote意为受精卵,它有两大作用,一是启动SystemServer,二是孵化启动App启动服务我们已经知道了init进程会从init.rc文件中解析并启动服务,那zygote是在哪定义的呢,init.rc的头几行就有一个import:import /system/etc/init/hw/init.${ro.zygote}.rc我们在init.rc同目录下就能找到几个对应的文件:init.zygote32_64.rc init.zygote32.rc init.zygote64_32.rc init.zygote64.rc,具体import哪个文件与具体设备硬件有关,现在64位手机这么普及了,我们就以init.zygote64.rc为目标分析 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system socket usap_pool_primary stream 660 root system onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond writepid /dev/cpuset/foreground/tasks下面的子项我们暂时不用关心,先记住app_process64的启动参数-Xzygote /system/bin --zygote --start-system-server即可Zygote启动的源文件为frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { ... //创建了一个AppRuntime,继承自AndroidRuntime,重写了一些回调方法 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] //在启动服务时,传进来的参数是包含文件路径的 //我们不需要这个参数,就减一下个数,移一下指针 argc--; argv++; ... //处理参数,这里只添加了一个-Xzygote参数 int i; for (i = 0; i < argc; i++) { ... if (argv[i][0] != '-') { break; } if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --. break; } runtime.addOption(strdup(argv[i])); ... } // Parse runtime arguments. Stop at first unrecognized option. bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className; //跳过参数/system/bin,这个参数目前没有被使用 ++i; // Skip unused "parent dir" argument. while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { //有--zygote参数 zygote = true; //ZYGOTE_NICE_NAME在64位下为zygote64,32位下为zygote niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) { //有-start-system-server参数 startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) { className.setTo(arg); break; } else { --i; break; } } Vector<String8> args; if (!className.isEmpty()) { //这个分支不会进入Zygote模式 ... } else { // We're in zygote mode. //新建Dalvik缓存目录 maybeCreateDalvikCache(); //添加启动参数 if (startSystemServer) { args.add(String8("start-system-server")); } char prop[PROP_VALUE_MAX]; if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY); return 11; } String8 abiFlag("--abi-list="); abiFlag.append(prop); args.add(abiFlag); // In zygote mode, pass all remaining arguments to the zygote // main() method. //Zygote模式下没有其他参数了 for (; i < argc; ++i) { args.add(String8(argv[i])); } } if (!niceName.isEmpty()) { //设置程序名以及进程名 runtime.setArgv0(niceName.string(), true /* setProcName */); } if (zygote) { //执行AndroidRuntime::start方法 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); } }整体结构还是比较简单的,就是处理一下参数,进入zygote对应的分支,执行AndroidRuntime::start方法,第一个参数传的是ZygoteInit在Java中的类名,第二个参数传了一些选项(start-system-server和abi-list),第三个参数传了true,代表启动虚拟机的时候需要额外添加一些JVM参数AndroidRuntime::startvoid AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... static const String8 startSystemServer("start-system-server"); // Whether this is the primary zygote, meaning the zygote which will fork system server. //64_32位兼容设备上会启动两个Zygote,一个叫zygote,一个叫zygote_secondary bool primary_zygote = false; //有start-system-server选项则代表是主Zygote for (size_t i = 0; i < options.size(); ++i) { if (options[i] == startSystemServer) { primary_zygote = true; /* track our progress through the boot sequence */ const int LOG_BOOT_PROGRESS_START = 3000; LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); } } //检查和配置一些环境变量 ... /* start the virtual machine */ //加载libart.so JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; //启动JVM if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } //回调AppRuntime中重写的方法 onVmCreated(env); /* * Register android functions. */ //注册Android JNI函数 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } //创建一个Java层的String数组用来装参数 jclass stringClass; jobjectArray strArray; jstring classNameStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); assert(strArray != NULL); //第一个参数是类名com.android.internal.os.ZygoteInit classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); //剩下来参数分别是start-system-server和abi-list for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); } /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ //将Java类名中的"."替换成"/",这是JNI中的类名规则 char* slashClassName = toSlashClassName(className != NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { //获取ZygoteInit中的main方法,参数为String类型,返回值为void jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { //执行ZygoteInit的main方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); //后面的代码除非JVM挂了,否则不会执行 ... } } ... }首先判断选项中是否携带参数start-system-server,如有,则将它视为主Zygote,接着就开始启动JVM了启动JVMJniInvocation使用JniInvocation初始化Android ART虚拟机环境,它的路径是libnativehelper/include_platform/nativehelper/JniInvocation.h,我们来看一下它是怎么做的我们首先看一下它的构造函数 /* libnativehelper/include_platform/nativehelper/JniInvocation.h */ class JniInvocation final { public: JniInvocation() { impl_ = JniInvocationCreate(); } ~JniInvocation() { JniInvocationDestroy(impl_); } ... }调用JniInvocationCreate方法创建了一个JniInvocationImpl实例对象JniInvocationImpl* JniInvocationCreate() { return new JniInvocationImpl(); }接着调用JniInvocation::Init方法bool Init(const char* library) { return JniInvocationInit(impl_, library) != 0; } int JniInvocationInit(JniInvocationImpl* instance, const char* library) { return instance->Init(library) ? 1 : 0; }可以看到,JniInvocation实际上是个代理类,内部实现是交给JniInvocationImpl的,路径为libnativehelper/JniInvocation.cppbool JniInvocationImpl::Init(const char* library) { ... //非debug一律为libart.so library = GetLibrary(library, buffer); //加载libart.so库 handle_ = OpenLibrary(library); if (handle_ == NULL) { //如果是加载libart.so库失败,直接返回false if (strcmp(library, kLibraryFallback) == 0) { // Nothing else to try. ALOGE("Failed to dlopen %s: %s", library, GetError().c_str()); return false; } ... //如果是加载其他库失败,尝试回退加载libart.so库 library = kLibraryFallback; handle_ = OpenLibrary(library); if (handle_ == NULL) { ALOGE("Failed to dlopen %s: %s", library, GetError().c_str()); return false; } } //从libart.so库获得三个JVM相关的函数地址 if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetDefaultJavaVMInitArgs_), "JNI_GetDefaultJavaVMInitArgs")) { return false; } if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_CreateJavaVM_), "JNI_CreateJavaVM")) { return false; } if (!FindSymbol(reinterpret_cast<FUNC_POINTER*>(&JNI_GetCreatedJavaVMs_), "JNI_GetCreatedJavaVMs")) { return false; } return true; }加载libart.so库我们先看GetLibrary方法static const char* kLibraryFallback = "libart.so"; const char* JniInvocationImpl::GetLibrary(const char* library, char* buffer, bool (*is_debuggable)(), int (*get_library_system_property)(char* buffer)) { #ifdef __ANDROID__ const char* default_library; if (!is_debuggable()) { library = kLibraryFallback; default_library = kLibraryFallback; } else { ... } #else ... const char* default_library = kLibraryFallback; #endif if (library == NULL) { library = default_library; } return library; }可以看到,在debug模式或library参数为NULL的情况下都是直接返回的libart.so而OpenLibrary方法是使用了dlopen函数,加载libart.so库void* OpenLibrary(const char* filename) { ... const int kDlopenFlags = RTLD_NOW | RTLD_NODELETE; return dlopen(filename, kDlopenFlags); ... }dlopen原型:void *dlopen(const char *filename, int flags); 文档:man7.org/linux/man-p…这是一个Linux函数,用来加载一个动态链接库,当加载成功时,会返回一个句柄上面的这两个参数,RTLD_NOW代表立即计算库的依赖性,RTLD_NODELETE代表不要再dlclose期间卸载库,这样当再次加载库的时候不会重新初始化对象的静态全局变量,使用这个flag是为了确保libart.so在关闭时不会被取消映射。因为即使在 JNI_DeleteJavaVM 调用之后,某些线程仍可能尚未完成退出,如果卸载该库,则可能导致段错误从libart.so库中寻找函数地址接着调用FindSymbol函数查找函数地址#define FUNC_POINTER void* bool JniInvocationImpl::FindSymbol(FUNC_POINTER* pointer, const char* symbol) { //获得函数地址 *pointer = GetSymbol(handle_, symbol); //获取失败,卸载libart.so库 if (*pointer == NULL) { ALOGE("Failed to find symbol %s: %s\n", symbol, GetError().c_str()); CloseLibrary(handle_); handle_ = NULL; return false; } return true; } FUNC_POINTER GetSymbol(void* handle, const char* symbol) { ... return dlsym(handle, symbol); ... }dlsym原型:void *dlsym(void *restrict handle , const char *restrict symbol); 文档:man7.org/linux/man-p…也是一个Linux函数,用来从已加载的动态链接库中获取一个函数的地址传入的第一个参数为之前加载库时返回的句柄,第二个参数为函数名总结回顾一下全局,JniInvocationImpl::Init的作用是,加载libart.so库,并从中获取三个函数指针:JNI_GetDefaultJavaVMInitArgs:获取虚拟机的默认初始化参数JNI_CreateJavaVM:创建虚拟机实例JNI_GetCreatedJavaVMs:获取创建的虚拟机实例这几个函数被定义在jni.h中,后面我们创建JVM的时候会用到这些函数AndroidRuntime::startVmint AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote) { JavaVMInitArgs initArgs; ... //配置了一大堆JVM选项 initArgs.version = JNI_VERSION_1_4; initArgs.options = mOptions.editArray(); initArgs.nOptions = mOptions.size(); initArgs.ignoreUnrecognized = JNI_FALSE; //创建并初始化JVM if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); return -1; } return 0; }JNI_CreateJavaVM方法就是我们之前从libart.so里获得的方法,被编译进libart.so前,源码的路径为art/runtime/jni/java_vm_ext.cc,接下来属于ART虚拟机的工作,我们就不再往下深究了后面有一个onVmCreated回调,但在zygote模式下没做任何事注册JNI函数接着调用startReg函数注册Android JNI函数/* * Register android native functions with the VM. */ /*static*/ int AndroidRuntime::startReg(JNIEnv* env) { ... //设置Native创建线程的函数,通过javaCreateThreadEtc这个函数创建的线程 //会把创建的线程attach到JVM中,使其既能执行c/c++代码,也能执行Java代码 androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); ALOGV("--- registering native functions ---\n"); //创建局部引用栈帧 env->PushLocalFrame(200); //注册jni函数 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } //将当前栈帧出栈,释放其中所有局部引用 env->PopLocalFrame(NULL); return 0; } 首先hook了Native创建线程的函数,之后创建线程便会调用我们设置的javaCreateThreadEtc函数,会把创建的线程attach到JVM中,使其既能执行c/c++代码,也能执行Java代码。这个等之后看到Android线程创建的时候再分析PushLocalFrame和PopLocalFrame是一对函数,它们是用来管理JNI的局部引用的首先,PushLocalFrame会创建出一个局部引用栈帧,之后JNI创建出来的局部引用都会放在这个栈帧里,等使用结束后调用PopLocalFrame函数,会将当前栈帧出栈,并且释放其中所有的局部引用接下来我们看register_jni_procs函数 struct RegJNIRec { int (*mProc)(JNIEnv*); }; static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { for (size_t i = 0; i < count; i++) { if (array[i].mProc(env) < 0) { ... return -1; } } return 0; }很简单,就是循环执行gRegJNI数组中所有的函数#define REG_JNI(name) { name } static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), ... };gRegJNI数组中存放着很多Java类注册JNI函数的函数,后面大家如果阅读源码看到了Android中的native方法可以来这边找它所对应的c++实现这边注册的类非常多,我们就取第一个register_com_android_internal_os_RuntimeInit为例分析一下 typedef struct { const char* name; const char* signature; void* fnPtr; } JNINativeMethod; int register_com_android_internal_os_RuntimeInit(JNIEnv* env) { const JNINativeMethod methods[] = { {"nativeFinishInit", "()V", (void*)com_android_internal_os_RuntimeInit_nativeFinishInit}, {"nativeSetExitWithoutCleanup", "(Z)V", (void*)com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup}, }; return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit", methods, NELEM(methods)); }创建了一个JNINativeMethod结构体,第一个成员是Java中的方法名,第二个成员是Java中对应方法的签名,第三个成员是Java方法对应native函数的函数指针,然后调用jniRegisterNativeMethods函数int jniRegisterNativeMethods(C_JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { JNIEnv* e = reinterpret_cast<JNIEnv*>(env); ALOGV("Registering %s's %d native methods...", className, numMethods); scoped_local_ref<jclass> c(env, findClass(env, className)); ALOG_ALWAYS_FATAL_IF(c.get() == NULL, "Native registration unable to find class '%s'; aborting...", className); int result = e->RegisterNatives(c.get(), gMethods, numMethods); ALOG_ALWAYS_FATAL_IF(result < 0, "RegisterNatives failed for '%s'; aborting...", className); return 0; }这个函数先通过Java类名获得一个jclass对象,接着调用JNIEnv::RegisterNatives函数,这个函数定义在jni.h中,实现在libart.so库中,我们在平时开发jni的时候,动态注册native方法的时候就会使用到它,这里就不再往下分析了进入JAVA世界JVM启动好了,JNI函数也注册完毕了,接下来就该进入到JAVA世界了void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... //创建一个Java层的String数组用来装参数 jclass stringClass; jobjectArray strArray; jstring classNameStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); assert(strArray != NULL); //第一个参数是类名com.android.internal.os.ZygoteInit classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); //剩下来参数分别是start-system-server和abi-list for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); } /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ //将Java类名中的"."替换成"/",这是JNI中的类名规则 char* slashClassName = toSlashClassName(className != NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { //获取ZygoteInit中的main方法,参数为String类型,返回值为void jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { //执行ZygoteInit的main方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); //后面的代码除非JVM挂了,否则不会执行 ... } } ... }这里看不懂的自己先补一下JNI知识,总之就是调用了com.android.internal.os.ZygoteInit类的静态方法main,以com.android.internal.os.ZygoteInit,start-system-server和abi-list作为参数ZygoteInitZygoteInit类的源码路径为frameworks/base/core/java/com/android/internal/os/ZygoteInit.java我们这就开始分析它的main方法public static void main(String argv[]) { ZygoteServer zygoteServer = null; // Mark zygote start. This ensures that thread creation will throw // an error. //标记着zygote开始启动,不允许创建线程(Zygote必须保证单线程) ZygoteHooks.startZygoteNoThreadCreation(); // Zygote goes into its own process group. //设置进程组id try { Os.setpgid(0, 0); } catch (ErrnoException ex) { throw new RuntimeException("Failed to setpgid(0,0)", ex); } Runnable caller; try { ... //配置参数 boolean startSystemServer = false; String zygoteSocketName = "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)) { zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } //public static final String PRIMARY_SOCKET_NAME = "zygote"; final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); ... if (!enableLazyPreload) { ... //预加载 preload(bootTimingsTraceLog); ... } ... //调用Java层的垃圾回收 gcAndFinalize(); ... //回调AppRRuntime中的onZygoteInit函数 Zygote.initNativeState(isPrimaryZygote); //解除创建线程限制(马上就要执行fork了,子进程要有能力创建线程) ZygoteHooks.stopZygoteNoThreadCreation(); //创建socket zygoteServer = new ZygoteServer(isPrimaryZygote); //启动SystemServer if (startSystemServer) { Runnable r = forkSystemServer(abiList, zygoteSocketName, 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; } } 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. //执行死循环监听socket,负责接收事件,启动App caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { if (zygoteServer != null) { zygoteServer.closeServerSocket(); } } // We're in the child process and have exited the select loop. Proceed to execute the // command. //接收到AMS的启动App请求后,fork出子进程,处理App启动 if (caller != null) { caller.run(); } }先调用ZygoteHooks.startZygoteNoThreadCreation()禁止创建线程,Zygote必须保证单线程,这和fork机制有关,fork函数只会将当前线程复制到子进程,同时,fork会将锁也复制到子进程中,如果在fork之前,有一个线程持有了锁,但是fork的时候没把这个线程复制到子进程中,这把锁就被永久持有了,会造成死锁android.system.Os我们看一下Os是什么,根据import我们知道它的全限定类名为android.system.Os,它的源码路径为libcore/luni/src/main/java/android/system/Os.java... import libcore.io.Libcore; public final class Os { private Os() {} ... public static void setpgid(int pid, int pgid) throws ErrnoException { Libcore.os.setpgid(pid, pgid); } ... } 它里面全是这种形式的静态代理方法,实际调用Libcore.os执行,我们就以setpgid方法去追踪一下Libcore位于libcore/luni/src/main/java/libcore/io/Libcore.java,os是其中的一个静态变量public final class Libcore { private Libcore() { } /** * Direct access to syscalls. Code should strongly prefer using {@link #os} * unless it has a strong reason to bypass the helpful checks/guards that it * provides. */ public static final Os rawOs = new Linux(); /** * Access to syscalls with helpful checks/guards. * For read access only; the only supported way to update this field is via * {@link #compareAndSetOs}. */ @UnsupportedAppUsage public static volatile Os os = new BlockGuardOs(rawOs); public static Os getOs() { return os; } ... }os的类型为BlockGuardOs,以Linux类型的常量rawOs作为构造方法参数实例化,它继承自ForwardingOspublic class ForwardingOs implements Os { @UnsupportedAppUsage private final Os os; @UnsupportedAppUsage @libcore.api.CorePlatformApi protected ForwardingOs(Os os) { this.os = Objects.requireNonNull(os); } ... public void setpgid(int pid, int pgid) throws ErrnoException { os.setpgid(pid, pgid); } ... }可以看到,这其实又是一个代理类,实际上是直接调用了Linux类的方法,至于BlockGuardOs,它在部分方法上做了一些回调监听,除此之外也是直接调用了Linux类的方法public final class Linux implements Os { Linux() { } ... public native int getpgid(int pid); ... }里面基本上都是JNI调用native方法,对应的c++源码路径为libcore/luni/src/main/native/libcore_io_Linux.cpp,下面是注册JNI函数的函数#define NATIVE_METHOD(className, functionName, signature) \ MAKE_JNI_NATIVE_METHOD(#functionName, signature, className ## _ ## functionName) #define MAKE_JNI_NATIVE_METHOD(name, signature, function) \ _NATIVEHELPER_JNI_MAKE_METHOD(kNormalNative, name, signature, function) #define _NATIVEHELPER_JNI_MAKE_METHOD(kind, name, sig, fn) \ MAKE_CHECKED_JNI_NATIVE_METHOD(kind, name, sig, fn) #define MAKE_CHECKED_JNI_NATIVE_METHOD(native_kind, name_, signature_, fn) \ ([]() { \ using namespace nativehelper::detail; /* NOLINT(google-build-using-namespace) */ \ static_assert( \ MatchJniDescriptorWithFunctionType<native_kind, \ decltype(fn), \ fn, \ sizeof(signature_)>(signature_),\ "JNI signature doesn't match C++ function type."); \ /* Suppress implicit cast warnings by explicitly casting. */ \ return JNINativeMethod { \ const_cast<decltype(JNINativeMethod::name)>(name_), \ const_cast<decltype(JNINativeMethod::signature)>(signature_), \ reinterpret_cast<void*>(&(fn))}; \ })() static JNINativeMethod gMethods[] = { ... NATIVE_METHOD(Linux, setpgid, "(II)V"), ... }; void register_libcore_io_Linux(JNIEnv* env) { ... jniRegisterNativeMethods(env, "libcore/io/Linux", gMethods, NELEM(gMethods)); }可以看到,Java层方法对应native方法的格式为Linux_方法名,我们通过这种规则找到setpgid方法对应的函数static void Linux_setpgid(JNIEnv* env, jobject, jint pid, int pgid) { throwIfMinusOne(env, "setpgid", TEMP_FAILURE_RETRY(setpgid(pid, pgid))); }可以看到是直接调用了Linux系统层函数总结综上所述,android.system.Os类存在的意义是可以使Java层能够方便的调用Linux系统方法预加载接下来就是一些参数配置工作,然后调用preload预加载static void preload(TimingsTraceLog bootTimingsTraceLog) { ... //预加载Java类 preloadClasses(); ... //加载三个jar文件 /* /system/framework/android.hidl.base-V1.0-java.jar */ /* /system/framework/android.hidl.manager-V1.0-java.jar */ /* /system/framework/android.test.base.jar */ cacheNonBootClasspathClassLoaders(); ... //预加载系统资源 preloadResources(); ... //预加载硬件抽象层? nativePreloadAppProcessHALs(); ... //预加载opengl maybePreloadGraphicsDriver(); ... //预加载动态库 preloadSharedLibraries(); //TextView预加载Font preloadTextResources(); //预加载webviewchromium WebViewFactory.prepareWebViewInZygote(); ... }preloadClasses我们看看Java类的预加载private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes"; 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; } ... try { BufferedReader br = new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE); int count = 0; String line; while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } ... //Java类加载器加载类 Class.forName(line, true, null); count++; ... } Log.i(TAG, "...preloaded " + count + " classes in " + (SystemClock.uptimeMillis() - startTime) + "ms."); } catch (IOException e) { Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); } finally { ... } }主要的代码就是从/system/etc/preloaded-classes这个文件中读取出需要预加载的类,再通过Class.forName使用类加载器加载一遍,编译前的路径为frameworks/base/config/preloaded-classes为什么需要预加载Zygote进程的一大作用就是孵化App,那是怎么孵化的呢?这过程中肯定要使用到fork,我们知道,fork后,父子进程是可以共享资源的,既然我们每启动一个App,都需要使用虚拟机、加载一些View等必要的类等等,那为何不在父进程中加载好这些,fork后子进程不就可以直接使用它们了吗?这就是Zygote进程预加载的原因启动binder线程池预加载结束后,会先清理一下Java层的垃圾,然后调用Zygote.initNativeState(isPrimaryZygote)方法,这个方法调用了native方法nativeInitNativeState,这个方法是在AndroidRuntime中注册的,同时也实现在AndroidRuntime中, static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); }我们之前分析过,执行的是AndroidRuntime的子类AppRuntime的onZygoteInit函数virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }通过这个函数启动Binder线程池,至于Binder的细节,我们留到以后再分析启动SystemServerZygote进程孵化的第一个进程便是SystemServer,具体怎么孵化的,孵化后SystemServer又做了什么,留在下一节我们再分析ZygoteServer构造方法我们知道,我们App都是从Zygote孵化而来的,App启动是从ActivityManagerService的startActivity方法开始的,那么AMS是怎么和Zygote通信的呢,答案是通过socket我们先从ZygoteServer的构造方法开始看起 ZygoteServer(boolean isPrimaryZygote) { ... if (isPrimaryZygote) { mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME); ... } else { ... } ... }其中有一些东西是和USAP机制有关的,但在AOSP中默认是关闭的,关于USAP机制我们以后再分析,现在只需要关注mZygoteSocket就可以了,它是通过调用Zygote.createManagedSocketFromInitSocket赋值的static LocalServerSocket createManagedSocketFromInitSocket(String socketName) { int fileDesc; //ANDROID_SOCKET_zygote final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { //获得文件描述符 String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); return new LocalServerSocket(fd); } catch (IOException ex) { throw new RuntimeException( "Error building socket from file descriptor: " + fileDesc, ex); } }很简单,就是从系统属性中获取一个fd,然后实例化LocalServerSocket,路径为frameworks/base/core/java/android/net/LocalServerSocket.javapublic LocalServerSocket(FileDescriptor fd) throws IOException { impl = new LocalSocketImpl(fd); impl.listen(LISTEN_BACKLOG); localAddress = impl.getSockAddress(); }在内部创建了一个LocalSocketImpl,然后调用了listen方法声明开始监听这个fd,内部调用了Linux的listen函数runSelectLoop然后我们来看在ZygoteInit中调用的runSelectLoop方法Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> socketFDs = new ArrayList<>(); ArrayList<ZygoteConnection> peers = new ArrayList<>(); //将server socket fd加到列表头(后面需要判断是否为server socket) socketFDs.add(mZygoteSocket.getFileDescriptor()); peers.add(null); ... while (true) { ... StructPollfd[] pollFDs; ... pollFDs = new StructPollfd[socketFDs.size()]; int pollIndex = 0; for (FileDescriptor socketFD : socketFDs) { pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = socketFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; } ... //上面一大段都与USAP机制有关,这里先不关注 int pollReturnValue; try { //等待文件描述符上的事件 pollReturnValue = Os.poll(pollFDs, pollTimeoutMs); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } if (pollReturnValue == 0) { //没有接收到事件(超时),从循环开头重新开始等待事件 ... } else { ... while (--pollIndex >= 0) { //没有要读取的数据,跳过 if ((pollFDs[pollIndex].revents & POLLIN) == 0) { continue; } if (pollIndex == 0) { //pollIndex == 0说明这个fd是ZygoteServer socket的fd //接受并建立一个socket连接 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); //将client socket fd加入列表 socketFDs.add(newPeer.getFileDescriptor()); } else if (pollIndex < usapPoolEventFDIndex) { //不使用USAP机制的话,pollIndex < usapPoolEventFDIndex条件一定成立 //进入这边说明是client socket try { //内部执行fork,返回一个待执行Runnable用于处理子进程后续任务 ZygoteConnection connection = peers.get(pollIndex); final Runnable command = connection.processOneCommand(this); //fork后,在子进程中会将这个变量设为true if (mIsForkChild) { //子进程中 if (command == null) { throw new IllegalStateException("command == null"); } //return出去,由ZygoteInit执行这个Runnable return command; } else { //父进程中 if (command != null) { throw new IllegalStateException("command != null"); } //读取完了,关闭这个socket,清理列表 if (connection.isClosedByPeer()) { connection.closeSocket(); peers.remove(pollIndex); socketFDs.remove(pollIndex); } } } catch (Exception e) { ... } finally { mIsForkChild = false; } } else { ... //不开启USAP机制不会走到这个分支 } } ... } ... } }创建两个列表,socketFDs和peers的下标是一一对应的,首先将server socket fd添加到列表头,方便后续判断事件是来自client或是server socker,peers列表也要添加一个null作为socketFDs的对应接着就开始执行死循环,Zygote进程永远不会退出这个循环,只有fork出子进程后,子进程会主动returnpoll为了理解后面的内容,我们先要学习一下poll函数poll是Linux中的字符设备驱动中的一个函数,它的作用是等待文件描述符上的某个事件原型:int poll(struct pollfd * fds , nfds_t nfds , int timeout );文档:man7.org/linux/man-p…第一个参数是一个pollfd结构体指针struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ }; fd不用多说,就是文件描述符event代表关注哪些事件,POLLIN代表可读,POLLOUT代表可写等等revents是由内核通知的,函数返回的时候,会设置对应的fd实际发生的事件,比如fd有可读的事件,设置POLLIN第二个参数nfds表示fd的个数,即pollfd数组的size第三个参数表示超时时间返回值:大于0:表示有fd事件产生,值为有产生事件的fd的个数等于0:表示超时小于0:表示有错误产生StructPollfd & pollfd弄懂poll是干嘛的后,我们再来接着看runSelectLoop方法死循环中首先创建了一个StructPollfd数组,它根据socketFDs依次创建出一个个StructPollfd对象,并将他们的事件都设为POLLIN可读StructPollfd和c中的结构体pollfd是对应的,目的是为了方便Java层调用Linux的poll函数StructPollfd的路径为libcore/luni/src/main/java/android/system/StructPollfd.java public final class StructPollfd { public FileDescriptor fd; public short events; public short revents; public Object userData; ... }调用然后调用Os.poll方法关于Os我们上面刚分析过,知道他调用了JNI函数,native函数命名格式为Linux_函数名,我们去libcore/luni/src/main/native/libcore_io_Linux.cpp中找一下static jint Linux_poll(JNIEnv* env, jobject, jobjectArray javaStructs, jint timeoutMs) { ... //把Java对象StructPollfd数组转换成c中的struct pollfd数组 int rc; while (true) { ... rc = poll(fds.get(), count, timeoutMs); if (rc >= 0 || errno != EINTR) { break; } ... } if (rc == -1) { throwErrnoException(env, "poll"); return -1; } ... //设置Java对象StructPollfd的revents值 return rc; }简单看一下,就是把传进去的StructPollfd数组转换成了struct pollfd数组,然后调用Linux poll函数,再把revents写进StructPollfd对象中,最后返回再看回runSelectLoop方法,如果poll执行返回值为-1,会直接引发一个Java异常,其他情况先判断一下poll的返回值,如果为0,则没有事件产生,否则会从后向前依次判断pollFDs的revents,如果为POLLIN可读,则处理,不可读则跳过建立连接我们先看第一次poll到事件的情况,这时候,pollFDs中只有一个zygote socket fd,收到可读事件,说明有客户端socket向zygote socket请求发起连接,这时候我们调用acceptCommandPeer方法建立新连接private ZygoteConnection acceptCommandPeer(String abiList) { try { return createNewConnection(mZygoteSocket.accept(), abiList); } catch (IOException ex) { throw new RuntimeException( "IOException during accept()", ex); } }调用了mZygoteSocket.accept方法public LocalSocket accept() throws IOException { LocalSocketImpl acceptedImpl = new LocalSocketImpl(); impl.accept(acceptedImpl); return LocalSocket.createLocalSocketForAccept(acceptedImpl); }新建了一个LocalSocketImpl(client socket) 实例,然后调用LocalSocketImpl(zygote socket) 的accept方法protected void accept(LocalSocketImpl s) throws IOException { if (fd == null) { throw new IOException("socket not created"); } try { s.fd = Os.accept(fd, null /* address */); s.mFdCreatedInternally = true; } catch (ErrnoException e) { throw e.rethrowAsIOException(); } }调用了Linux的accept函数,接受建立连接,并返回了一个新的client socket fd,将LocalSocketImpl中的fd变量设置为这个fd,接着调用LocalSocket.createLocalSocketForAccept将LocalSocketImpl包装成LocalSocket static LocalSocket createLocalSocketForAccept(LocalSocketImpl impl) { return createConnectedLocalSocket(impl, SOCKET_UNKNOWN); } private static LocalSocket createConnectedLocalSocket(LocalSocketImpl impl, int sockType) { LocalSocket socket = new LocalSocket(impl, sockType); socket.isConnected = true; socket.isBound = true; socket.implCreated = true; return socket; }然后使用这个LocalSocket创建了一个ZygoteConnection包装socket连接protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList) throws IOException { return new ZygoteConnection(socket, abiList); }我们看一下构造方法做了什么ZygoteConnection(LocalSocket socket, String abiList) throws IOException { mSocket = socket; this.abiList = abiList; mSocketOutStream = new DataOutputStream(socket.getOutputStream()); mSocketReader = new BufferedReader( new InputStreamReader(socket.getInputStream()), Zygote.SOCKET_BUFFER_SIZE); ... isEof = false; }打开了client socket的输入输出流,准备读写数据了然后将这个连接和fd分别添加进peers和socketFDs执行client socket命令在第二次循环中pollFDs数组中便包括了新建立连接的client socket了,这时调用Os.poll,可以获得到这个client socket的可读事件,此时调用connection.processOneCommand方法Runnable processOneCommand(ZygoteServer zygoteServer) { String[] args; try { //读取从client socket传来的参数 args = Zygote.readArgumentList(mSocketReader); } catch (IOException ex) { throw new IllegalStateException("IOException on command socket", ex); } ... int pid; FileDescriptor childPipeFd = null; FileDescriptor serverPipeFd = null; //解析参数 ZygoteArguments parsedArgs = new ZygoteArguments(args); ... //一系列参数校验工作 //创建子进程 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.mIsTopApp, parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList, parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs); try { if (pid == 0) { //子进程中 //设置mIsForkChild = true zygoteServer.setForkChild(); //子进程中关闭fork复制来的zygote socket zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote); } else { //父进程中 IoUtils.closeQuietly(childPipeFd); childPipeFd = null; handleParentProc(pid, serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }启动APP进程首先读取从client socket传来的参数,然后校验这些参数,完毕后调用Zygote.forkAndSpecialize方法fork出子进程static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) { //停止其他线程 ZygoteHooks.preFork(); //fork进程 int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp, pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs, bindMountAppStorageDirs); ... //恢复其他线程 ZygoteHooks.postForkCommon(); return pid; }Zygote进程启动了4个线程:HeapTaskDaemonReferenceQueueDaemonFinalizerDaemonFinalizerWatchdogDaemon之前上面也分析过了多线程对fork会产生影响,所以这里先把其他线程停了,等fork完了再重新启动然后执行native函数nativeForkAndSpecialize,路径为frameworks/base/core/jni/com_android_internal_os_Zygote.cpp static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( JNIEnv* env, jclass, jint uid, jint gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, jboolean mount_data_dirs, jboolean mount_storage_dirs) { ... pid_t pid = ForkCommon(env, false, fds_to_close, fds_to_ignore, true); if (pid == 0) { SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list, mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); } return pid; }先调用ForkCommon,再在子进程调用SpecializeCommonstatic pid_t ForkCommon(JNIEnv* env, bool is_system_server, const std::vector<int>& fds_to_close, const std::vector<int>& fds_to_ignore, bool is_priority_fork) { //设置子进程信号处理函数 SetSignalHandlers(); ... //fork前先阻塞SIGCHLD信号 BlockSignal(SIGCHLD, fail_fn); ... //执行fork pid_t pid = fork(); ... //恢复SIGCHLD信号 UnblockSignal(SIGCHLD, fail_fn); return pid; }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, bool is_top_app, jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, bool mount_data_dirs, bool mount_storage_dirs) { const char* process_name = is_system_server ? "system_server" : "zygote"; ... //创建进程组 if (!is_system_server && getuid() == 0) { const int rc = createProcessGroup(uid, getpid()); if (rc == -EROFS) { ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?"); } else if (rc != 0) { ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc)); } } //设置GroupId SetGids(env, gids, is_child_zygote, fail_fn); //设置资源Limit SetRLimits(env, rlimits, fail_fn); ... //设置调度策略 SetSchedulerPolicy(fail_fn, is_top_app); ... //设置线程名 if (nice_name.has_value()) { SetThreadName(nice_name.value()); } else if (is_system_server) { SetThreadName("system_server"); } //子进程中不再处理SIGCHLD信号 UnsetChldSignalHandler(); ... if (is_child_zygote) { initUnsolSocketToSystemServer(); } //调用Zygote.callPostForkChildHooks方法 env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, managed_instruction_set); //设置默认进程优先级 setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT); if (env->ExceptionCheck()) { fail_fn("Error calling post fork hooks."); } }子进程创建完成后,ZygoteConnection在子进程中会返回handleChildProc,在父进程中会返回null在ZygoteServer中做了判断,如果为子进程且command不为null,返回common到ZygoteInit,如果是父进程,继续socket poll循环在ZygoteInit.runSelectLoop后,如果返回值caller(对应ZygoteServer中的command)不为null,则执行这个Runnable我们看一下handleChildProc做了什么 private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor pipeFd, boolean isZygote) { //在子进程中关闭发起启动App请求的client socket closeSocket(); //设置进程名 Zygote.setAppProcessName(parsedArgs, TAG); ... if (parsedArgs.mInvokeWith != null) { //和进程内存泄露或溢出有关? WrapperInit.execApplication(parsedArgs.mInvokeWith, parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.mRemainingArgs); // Should not get here. throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { //根据参数,执行这个方法 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mDisabledCompatChanges, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } } }执行ZygoteInit.zygoteInitpublic static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) { ... //重定向Log RuntimeInit.redirectLogStreams(); //通用初始化 RuntimeInit.commonInit(); //之前有提到,开启binder线程池 ZygoteInit.nativeZygoteInit(); return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv, classLoader); }RuntimeInit的路径为frameworks/base/core/java/com/android/internal/os/RuntimeInit.java,先执行通用初始化protected static final void commonInit() { //设置默认线程异常处理器 LoggingHandler loggingHandler = new LoggingHandler(); RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler); Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); //设置时区 RuntimeHooks.setTimeZoneIdSupplier(() -> SystemProperties.get("persist.sys.timezone")); //重置Log配置 LogManager.getLogManager().reset(); new AndroidConfig(); //设置网络UA信息 String userAgent = getDefaultUserAgent(); System.setProperty("http.agent", userAgent); //初始化网络流量统计 NetworkManagementSocketTagger.install(); ... initialized = true; }然后执行RuntimeInit.applicationInitprotected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges, String[] argv, ClassLoader classLoader) { //如果应用程序调用System.exit(),则立即终止该进程,不运行任何hook函数 nativeSetExitWithoutCleanup(true); //设置虚拟机参数 VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges); //解析参数 final Arguments args = new Arguments(argv); ... //查找startClass中的main方法 return findStaticMain(args.startClass, args.startArgs, classLoader); }这里的startClass为android.app.ActivityThreadprotected 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); }这里使用了Java中的反射,找到了ActivityThread中对应的main方法,并用其创建了一个Runnable对象MethodAndArgsCallerstatic class MethodAndArgsCaller implements Runnable { private final Method mMethod; private final String[] mArgs; public MethodAndArgsCaller(Method method, String[] args) { mMethod = method; mArgs = args; } public void run() { try { //执行ActivityThread.main方法 mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } } }之前说了,在ZygoteInit.runSelectLoop后,如果返回值caller不为null,则执行这个Runnable,即执行MethodAndArgsCaller的run方法,反射调用ActivityThread.main方法结束至此,Zygote进程部分的分析就到此为止了,后面fork出App进程那段讲的很粗糙,后面写到App启动那块的时候,我会重新梳理一遍这里的逻辑,补充上去

0
0
0
浏览量1220
chole

Android源码分析 - Activity启动流程(上)

开篇本篇以android-11.0.0_r25作为基础解析作为一名Android开发,我们最熟悉并且最常打交道的当然非四大组件中的Activity莫属,这次我们就来讲讲一个Activity是怎样启动起来的本来本篇想要讲ActivityManagerService的,但AMS中的内容过多过于繁杂,不如用这种以线及面的方式,通过Activity的启动流程这一条线,去了解ActivityThread,AMS等是怎么工作的Android窗口结构关系在开始正式深入代码之前,我们需要先理一下Android的窗口结构关系,以免后面看到源码里各种parent、child头晕,我画了一张树状关系图来描述它上图中的所有类都是WindowContainer的子类,WindowContainer是一个窗口容器,它的child也是WindowContainer,它是用来管理窗口子容器的可以先不用纠结理解这张图中的关系,顺着源码往下看,碰到不理解的地方回头看一下就可以了startActivity作为Android开发,startActivity这个方法一定非常熟悉,我们以这个函数作为入口来分析Activity的启动流程Activity和ContextImpl的startActivity方法实现不太一样,但最终都调用了Instrumentation.execStartActivity方法Instrumentation路径:frameworks/base/core/java/android/app/Instrumentation.java以下是Google官方对这个类功能的注释Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's <instrumentation> tag.简单翻译一下,就是这个类是用于监控系统与应用的交互的(onCreate等生命周期会经历Instrumentation这么一环),它会在任何App代码执行前被初始化。本人猜测,这个类主要存在的意义是为了给自动化测试提供一个切入点 public ActivityResult execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options) { IApplicationThread whoThread = (IApplicationThread) contextThread; //记录调用者 Uri referrer = target != null ? target.onProvideReferrer() : null; if (referrer != null) { intent.putExtra(Intent.EXTRA_REFERRER, referrer); } ... //自动化测试相关 try { //迁移额外的URI数据流到剪贴板(处理Intent使用ACTION_SEND或ACTION_SEND_MULTIPLE共享数据的情况) intent.migrateExtraStreamToClipData(who); //处理离开当前App进程的情况 intent.prepareToLeaveProcess(who); //请求ATMS启动Activity int result = ActivityTaskManager.getService().startActivity(whoThread, who.getBasePackageName(), who.getAttributionTag(), intent, intent.resolveTypeIfNeeded(who.getContentResolver()), token, target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); //检查异常情况,抛出对应异常 checkStartActivityResult(result, intent); } catch (RemoteException e) { throw new RuntimeException("Failure from system", e); } return null; }这个函数调用了ActivityTaskManager.getService.startActivity方法public static IActivityTaskManager getService() { return IActivityTaskManagerSingleton.get(); } private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton = new Singleton<IActivityTaskManager>() { @Override protected IActivityTaskManager create() { final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE); return IActivityTaskManager.Stub.asInterface(b); } };这里getService出来的很明显的是一个远程binder对象,我们之前已经分析过那么多binder知识了,以后就不再过多啰嗦了,这里实际上调用的是ActivityTaskManagerSerivce(以下简称ATMS)的startActivity方法ActivityTaskManagerSerivceATMS是Android 10以后新加的一个服务,用来专门处理Activity相关工作,分担AMS的工作@Override public final int startActivity(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) { return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, UserHandle.getCallingUserId()); } @Override public int startActivityAsUser(IApplicationThread caller, String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) { return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId, true /*validateIncomingUser*/); } private int startActivityAsUser(IApplicationThread caller, String callingPackage, @Nullable String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) { //断言发起startActivity请求方的UID和callingPackage指向的是同一个App assertPackageMatchesCallingUid(callingPackage); //确认请求方没有被隔离 enforceNotIsolatedCaller("startActivityAsUser"); //检查并获取当前用户ID(多用户模式) userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser"); //使用ActivityStarter启动Activity return getActivityStartController().obtainStarter(intent, "startActivityAsUser") .setCaller(caller) //调用方ApplicationThread .setCallingPackage(callingPackage) //调用方包名 .setCallingFeatureId(callingFeatureId) // Context.getAttributionTag() .setResolvedType(resolvedType) //设置Intent解析类型 .setResultTo(resultTo) //设置目标Activity Token(ContextImpl.startActivity传入参数为null) .setResultWho(resultWho) //设置目标Activity(ContextImpl.startActivity传入参数为null) .setRequestCode(requestCode) //设置requestCode .setStartFlags(startFlags) // startFlags == 0 .setProfilerInfo(profilerInfo) // null .setActivityOptions(bOptions) //设置Activity Options Bundle .setUserId(userId) //设置用户ID .execute(); }这个函数大部分内容都是检查,最重要的是最后一段使用ActivityStarter启动Activity,首先通过ActivityStartController的obtainStarter方法获取一个ActivityStarter实例,然后调用各种set方法设置参数,最后执行execute方法执行ActivityStarter这个类从名字就能看出来,就是一个专门处理Activity启动的类int execute() { try { // Refuse possible leaked file descriptors //校验Intent,不允许其携带fd if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } final LaunchingState launchingState; synchronized (mService.mGlobalLock) { //通过Token获取调用方ActivityRecord final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo); //记录启动状态 launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching( mRequest.intent, caller); } // If the caller hasn't already resolved the activity, we're willing // to do so here. If the caller is already holding the WM lock here, // and we need to check dynamic Uri permissions, then we're forced // to assume those permissions are denied to avoid deadlocking. //通过Intent解析Activity信息 if (mRequest.activityInfo == null) { mRequest.resolveActivity(mSupervisor); } int res; synchronized (mService.mGlobalLock) { ... //处理Configuration //清除Binder调用方UID和PID,用当前进程的UID和PID替代,并返回之前的UID和PID(UID:前32位,PID:后32位) final long origId = Binder.clearCallingIdentity(); //解析成为重量级进程(如果设置了相关flag的话) //这里的重量级进程指的是不能保存状态的应用进程 res = resolveToHeavyWeightSwitcherIfNeeded(); if (res != START_SUCCESS) { return res; } //执行请求 res = executeRequest(mRequest); //恢复之前的Binder调用方UID和PID Binder.restoreCallingIdentity(origId); ... //更新Configuration // Notify ActivityMetricsLogger that the activity has launched. // ActivityMetricsLogger will then wait for the windows to be drawn and populate // WaitResult. //记录启动状态 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res, mLastStartActivityRecord); //返回启动结果 return getExternalResult(mRequest.waitResult == null ? res : waitForResult(res, mLastStartActivityRecord)); } } finally { //清理回收工作 onExecutionComplete(); } }这个函数每一步做了什么我都用注释标出来了,大家看看就好,重点在于其中的executeRequest(mRequest)/** * Executing activity start request and starts the journey of starting an activity. Here * begins with performing several preliminary checks. The normally activity launch flow will * go through {@link #startActivityUnchecked} to {@link #startActivityInner}. */ private int executeRequest(Request request) { if (TextUtils.isEmpty(request.reason)) { throw new IllegalArgumentException("Need to specify a reason."); } mLastStartReason = request.reason; mLastStartActivityTimeMs = System.currentTimeMillis(); mLastStartActivityRecord = null; final IApplicationThread caller = request.caller; Intent intent = request.intent; NeededUriGrants intentGrants = request.intentGrants; String resolvedType = request.resolvedType; ActivityInfo aInfo = request.activityInfo; ResolveInfo rInfo = request.resolveInfo; final IVoiceInteractionSession voiceSession = request.voiceSession; final IBinder resultTo = request.resultTo; String resultWho = request.resultWho; int requestCode = request.requestCode; int callingPid = request.callingPid; int callingUid = request.callingUid; String callingPackage = request.callingPackage; String callingFeatureId = request.callingFeatureId; final int realCallingPid = request.realCallingPid; final int realCallingUid = request.realCallingUid; final int startFlags = request.startFlags; final SafeActivityOptions options = request.activityOptions; Task inTask = request.inTask; int err = ActivityManager.START_SUCCESS; // Pull the optional Ephemeral Installer-only bundle out of the options early. final Bundle verificationBundle = options != null ? options.popAppVerificationBundle() : null; WindowProcessController callerApp = null; if (caller != null) { //获取调用方应用进程对应的WindowProcessController //这个类是用于和ProcessRecord进行通讯的 callerApp = mService.getProcessController(caller); if (callerApp != null) { callingPid = callerApp.getPid(); callingUid = callerApp.mInfo.uid; } else { //异常情况,startActivity的调用方进程不存在或未启动 Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid + ") when starting: " + intent.toString()); err = ActivityManager.START_PERMISSION_DENIED; } } //获取当前用户ID final int userId = aInfo != null && aInfo.applicationInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; if (err == ActivityManager.START_SUCCESS) { Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + "} from uid " + callingUid); } ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; //调用方Activity Token != null if (resultTo != null) { //获取调用方ActivityRecord(要求存在任意一个Window栈中,即是RootWindow的子嗣) sourceRecord = mRootWindowContainer.isInAnyStack(resultTo); if (DEBUG_RESULTS) { Slog.v(TAG_RESULTS, "Will send result to " + resultTo + " " + sourceRecord); } if (sourceRecord != null) { //调用方需要response if (requestCode >= 0 && !sourceRecord.finishing) { resultRecord = sourceRecord; } } } final int launchFlags = intent.getFlags(); //多Activity传值场景 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) { ... } //找不到可以处理此Intent的组件 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { // We couldn't find a class that can handle the given Intent. // That's the end of that! err = ActivityManager.START_INTENT_NOT_RESOLVED; } //Intent中解析不出相应的Activity信息 if (err == ActivityManager.START_SUCCESS && aInfo == null) { // We couldn't find the specific class specified in the Intent. // Also the end of the line. err = ActivityManager.START_CLASS_NOT_FOUND; } if (err == ActivityManager.START_SUCCESS && sourceRecord != null && sourceRecord.getTask().voiceSession != null) { ... //语言交互相关 } if (err == ActivityManager.START_SUCCESS && voiceSession != null) { ... //语言交互相关 } final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getRootTask(); if (err != START_SUCCESS) { //回调给调用方Activity结果 if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED, null /* data */, null /* dataGrants */); } SafeActivityOptions.abort(options); return err; } //检查启动Activity的权限 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho, requestCode, callingPid, callingUid, callingPackage, callingFeatureId, request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord, resultStack); abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid, callingPackage); boolean restrictedBgActivity = false; if (!abort) { try { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "shouldAbortBackgroundActivityStart"); //检查是否要限制后台启动Activity restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, realCallingUid, realCallingPid, callerApp, request.originatingPendingIntent, request.allowBackgroundActivityStart, intent); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); } } // Merge the two options bundles, while realCallerOptions takes precedence. //过渡动画相关 ActivityOptions checkedOptions = options != null ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null; if (request.allowPendingRemoteAnimationRegistryLookup) { checkedOptions = mService.getActivityStartController() .getPendingRemoteAnimationRegistry() .overrideOptionsIfNeeded(callingPackage, checkedOptions); } if (mService.mController != null) { try { // The Intent we give to the watcher has the extra data stripped off, since it // can contain private information. Intent watchIntent = intent.cloneFilter(); //这个方法似乎只打印了一些日志,恒返回true,即abort |= false abort |= !mService.mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { mService.mController = null; } } //初始化ActivityStartInterceptor mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage, callingFeatureId); if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid, checkedOptions)) { // activity start was intercepted, e.g. because the target user is currently in quiet // mode (turn off work) or the target application is suspended //拦截并转化成其他的启动模式 intent = mInterceptor.mIntent; rInfo = mInterceptor.mRInfo; aInfo = mInterceptor.mAInfo; resolvedType = mInterceptor.mResolvedType; inTask = mInterceptor.mInTask; callingPid = mInterceptor.mCallingPid; callingUid = mInterceptor.mCallingUid; checkedOptions = mInterceptor.mActivityOptions; // The interception target shouldn't get any permission grants // intended for the original destination intentGrants = null; } if (abort) { //回调给调用方Activity结果 if (resultRecord != null) { resultRecord.sendResult(INVALID_UID, resultWho, requestCode, RESULT_CANCELED, null /* data */, null /* dataGrants */); } // We pretend to the caller that it was really started, but they will just get a // cancel result. ActivityOptions.abort(checkedOptions); return START_ABORTED; } // If permissions need a review before any of the app components can run, we // launch the review activity and pass a pending intent to start the activity // we are to launching now after the review is completed. if (aInfo != null) { //如果启动的Activity没有相应权限,则需要用户手动确认允许权限后,再进行启动工作 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired( aInfo.packageName, userId)) { //将原来的Intent包装在新的Intent中,用这个确认权限的新Intent继续后面的启动工作 final IIntentSender target = mService.getIntentSenderLocked( ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingFeatureId, callingUid, userId, null, null, 0, new Intent[]{intent}, new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null); Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS); int flags = intent.getFlags(); flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; /* * Prevent reuse of review activity: Each app needs their own review activity. By * default activities launched with NEW_TASK or NEW_DOCUMENT try to reuse activities * with the same launch parameters (extras are ignored). Hence to avoid possible * reuse force a new activity via the MULTIPLE_TASK flag. * * Activities that are not launched with NEW_TASK or NEW_DOCUMENT are not re-used, * hence no need to add the flag in this case. */ if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) { flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK; } newIntent.setFlags(flags); newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName); newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target)); if (resultRecord != null) { newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true); } intent = newIntent; // The permissions review target shouldn't get any permission // grants intended for the original destination intentGrants = null; resolvedType = null; callingUid = realCallingUid; callingPid = realCallingPid; rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0, computeResolveFilterUid( callingUid, realCallingUid, request.filterCallingUid)); aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/); } } // If we have an ephemeral app, abort the process of launching the resolved intent. // Instead, launch the ephemeral installer. Once the installer is finished, it // starts either the intent we resolved here [on install error] or the ephemeral // app [on install success]. if (rInfo != null && rInfo.auxiliaryInfo != null) { ... //Instant App相关 } //创建启动Activity的ActivityRecord final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid, callingPackage, callingFeatureId, intent, resolvedType, aInfo, mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode, request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions, sourceRecord); mLastStartActivityRecord = r; if (r.appTimeTracker == null && sourceRecord != null) { // If the caller didn't specify an explicit time tracker, we want to continue // tracking under any it has. r.appTimeTracker = sourceRecord.appTimeTracker; } //获取顶层焦点的Acticity栈 final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack(); // If we are starting an activity that is not from the same uid as the currently resumed // one, check whether app switches are allowed. //当此时栈顶Activity UID != 调用方 UID的时候(比如悬浮窗) if (voiceSession == null && stack != null && (stack.getResumedActivity() == null || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) { //检查是否可以直接切换应用 // 1. 设置的 mAppSwitchesAllowedTime < 当前系统时间(stopAppSwitches) // 2. 调用方在最近任务中 // 3. 调用方具有 STOP_APP_SWITCHES 权限 // ... if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, realCallingPid, realCallingUid, "Activity start")) { //加入到延时启动列表中 if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) { mController.addPendingActivityLaunch(new PendingActivityLaunch(r, sourceRecord, startFlags, stack, callerApp, intentGrants)); } ActivityOptions.abort(checkedOptions); return ActivityManager.START_SWITCHES_CANCELED; } } //回调处理延迟应用切换 mService.onStartActivitySetDidAppSwitch(); mController.doPendingActivityLaunches(false); //核心:进入Activity启动的下一阶段 mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask, restrictedBgActivity, intentGrants); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; } return mLastStartActivityResult; }这个函数大部分都是检查工作,这些可以看我标的注释,基本上介绍的比较详细了,然后进入到Activity启动的下一步,startActivityUnchecked/** * Start an activity while most of preliminary checks has been done and caller has been * confirmed that holds necessary permissions to do so. * Here also ensures that the starting activity is removed if the start wasn't successful. */ private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { int result = START_CANCELED; final ActivityStack startedActivityStack; try { //暂停布局工作,避免重复刷新 mService.deferWindowLayout(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); //接着把启动Activity工作交给这个方法 result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); //进行一些更新Configuration,清理栈等收尾工作 startedActivityStack = handleStartResult(r, result); //恢复布局工作 mService.continueWindowLayout(); } postStartActivityProcessing(r, result, startedActivityStack); return result; }这个方法也不是主要逻辑所在,我们往下接着看startActivityInner方法/** * Start an activity and determine if the activity should be adding to the top of an existing * task or delivered new intent to an existing activity. Also manipulating the activity task * onto requested or valid stack/display. * * Note: This method should only be called from {@link #startActivityUnchecked}. */ // TODO(b/152429287): Make it easier to exercise code paths through startActivityInner @VisibleForTesting int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { //设置初始化参数 setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor, restrictedBgActivity); //计算处理Activity启动模式 computeLaunchingTaskFlags(); //计算调用方Activity任务栈 computeSourceStack(); //将flags设置为调整后的LaunchFlags mIntent.setFlags(mLaunchFlags); //查找是否有可复用的Task final Task reusedTask = getReusableTask(); // If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid) && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) { mFrozeTaskList = true; mSupervisor.mRecentTasks.setFreezeTaskListReordering(); } // Compute if there is an existing task that should be used for. //计算是否存在可使用的现有Task final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask(); final boolean newTask = targetTask == null; mTargetTask = targetTask; //计算启动参数 computeLaunchParams(r, sourceRecord, targetTask); // Check if starting activity on given task or on a new task is allowed. //检查是否允许在targetTask上或者新建Task启动 int startResult = isAllowedToStart(r, newTask, targetTask); if (startResult != START_SUCCESS) { return startResult; } //获得栈顶未finish的ActivityRecord final ActivityRecord targetTaskTop = newTask ? null : targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null) { // Recycle the target task for this launch. //回收,准备复用这个Task startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } else { mAddingToTask = true; } // If the activity being launched is the same as the one currently at the top, then // we need to check if it should only be launched once. //处理singleTop启动模式 final ActivityStack topStack = mRootWindowContainer.getTopDisplayFocusedStack(); if (topStack != null) { startResult = deliverToCurrentTopIfNeeded(topStack, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } //复用或创建Activity栈 if (mTargetStack == null) { mTargetStack = getLaunchStack(mStartActivity, mLaunchFlags, targetTask, mOptions); } if (newTask) { //开启新Task final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; //复用或新建一个Task,并建立Task与ActivityRecord之间的关联 setNewTask(taskToAffiliate); if (mService.getLockTaskController().isLockTaskModeViolation( mStartActivity.getTask())) { Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity); return START_RETURN_LOCK_TASK_MODE_VIOLATION; } } else if (mAddingToTask) { //复用Task //将启动Activity添加到targetTask容器顶部或将其父容器替换成targetTask(也会将启动Activity添加到targetTask容器顶部) addOrReparentStartingActivity(targetTask, "adding to task"); } if (!mAvoidMoveToFront && mDoResume) { mTargetStack.getStack().moveToFront("reuseOrNewTask", targetTask); if (mOptions != null) { if (mOptions.getTaskAlwaysOnTop()) { mTargetStack.setAlwaysOnTop(true); } } if (!mTargetStack.isTopStackInDisplayArea() && mService.mInternal.isDreaming()) { // Launching underneath dream activity (fullscreen, always-on-top). Run the launch- // -behind transition so the Activity gets created and starts in visible state. mLaunchTaskBehind = true; r.mLaunchTaskBehind = true; } } ... mTargetStack.mLastPausedActivity = null; mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded( false /* forceSend */, mStartActivity); //将Task移到ActivityStack容器顶部 mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(), newTask, mKeepCurTransition, mOptions); if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); //启动的Activity不可获得焦点,无法恢复它 if (!mTargetStack.isTopActivityFocusable() || (topTaskActivity != null && topTaskActivity.isTaskOverlay() && mStartActivity != topTaskActivity)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. // Also, we don't want to resume activities in a task that currently has an overlay // as the starting activity just needs to be in the visible paused state until the // over is removed. // Passing {@code null} as the start parameter ensures all activities are made // visible. mTargetStack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mTargetStack.getDisplay().mDisplayContent.executeAppTransition(); } else { // If the target stack was not previously focusable (previous top running activity // on that stack was not visible) then any prior calls to move the stack to the // will not update the focused stack. If starting the new activity now allows the // task stack to be focusable, then ensure that we now update the focused stack // accordingly. if (mTargetStack.isTopActivityFocusable() && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) { mTargetStack.moveToFront("startActivityInner"); } //重点:恢复栈顶Activities mRootWindowContainer.resumeFocusedStacksTopActivities( mTargetStack, mStartActivity, mOptions); } } mRootWindowContainer.updateUserStack(mStartActivity.mUserId, mTargetStack); // Update the recent tasks list immediately when the activity starts //当Activity启动后立刻更新最近任务列表 mSupervisor.mRecentTasks.add(mStartActivity.getTask()); mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetStack); return START_SUCCESS; }这里主要做了一些Task和栈的操作,是否可以复用栈,是否需要新栈,处理栈顶复用等相关操作。我们需要注意一下这里关于Task的操作,不管是新建Task(newTask)还是复用Task(mAddingToTask),都会调用到addOrReparentStartingActivity方法将启动ActivityRecord添加到targetTask容器顶部(newTask的情况下会调用setNewTask方法先复用或创建Task,然后再用这个Task调用addOrReparentStartingActivity方法),之后调用mTargetStack.startActivityLocked方法将Task移到mTargetStack容器顶部,此时调用mTargetStack.topRunningActivity便会得到我们将要启动的这个ActivityRecord最后判断目标Activity是否可获得焦点,当可获得焦点的时候,调用RootWindowContainer.resumeFocusedStacksTopActivities方法恢复Activity要注意,从这个方法开始的以后的方法不再只是针对Activity启动的方法,它们有可能被多方调用,所以其中的一些步骤case我们是不会经历的,可以忽略掉这部分RootWindowContainerRootWindowContainer是显示窗口的根窗口容器,它主要是用来管理显示屏幕的boolean resumeFocusedStacksTopActivities( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) { if (!mStackSupervisor.readyToResume()) { return false; } boolean result = false; //目标栈在栈顶显示区域 if (targetStack != null && (targetStack.isTopStackInDisplayArea() || getTopDisplayFocusedStack() == targetStack)) { //使用目标栈进行恢复 result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); } //可能存在多显示设备(投屏等) for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { boolean resumedOnDisplay = false; final DisplayContent display = getChildAt(displayNdx); for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) { final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx); for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) { final ActivityStack stack = taskDisplayArea.getStackAt(sNdx); final ActivityRecord topRunningActivity = stack.topRunningActivity(); if (!stack.isFocusableAndVisible() || topRunningActivity == null) { continue; } if (stack == targetStack) { //如果进入到这里,代表着targetStack在上面已经恢复过了,此时只需要记录结果即可 resumedOnDisplay |= result; continue; } if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) { //执行切换效果 stack.executeAppTransition(targetOptions); } else { //使顶部显示的Activity执行Resume、Pause或Start生命周期 resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target); } } } if (!resumedOnDisplay) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home // activity is started and resumed, and no recursion occurs. //当没有任何有效的Activity的时候(设备刚启动或Launcher崩溃),可能没有任何东西可被恢复 //这时候使用DisplayContent中的焦点栈进行恢复 //如果连存在焦点的栈都没有,则恢复Launcher的Activity final ActivityStack focusedStack = display.getFocusedStack(); if (focusedStack != null) { result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); } else if (targetStack == null) { result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); } } } return result; }这个方法主要做了几件事:如果目标栈在栈顶显示区域,执行Resume遍历显示设备,从中遍历所有有焦点并且可见的栈,对其栈顶Activity执行相应的切换效果及生命周期对每个显示设备,如果存在焦点栈,则使用其执行Resume,否则启动Launcher在正常情况下,我们会走进ActivityStack.resumeTopActivityUncheckedLocked这个方法ActivityStackActivity栈,用于管理栈中的Activityboolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { if (mInResumeTopActivity) { // Don't even start recursing. //防止递归 return false; } boolean result = false; try { // Protect against recursion. //防止递归 mInResumeTopActivity = true; result = resumeTopActivityInnerLocked(prev, options); // When resuming the top activity, it may be necessary to pause the top activity (for // example, returning to the lock screen. We suppress the normal pause logic in // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here // to ensure any necessary pause logic occurs. In the case where the Activity will be // shown regardless of the lock screen, the call to // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. final ActivityRecord next = topRunningActivity(true /* focusableOnly */); if (next == null || !next.canTurnScreenOn()) { //准备休眠 checkReadyForSleep(); } } finally { mInResumeTopActivity = false; } return result; }这里做了一个防止递归调用的措施,接下来调用了resumeTopActivityInnerLocked方法private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { if (!mAtmService.isBooting() && !mAtmService.isBooted()) { // Not ready yet! //ATMS服务尚未准备好 return false; } // Find the next top-most activity to resume in this stack that is not finishing and is // focusable. If it is not focusable, we will fall into the case below to resume the // top activity in the next focusable task. //在之前我们已经把要启动的ActivityRecord加到了栈顶 ActivityRecord next = topRunningActivity(true /* focusableOnly */); final boolean hasRunningActivity = next != null; ... if (!hasRunningActivity) { // There are no activities left in the stack, let's look somewhere else. return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); } next.delayedResume = false; final TaskDisplayArea taskDisplayArea = getDisplayArea(); // If the top activity is the resumed one, nothing to do. //如果需要Resume的已在顶部且状态为Resume,不需要做任何事 //启动Activity不会碰到这种case if (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { ... return false; } if (!next.canResumeByCompat()) { return false; } // If we are currently pausing an activity, then don't do anything until that is done. //如果有正在Pause的Activity,在它Pause完成前不要做任何事 final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete(); if (!allPausedComplete) { return false; } ... // Make sure that the user who owns this activity is started. If not, // we will just leave it as is because someone should be bringing // another user's activities to the top of the stack. //确保拥有此Activity的用户已启动 if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) { return false; } // The activity may be waiting for stop, but that is no longer // appropriate for it. mStackSupervisor.mStoppingActivities.remove(next); next.setSleeping(false); //这里似乎重复检查了,我去查看了一下master分支的代码,已经没有这一段了 if (!mRootWindowContainer.allPausedActivitiesComplete()) { return false; } //设置启动Activity UID,获取WakeLock,保证在显示Activity的过程中,系统不会进行休眠状态 mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); ActivityRecord lastResumed = null; //上一个具有焦点的ActivityStack(目前仍是屏幕上正在显示的那个Activity的栈) final ActivityStack lastFocusedStack = taskDisplayArea.getLastFocusedStack(); if (lastFocusedStack != null && lastFocusedStack != this) { lastResumed = lastFocusedStack.mResumedActivity; ... } //Pause掉其他ActivityStack中的栈顶状态为Resume的Activity boolean pausing = taskDisplayArea.pauseBackStacks(userLeaving, next); //Pause掉当前ActivityStack中的栈顶状态为Resume的Activity if (mResumedActivity != null) { pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next); } if (pausing) { //有Activity执行了Pause // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.attachedToProcess()) { //将启动的Activity进程信息移至lru列表的头部 //因为很快就会使用它启动Activity next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, true /* activityChange */, false /* updateOomAdj */, false /* addPendingTopUid */); } else if (!next.isProcessRunning()) { //App进程未启动 // Since the start-process is asynchronous, if we already know the process of next // activity isn't running, we can start the process earlier to save the time to wait // for the current activity to be paused. final boolean isTop = this == taskDisplayArea.getFocusedStack(); //启动App进程 mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop, isTop ? "pre-top-activity" : "pre-activity"); } ... //这里会先结束掉启动Activity的流程,等待onPause生命周期走完后 //再重新调用这个方法执行下一步操作,避免Activity生命周期紊乱 return true; } else if (mResumedActivity == next && next.isState(RESUMED) && taskDisplayArea.allResumedActivitiesComplete()) { // It is possible for the activity to be resumed when we paused back stacks above if the // next activity doesn't have to wait for pause to complete. // So, nothing else to-do except: // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. //不需要等待其他的Activity onPause完成 //执行完切换效果后就没有什么其他需要做的了 executeAppTransition(options); return true; } ... //启动Activity流程不会进入这个case if (prev != null && prev != next && next.nowVisible) { if (prev.finishing) { prev.setVisibility(false); } } //修改启动Activity的package的状态 mAtmService.getPackageManager().setPackageStoppedState( next.packageName, false, next.mUserId); ... //Activity转场动画准备 if (next.attachedToProcess()) { //对于将要启动的ActivityRecord来说,此时尚未完成和Process的绑定,返回false ... ActivityRecord lastResumedActivity = lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; //保存状态以做后面恢复使用 final ActivityState lastState = next.getState(); mAtmService.updateCpuStats(); //更新ActivityRecord状态 next.setState(RESUMED, "resumeTopActivityInnerLocked"); //更新启动Activity的进程信息并将其移至lru列表的头部 next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, true /* activityChange */, true /* updateOomAdj */, true /* addPendingTopUid */); ... //更新Activity显示、方向和Configuration try { final ClientTransaction transaction = ClientTransaction.obtain(next.app.getThread(), next.appToken); // Deliver all pending results. ArrayList<ResultInfo> a = next.results; if (a != null) { final int N = a.size(); if (!next.finishing && N > 0) { if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Delivering results to " + next + ": " + a); transaction.addCallback(ActivityResultItem.obtain(a)); } } if (next.newIntents != null) { transaction.addCallback( NewIntentItem.obtain(next.newIntents, true /* resume */)); } // Well the app will no longer be stopped. // Clear app token stopped state in window manager if needed. next.notifyAppResumed(next.stopped); EventLogTags.writeWmResumeActivity(next.mUserId, System.identityHashCode(next), next.getTask().mTaskId, next.shortComponentName); next.setSleeping(false); mAtmService.getAppWarningsLocked().onResumeActivity(next); next.app.setPendingUiCleanAndForceProcessStateUpTo(mAtmService.mTopProcessState); next.clearOptionsLocked(); //设置onResume生命周期请求 transaction.setLifecycleStateRequest( ResumeActivityItem.obtain(next.app.getReportedProcState(), dc.isNextTransitionForward())); //调度执行Activity onResume生命周期 mAtmService.getLifecycleManager().scheduleTransaction(transaction); if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " + next); } catch (Exception e) { //resume失败需要尝试restart //恢复初始状态 next.setState(lastState, "resumeTopActivityInnerLocked"); if (lastResumedActivity != null) { lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); } ... //重新启动Activity mStackSupervisor.startSpecificActivity(next, true, false); return true; } // From this point on, if something goes wrong there is no way // to recover the activity. try { //更新信息 next.completeResumeLocked(); } catch (Exception e) { // If any exception gets thrown, toss away this // activity and try the next one. Slog.w(TAG, "Exception thrown during resume of " + next, e); next.finishIfPossible("resume-exception", true /* oomAdj */); return true; } } else { //尚未绑定Process // Whoops, need to restart this activity! if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { next.showStartingWindow(null /* prev */, false /* newTask */, false /* taskSwich */); } } //启动Activity mStackSupervisor.startSpecificActivity(next, true, true); } return true; }这里的代码很长,其实我们只需要关注三个点:Pause掉其他Activity如果对应App尚未启动,启动App进程启动Activity第一步,在启动Activity前,我们需要先Pause掉其他Activity,这一点很好理解,我们可以对照着看Activity生命周期也是这样的,这里会通过ATMS跨进程调用相应Activity的onPause生命周期,等待onPause执行完成后,再跨进程调用回ATMS,经过一系列方法调用,又重新调用resumeTopActivityInnerLocked方法,继续执行下一步操作第二步,如果App尚未启动,则先去启动App进程,这主要体现在这里if (!next.isProcessRunning()) { //App进程未启动 //启动App进程 mAtmService.startProcessAsync(next, false /* knownToBeDead */, isTop, isTop ? "pre-top-activity" : "pre-activity"); } 在启动完App进程后,会调用ATMS的attachApplication方法,最终调用到ActivityStackSupervisor.realStartActivityLocked方法启动Activity,这个方法后面会讲第三步,如果App进程已经启动,这时候会调用ActivityStackSupervisor.startSpecificActivity方法,最终殊途同归调用ActivityStackSupervisor.realStartActivityLocked方法启动Activity结束这里篇幅有点过长了,所以我觉得还是分篇比较好,这一章其实重要内容不是很多,最主要的内容,像Activity的生命周期控制,App进程的启动,Activity具体的启动及其后续生命周期执行都会放在下一章来讲

0
0
0
浏览量880
chole

Android源码分析 - Binder驱动(上)

开篇本篇以aosp分支android-11.0.0_r25,kernel分支android-msm-wahoo-4.4-android11作为基础解析上一篇文章Android源码分析 - Binder概述我们大概了解了一下Android选用Binder的原因,以及Binder的基本结构和通信过程。今天,我们便开始从Binder驱动层代码开始分析Binder的机制提示Binder驱动部分代码不在AOSP项目中,所以我们需要单独clone一份驱动代码由于我的开发设备是pixel2,查了Linux内核版本号为4.4.223,对应的分支为android-msm-wahoo-4.4-android11,所以今天的分析我们也是基于此分支我是从清华大学镜像站clone的代码,高通的设备,所以地址为:aosp.tuna.tsinghua.edu.cn/android/ker…初始化binder驱动的源码位于drivers/android目录下,我们从binder.c文件看起Linux initcall机制在binder.c的最底下,我们可以看到这一行代码device_initcall(binder_init);在Linux内核中,驱动程序通常是用xxx_initcall(fn)启动的,这实际上是一个宏定义,被定义在平台对应的init.h文件中#define early_initcall(fn) __define_initcall(fn, early) #define pure_initcall(fn) __define_initcall(fn, 0) #define core_initcall(fn) __define_initcall(fn, 1) #define core_initcall_sync(fn) __define_initcall(fn, 1s) #define postcore_initcall(fn) __define_initcall(fn, 2) #define postcore_initcall_sync(fn) __define_initcall(fn, 2s) #define arch_initcall(fn) __define_initcall(fn, 3) #define arch_initcall_sync(fn) __define_initcall(fn, 3s) #define subsys_initcall(fn) __define_initcall(fn, 4) #define subsys_initcall_sync(fn) __define_initcall(fn, 4s) #define fs_initcall(fn) __define_initcall(fn, 5) #define fs_initcall_sync(fn) __define_initcall(fn, 5s) #define rootfs_initcall(fn) __define_initcall(fn, rootfs) #define device_initcall(fn) __define_initcall(fn, 6) #define device_initcall_sync(fn) __define_initcall(fn, 6s) #define late_initcall(fn) __define_initcall(fn, 7) #define late_initcall_sync(fn) __define_initcall(fn, 7s)可以看到,实际上调用的是__define_initcall()函数,这个函数的第二个参数表示优先级,数字越小,优先级越高,带s的优先级低于不带s的优先级在Linux内核启动过程中,需要调用各种函数,在底层实现是通过在内核镜像文件中,自定义一个段,这个段里面专门用来存放这些初始化函数的地址,内核启动时,只需要在这个段地址处取出函数指针,一个个执行即可,而__define_initcall()函数,就是将自定义的init函数添加到上述段中binder_init了解了以上函数定义后,我们再回头看device_initcall(binder_init)就可以知道,在Linux内核启动时,会调用binder_init这么一个函数static int __init binder_init(void) { int ret; char *device_name, *device_names, *device_tmp; struct binder_device *device; struct hlist_node *tmp; //初始化binder内存回收 ret = binder_alloc_shrinker_init(); if (ret) return ret; ... //创建一个单线程工作队列,用于处理异步任务 binder_deferred_workqueue = create_singlethread_workqueue("binder"); if (!binder_deferred_workqueue) return -ENOMEM; //创建binder/proc目录 binder_debugfs_dir_entry_root = debugfs_create_dir("binder", NULL); if (binder_debugfs_dir_entry_root) binder_debugfs_dir_entry_proc = debugfs_create_dir("proc", binder_debugfs_dir_entry_root); //在binder目录下创建5个文件 if (binder_debugfs_dir_entry_root) { debugfs_create_file("state", 0444, binder_debugfs_dir_entry_root, NULL, &binder_state_fops); debugfs_create_file("stats", 0444, binder_debugfs_dir_entry_root, NULL, &binder_stats_fops); debugfs_create_file("transactions", 0444, binder_debugfs_dir_entry_root, NULL, &binder_transactions_fops); debugfs_create_file("transaction_log", 0444, binder_debugfs_dir_entry_root, &binder_transaction_log, &binder_transaction_log_fops); debugfs_create_file("failed_transaction_log", 0444, binder_debugfs_dir_entry_root, &binder_transaction_log_failed, &binder_transaction_log_fops); } //"binder,hwbinder,vndbinder" device_names = kzalloc(strlen(binder_devices_param) + 1, GFP_KERNEL); if (!device_names) { ret = -ENOMEM; goto err_alloc_device_names_failed; } strcpy(device_names, binder_devices_param); device_tmp = device_names; //用binder,hwbinder,vndbinder分别调用init_binder_device函数 while ((device_name = strsep(&device_tmp, ","))) { ret = init_binder_device(device_name); if (ret) goto err_init_binder_device_failed; } return ret; err_init_binder_device_failed: ... err_alloc_device_names_failed: ... }我们将重点放在init_binder_device函数上init_binder_devicestatic int __init init_binder_device(const char *name) { int ret; struct binder_device *binder_device; binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL); if (!binder_device) return -ENOMEM; //binder注册虚拟字符设备所对应的file_operations binder_device->miscdev.fops = &binder_fops; //动态分配次设备号 binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; binder_device->miscdev.name = name; binder_device->context.binder_context_mgr_uid = INVALID_UID; binder_device->context.name = name; //初始化互斥锁 mutex_init(&binder_device->context.context_mgr_node_lock); //注册misc设备 ret = misc_register(&binder_device->miscdev); if (ret < 0) { kfree(binder_device); return ret; } //将binder设备加入链表(头插法) hlist_add_head(&binder_device->hlist, &binder_devices); return ret; }先构造了一个结构体用来存放binder参数,然后通过misc_register函数,以misc设备进行注册binder,作为虚拟字符设备注册misc设备我们先学习一下在Linux中如何注册一个misc设备在Linux驱动中把无法归类的五花八门的设备定义为misc设备,Linux内核所提供的misc设备有很强的包容性,各种无法归结为标准字符设备的类型都可以定义为misc设备,譬如NVRAM,看门狗,实时时钟,字符LCD等在Linux内核里把所有的misc设备组织在一起,构成了一个子系统(subsys),统一进行管理。在这个子系统里的所有miscdevice类型的设备共享一个主设备号MISC_MAJOR(10),但次设备号不同在内核中用miscdevice结构体表示misc设备,具体的定义在include/linux/miscdevice.h中 struct miscdevice { int minor; const char *name; const struct file_operations *fops; struct list_head list; struct device *parent; struct device *this_device; const struct attribute_group **groups; const char *nodename; umode_t mode; };我们自己注册misc设备时只需要填入前3项即可:minor:次设备号,如果填充MISC_DYNAMIC_MINOR,则由内核动态分配次设备号name:设备名fops:file_operations结构体,用于定义自己misc设备的文件操作函数,如果不填此项则会使用默认的misc_fopsfile_operations结构体被定义在include/linux/fs.h中struct file_operations { struct module *owner; loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); ssize_t (*read_iter) (struct kiocb *, struct iov_iter *); ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*flush) (struct file *, fl_owner_t id); int (*release) (struct inode *, struct file *); int (*fsync) (struct file *, loff_t, loff_t, int datasync); int (*aio_fsync) (struct kiocb *, int datasync); int (*fasync) (int, struct file *, int); int (*lock) (struct file *, int, struct file_lock *); ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); int (*check_flags)(int); int (*flock) (struct file *, int, struct file_lock *); ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int); ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int); int (*setlease)(struct file *, long, struct file_lock **, void **); long (*fallocate)(struct file *file, int mode, loff_t offset, loff_t len); void (*show_fdinfo)(struct seq_file *m, struct file *f); #ifndef CONFIG_MMU unsigned (*mmap_capabilities)(struct file *); #endif };file_operation是把系统调用和驱动程序关联起来的关键结构,这个结构的每一个成员都对应着一个系统调用,Linux系统调用通过读取file_operation中相应的函数指针,接着把控制权转交给函数,从而完成Linux设备驱动程序的工作最后调用m//注册misc设备extern int misc_register(struct miscdevice *misc); //卸载misc设备 extern void misc_deregister(struct miscdevice *misc); isc_register函数注册misc设备,函数原型如下:注册binder设备了解了misc设备的注册,我们就可以看一下binder的注册过程了,代码中先构建了一个binder_device结构体,我们先观察一下这个结构体长什么样子struct binder_device { struct hlist_node hlist; struct miscdevice miscdev; struct binder_context context; }; 其中的hlist_node是链表中的一个节点,miscdevice就是上文所描述的注册misc所必要的结构体参数,binder_context用于保存binder上下文管理者的信息回到代码中,首先给miscdevice赋了值,指定了file_operation,设置了minor动态分配次设备号,binder_context则是简单初始化了一下,然后便调用misc_register函数注册misc设备,最后将这个binder设备使用头插法加入到一个全局链表中我们看一下它指定的file_operation static const struct file_operations binder_fops = { .owner = THIS_MODULE, .poll = binder_poll, .unlocked_ioctl = binder_ioctl, .compat_ioctl = binder_ioctl, .mmap = binder_mmap, .open = binder_open, .flush = binder_flush, .release = binder_release, };可以看到,binder驱动支持以上7种系统调用,接下来,我们就逐一分析这些系统调用binder_proc在分析这些系统调用前,我们有必要先了解一下在binder中非常重要的结构体binder_proc,它是用来描述进程上下文信息以及管理IPC的一个结构体,被定义在drivers/android/binder.c中,是一个私有的结构体struct binder_proc { //hash链表中的一个节点 struct hlist_node proc_node; //处理用户请求的线程组成的红黑树 struct rb_root threads; //binder实体组成的红黑树 struct rb_root nodes; //binder引用组成的红黑树,以句柄来排序 struct rb_root refs_by_desc; //binder引用组成的红黑树,以它对应的binder实体的地址来排序 struct rb_root refs_by_node; struct list_head waiting_threads; //进程id int pid; //进程描述符 struct task_struct *tsk; //进程打开的所有文件数据 struct files_struct *files; struct mutex files_lock; struct hlist_node deferred_work_node; int deferred_work; bool is_dead; //待处理事件队列 struct list_head todo; struct binder_stats stats; struct list_head delivered_death; int max_threads; int requested_threads; int requested_threads_started; atomic_t tmp_ref; struct binder_priority default_priority; struct dentry *debugfs_entry; //用来记录mmap分配的用户虚拟地址空间和内核虚拟地址空间等信息 struct binder_alloc alloc; struct binder_context *context; spinlock_t inner_lock; spinlock_t outer_lock; };binder_open我们先从打开binder驱动设备开始static int binder_open(struct inode *nodp, struct file *filp) { //管理IPC和保存进程信息的结构体 struct binder_proc *proc; struct binder_device *binder_dev; ... proc = kzalloc(sizeof(*proc), GFP_KERNEL); if (proc == NULL) return -ENOMEM; //初始化内核同步自旋锁 spin_lock_init(&proc->inner_lock); spin_lock_init(&proc->outer_lock); //原子操作赋值 atomic_set(&proc->tmp_ref, 0); //使执行当前系统调用进程的task_struct.usage加1 get_task_struct(current->group_leader); //使binder_proc中的tsk指向执行当前系统调用的进程 proc->tsk = current->group_leader; //初始化文件锁 mutex_init(&proc->files_lock); //初始化todo列表 INIT_LIST_HEAD(&proc->todo); //设置优先级 if (binder_supported_policy(current->policy)) { proc->default_priority.sched_policy = current->policy; proc->default_priority.prio = current->normal_prio; } else { proc->default_priority.sched_policy = SCHED_NORMAL; proc->default_priority.prio = NICE_TO_PRIO(0); } //找到binder_device结构体的首地址 binder_dev = container_of(filp->private_data, struct binder_device, miscdev); //使binder_proc的上下文指向binder_device的上下文 proc->context = &binder_dev->context; //初始化binder缓冲区 binder_alloc_init(&proc->alloc); //全局binder_stats结构体中,BINDER_STAT_PROC类型的对象创建数量加1 binder_stats_created(BINDER_STAT_PROC); //设置当前进程id proc->pid = current->group_leader->pid; //初始化已分发的死亡通知列表 INIT_LIST_HEAD(&proc->delivered_death); //初始化等待线程列表 INIT_LIST_HEAD(&proc->waiting_threads); //保存binder_proc数据 filp->private_data = proc; //因为binder支持多线程,所以需要加锁 mutex_lock(&binder_procs_lock); //将binder_proc添加到binder_procs全局链表中 hlist_add_head(&proc->proc_node, &binder_procs); //释放锁 mutex_unlock(&binder_procs_lock); //在binder/proc目录下创建文件,以执行当前系统调用的进程id为名 if (binder_debugfs_dir_entry_proc) { char strbuf[11]; snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); proc->debugfs_entry = debugfs_create_file(strbuf, 0444, binder_debugfs_dir_entry_proc, (void *)(unsigned long)proc->pid, &binder_proc_fops); } return 0; }binder_open函数创建了binder_proc结构体,并把初始化并将当前进程等信息保存到binder_proc结构体中,然后将binder_proc结构体保存到文件指针filp的private_data中,再将binder_proc加入到全局链表binder_procs中这里面有一些关于Linux的知识需要解释一下spinlockspinlock是内核中提供的一种自旋锁机制。在Linux内核实现中,常常会碰到共享数据被中断上下文和进程上下文访问的场景,如果只有进程上下文的话,我们可以使用互斥锁或者信号量解决,将未获得锁的进程置为睡眠状态等待,但由于中断上下文不是一个进程,它不存在task_struct,所以不可被调度,当然也就不可睡眠,这时候就可以通过spinlock自旋锁的忙等待机制来达成睡眠同样的效果current在Linux内核中,定义了一个叫current的宏,它被定义在asm/current.h中static inline struct task_struct *get_current(void) { return(current_thread_info()->task); } #define current get_current()它返回一个task_struct指针,指向执行当前这段内核代码的进程container_ofcontainer_of也是Linux中定义的一个宏,它的作用是根据一个结构体变量中的一个域成员变量的指针来获取指向整个结构体变量的指针#define offsetof(TYPE, MEMBER) ((size_t)&((TYPE *)0)->MEMBER) #define container_of(ptr, type, member) ({              \          const typeof( ((type *)0)->member ) *__mptr = (ptr);    \          (type *)( (char *)__mptr - offsetof(type,member) );})fd&filpfilp->private_data保存了binder_proc结构体,当进程调用open系统函数时,内核会返回一个文件描述符fd,这个fd指向文件指针filp,在后续调用mmap,ioctl等函数与binder驱动交互时,会传入这个fd,内核就会以这个fd指向文件指针filp作为参数调用binder_mmap,binder_ioctl等函数,这样这些函数就可以通过filp->private_data取出binder_proc结构体binder_mmapvm_area_struct在分析mmap前,我们需要先了解一下vm_area_struct这个结构体,它被定义在include/linux/mm_types.h中 struct vm_area_struct { //当前vma的首地址 unsigned long vm_start; //当前vma的末地址后第一个字节的地址 unsigned long vm_end; //链表 struct vm_area_struct *vm_next, *vm_prev; //红黑树中对应节点 struct rb_node vm_rb; //当前vma前面还有多少空闲空间 unsigned long rb_subtree_gap; //当前vma所属的内存地址空间 struct mm_struct *vm_mm; //访问权限 pgprot_t vm_page_prot; //vma标识集,定义在 include/linux/mm.h 中 unsigned long vm_flags; union { struct { struct rb_node rb; unsigned long rb_subtree_last; } shared; const char __user *anon_name; }; struct list_head anon_vma_chain; struct anon_vma *anon_vma; //当前vma操作函数集指针 const struct vm_operations_struct *vm_ops; //当前vma起始地址在vm_file中的文件偏移,单位为物理页面PAGE_SIZE unsigned long vm_pgoff; //被映射的文件(如果使用文件映射) struct file * vm_file; void * vm_private_data; #ifndef CONFIG_MMU struct vm_region *vm_region; /* NOMMU mapping region */ #endif #ifdef CONFIG_NUMA struct mempolicy *vm_policy; /* NUMA policy for the VMA */ #endif struct vm_userfaultfd_ctx vm_userfaultfd_ctx; };vm_area_struct结构体描述了一段虚拟内存空间,通常,进程所使用到的虚拟内存空间不连续,且各部分虚存空间的访问属性也可能不同,所以一个进程的虚拟内存空间需要多个vm_area_struct结构来描述(后面简称vma)每个进程都有一个对应的task_struct结构描述,这个task_struct结构中有一个mm_struct结构用于描述进程的内存空间,mm_struct结构中有两个域成员变量分别指向了vma链表头和红黑树根vma所描述的虚拟内存空间范围由vm_start和vm_end表示,vm_start代表当前vma的首地址,vm_end代表当前vma的末地址后第一个字节的地址,即虚拟内存空间范围为[vm_start, vm_end)vm_operations_struct和上文中的file_operations类似,用来定义虚拟内存的操作函数介绍完vma,接下来我们便看一下binder_mmap函数static int binder_mmap(struct file *filp, struct vm_area_struct *vma) { int ret; struct binder_proc *proc = filp->private_data; const char *failure_string; //校验进程信息 if (proc->tsk != current->group_leader) return -EINVAL; //将虚拟内存地址大小限制在4M if ((vma->vm_end - vma->vm_start) > SZ_4M) vma->vm_end = vma->vm_start + SZ_4M; ... //检查用户空间是否可写(FORBIDDEN_MMAP_FLAGS == VM_WRITE) if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) { ret = -EPERM; failure_string = "bad vm_flags"; goto err_bad_arg; } //VM_DONTCOPY表示此vma不可被fork所复制 vma->vm_flags |= VM_DONTCOPY | VM_MIXEDMAP; //用户空间不可设置该vma的VM_WRITE标志 vma->vm_flags &= ~VM_MAYWRITE; //设置此vma操作函数集 vma->vm_ops = &binder_vm_ops; //指向binder_proc vma->vm_private_data = proc; //处理进程虚拟内存空间与内核虚拟地址空间的映射关系 ret = binder_alloc_mmap_handler(&proc->alloc, vma); if (ret) return ret; mutex_lock(&proc->files_lock); //获取进程的打开文件信息结构体files_struct,并将引用计数加1 proc->files = get_files_struct(current); mutex_unlock(&proc->files_lock); return 0; err_bad_arg: pr_err("%s: %d %lx-%lx %s failed %d\n", __func__, proc->pid, vma->vm_start, vma->vm_end, failure_string, ret); return ret; }首先从filp中获取对应的binder_proc信息将它的进程task_struct和执行当前这段内核代码的进程task_struct对比校验限制了用户空间虚拟内存的大小在4M以内检查用户空间是否可写(binder驱动为进程分配的缓冲区在用户空间中只可以读,不可以写)设置vm_flags,令vma不可写,不可复制设置vma的操作函数集将vm_area_struct中的成员变量vm_private_data指向binder_proc,使得vma设置的操作函数中可以拿到binder_proc处理进程虚拟内存空间与内核虚拟地址空间的映射关系获取进程的打开文件信息结构体files_struct,令binder_proc的files指向它,并将引用计数加1binder_alloc_mmap_handlerbinder_alloc_mmap_handler将进程虚拟内存空间与内核虚拟地址空间做映射,它被实现在drivers/android/binder_alloc.c中这里先介绍一下vm_struct,之前我们已经了解了vm_area_struct表示用户进程中的虚拟地址空间,而相对应的,vm_struct则表示内核中的虚拟地址空间int binder_alloc_mmap_handler(struct binder_alloc *alloc, struct vm_area_struct *vma) { int ret; struct vm_struct *area; const char *failure_string; struct binder_buffer *buffer; mutex_lock(&binder_alloc_mmap_lock); //检查是否已经分配过内核缓冲区 if (alloc->buffer) { ret = -EBUSY; failure_string = "already mapped"; goto err_already_mapped; } //获得一个内核虚拟空间 area = get_vm_area(vma->vm_end - vma->vm_start, VM_ALLOC); if (area == NULL) { ret = -ENOMEM; failure_string = "get_vm_area"; goto err_get_vm_area_failed; } //alloc->buffer指向内核虚拟内存空间地址 alloc->buffer = area->addr; //计算出用户虚拟空间线性地址到内核虚拟空间线性地址的偏移量 alloc->user_buffer_offset = vma->vm_start - (uintptr_t)alloc->buffer; mutex_unlock(&binder_alloc_mmap_lock); ... //申请内存 alloc->pages = kzalloc(sizeof(alloc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL); if (alloc->pages == NULL) { ret = -ENOMEM; failure_string = "alloc page array"; goto err_alloc_pages_failed; } //buffer大小等于vma大小 alloc->buffer_size = vma->vm_end - vma->vm_start; buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); if (!buffer) { ret = -ENOMEM; failure_string = "alloc buffer struct"; goto err_alloc_buf_struct_failed; } //指向内核虚拟空间地址 buffer->data = alloc->buffer; //将buffer添加到链表中 list_add(&buffer->entry, &alloc->buffers); buffer->free = 1; //将此内核缓冲区加入到binder_alloc的空闲缓冲红黑树中 binder_insert_free_buffer(alloc, buffer); //设置进程最大可用异步事务缓冲区大小(防止异步事务消耗过多内核缓冲区,影响同步事务) alloc->free_async_space = alloc->buffer_size / 2; //内存屏障,保证指令顺序执行 barrier(); //设置binder_alloc alloc->vma = vma; alloc->vma_vm_mm = vma->vm_mm; //引用计数+1 atomic_inc(&alloc->vma_vm_mm->mm_count); return 0; ... //错误处理 }检查是否已经分配过内核缓冲区从内核中寻找一块可用的虚拟内存地址将此内核虚拟内存空间地址保存至binder_alloc计算出用户虚拟空间线性地址到内核虚拟空间线性地址的偏移量(这样就可以非常方便的在用户虚拟内存空间与内核虚拟内存空间间切换)为alloc->pages数组申请内存,申请的大小等于vma能分配多少个页框设置buffer大小等于vma大小为binder_buffer申请内存,填充参数,使其指向内核虚拟空间地址,并将其添加到链表和红黑树中设置binder_alloc其他参数这里要注意,虽然我们计算出了用户虚拟空间线性地址到内核虚拟空间线性地址的偏移量,但并没有建立映射关系。在旧版内核中,这里会调用binder_update_page_range函数分别将内核虚拟内存和进程虚拟内存与物理内存做映射,这样内核虚拟内存和进程虚拟内存也相当于间接建立了映射关系,而在4.4.223中,这件事将会延迟到binder_ioctl后当完成物理内存的映射后,以32位系统,缓冲区大小4M为例,效果应该如下图所示:总结到这里,我们已经了解了binder驱动设备是如何注册的,并且分析了binder_open和binder_mmap操作函数,了解了一些重要的结构体,明白了mmap是如何映射用户空间和内核空间的,由于篇幅原因,下一章我们会分析binder驱动中最重要的部分binder_ioctl

0
0
0
浏览量873