Android 系统服务 PMS Installd 守护进程(二)

1,002 阅读10分钟

背景

PMS 中负责应用的安装、卸载工作,是由 Installer 系统服务来完成的。但 Installer也只是java层封装,真正干活是installd守护进程 的Binder服务: InstalldNativeService

installd 进程 具有root权限,pms的SystemServer进程只有 system 权限。

一、installd.rc

Installd 守护进程启动是从解析installd.rc文件开始的。

/frameworks/native/cmds/installd/installd.rc

2 service installd /system/bin/installd
3     class main

android 6.0是通过socket来与SystemServer通信的,后面改成通过 binder 机制来通信。

init进程解析 installd.rc 文件,启动installd服务,fork() 出 installd进程。执行入口函数main()

二、installd.cpp

/frameworks/native/cmds/installd/installd.cpp

     int main(const int argc, char *argv[]) {
239      return android::installd::installd_main(argc, argv);
240  }

2.1 installd_main()

static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
196      int ret;
197      int selinux_enabled = (is_selinux_enabled() > 0);
198  
199      setenv("ANDROID_LOG_TAGS", "*:v", 1);
200      android::base::InitLogging(argv);
201  
202      SLOGI("installd firing up");
203  
204      union selinux_callback cb;
205      cb.func_log = log_callback;
206      selinux_set_callback(SELINUX_CB_LOG, cb);
         // 初始化全局  
208      if (!initialize_globals()) {
209          SLOGE("Could not initialize globals; exiting.\n");
210          exit(1);
211      }
    212  // 初始化文件目录
213      if (initialize_directories() < 0) {
214          SLOGE("Could not create directories; exiting.\n");
215          exit(1);
216      }
    217  // linux se 增强
218      if (selinux_enabled && selinux_status_open(true) < 0) {
219          SLOGE("Could not open selinux status; exiting.\n");
220          exit(1);
221      }
222      // 内部注册installd服务到SM中。同时开启binder线程
223      if ((ret = InstalldNativeService::start()) != android::OK) {
224          SLOGE("Unable to start InstalldNativeService: %d", ret);
225          exit(1);
226      }
227      // IPCThreadState通过 talKWitchDriver()不断的与binder驱动通信,读写命令
228      IPCThreadState::self()->joinThreadPool();
229  
230      LOG(INFO) << "installd shutting down";
231  
232      return 0;
233  }
  1. 初始化全局目录
  2. 初始化文件目录
  3. linux SE增强,提高安全
  4. 注册 installd服务到SM;开启Binder线程
  5. talKWitchDriver() 从binder驱动读取数据

2.2 initialize_globals()

frameworks/native/cmds/installd/installd.cpp

static bool initialize_globals() {
69      return init_globals_from_data_and_root();
70  }
 bool init_globals_from_data_and_root() {
        // 获取目录: data/
64      const char* data_path = getenv("ANDROID_DATA");
65      ...
        // 获取目录: system/
69      const char* root_path = getenv("ANDROID_ROOT");
70      ...
74      return init_globals_from_data_and_root(data_path, root_path);
75  }

传入两个目录: /data/、/system/。

frameworks/native/cmds/installd/globals.cpp

    //部分常量如下:
31  static constexpr const char* APP_SUBDIR = "app/"; // sub-directory under ANDROID_DATA
33  static constexpr const char* PRIV_APP_SUBDIR = "priv-app/"; // sub-directory under ANDROID_DATA
35  static constexpr const char* EPHEMERAL_APP_SUBDIR = "app-ephemeral/"; // sub-directory under                                                                      // ANDROID_DATA
38  static constexpr const char* APP_LIB_SUBDIR = "app-lib/"; // sub-directory under ANDROID_DATA
40  static constexpr const char* MEDIA_SUBDIR = "media/"; // sub-directory under ANDROID_DATA
42  static constexpr const char* PROFILES_SUBDIR = "misc/profiles"; // sub-directory under ANDROID_DATA 
44  static constexpr const char* PRIVATE_APP_SUBDIR = "app-private/"; // sub-directory under                                                                 // ANDROID_DATA
47  static constexpr const char* STAGING_SUBDIR = "app-staging/"; // sub-directory under ANDROID_DATA

     bool init_globals_from_data_and_root(const char* data, const char* root) {
86      // Get the android data directory. 
        // data/ 目录
87      android_data_dir = ensure_trailing_slash(data);
88  
89      // Get the android root directory.
        // system/   目录
90      android_root_dir = ensure_trailing_slash(root);
91  
92      // Get the android app directory.
        //  /data/app/    app 目录
93      android_app_dir = android_data_dir + APP_SUBDIR;
94  
95      // Get the android protected app directory.
        //  /data/app-private/   受保护的私有目录目录
96      android_app_private_dir = android_data_dir + PRIVATE_APP_SUBDIR;
97  
98      // Get the android ephemeral app directory.
        //  /data/app-ephemeral//   临时目录
99      android_app_ephemeral_dir = android_data_dir + EPHEMERAL_APP_SUBDIR;
100  
101      // Get the android app native library directory.
        //  /data/app-lib/   native库的目录
102      android_app_lib_dir = android_data_dir + APP_LIB_SUBDIR;
103  
104      // Get the sd-card ASEC mount point.
        //  /mnt/aesc/   sdcard挂载点目录
105      android_asec_dir = ensure_trailing_slash(getenv(ASEC_MOUNTPOINT_ENV_NAME));
106  
107      // Get the android media directory.
        //  /data/media/   多媒体目录
108      android_media_dir = android_data_dir + MEDIA_SUBDIR;
109  
110      // Get the android external app directory.
        //  /mnt/expand/   外部目录
111      android_mnt_expand_dir = "/mnt/expand/";
112  
113      // Get the android profiles directory.
         //  data/misc/profiles   
114      android_profiles_dir = android_data_dir + PROFILES_SUBDIR;
115  
116      // Get the android session staging directory.
            //  data/app-staging/  
117      android_staging_dir = android_data_dir + STAGING_SUBDIR;
118  
119      // Take note of the system and vendor directories.
         // 系统和厂商的目录
120      android_system_dirs.clear();
          //  system/app/ 
121      android_system_dirs.push_back(android_root_dir + APP_SUBDIR);
          //  system/priv-app/
122      android_system_dirs.push_back(android_root_dir + PRIV_APP_SUBDIR);
            //   /vendor/app/
123      android_system_dirs.push_back("/vendor/app/");
        //   /oem/app/
124      android_system_dirs.push_back("/oem/app/");
125  
126      return true;
127  }

总结:

  • 初始化 /data 、/system 下的相关目录,保存到成员变量中。
  • 初始化系统和厂商目录

2.2.1 ensure_trailing_slash()

frameworks/native/cmds/installd/globals.cpp

 static std::string ensure_trailing_slash(const std::string& path) {
78      if (path.rfind('/') != path.size() - 1) {
79          return path + '/';
80      } else {
81          return path;
82      }
83  }

这个方法确保路径后面有/符号。

2.3 initialize_directories()

static int initialize_directories() {
73      int res = -1;
74  
75      // Read current filesystem layout version to handle upgrade paths
        // 读取文件系统 
76      char version_path[PATH_MAX];
77      snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.c_str());
78  
79      int oldVersion;
80      if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
81          oldVersion = 0;
82      }
83      int version = oldVersion;
84  
85      if (version < 2) {
86          SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
87          version = 2;
88      }
89      // 创建 /data/misc/user 目录
90      if (ensure_config_user_dirs(0) == -1) {
91          SLOGE("Failed to setup misc for user 0");
92          goto fail;
93      }
94  
95      if (version == 2) {
96          SLOGD("Upgrading to /data/misc/user directories");
97         //  misc_dir= /data/misc/
98          char misc_dir[PATH_MAX];
99          snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.c_str());
100             //  /data/misc/keychain/cacerts-added
101          char keychain_added_dir[PATH_MAX];
102          snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
103             
104          char keychain_removed_dir[PATH_MAX];
                 //  /data/misc/keychain/cacerts-removed
105          snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
106  
107          DIR *dir;
108          struct dirent *dirent;
                //  打开目录  /data/user 
109          dir = opendir("/data/user");
110          if (dir != nullptr) {
111              while ((dirent = readdir(dir))) {
112                  const char *name = dirent->d_name;
113  
114                  // skip "." and ".."
115                  if (name[0] == '.') {
116                      if (name[1] == 0) continue;
117                      if ((name[1] == '.') && (name[2] == 0)) continue;
118                  }
119                  // 根据名字获取uid
120                  uint32_t user_id = std::stoi(name);
121  
122                  // /data/misc/user/<user_id>
123                  if (ensure_config_user_dirs(user_id) == -1) {
124                      goto fail;
125                  }
126  
127                  char misc_added_dir[PATH_MAX];
                      // /data/misc/user/uid/keychain/cacerts-added
128                  snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
129  
130                  char misc_removed_dir[PATH_MAX];
                      // /data/misc/user/uid/keychain/cacerts-removed
131                  snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
132  
133                  uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
134                  gid_t gid = uid;
                      // 拷贝 /data/misc/keychain/cacerts-added--> 
                      //  /data/misc/user/uid/keychain/cacerts-added
135                  if (access(keychain_added_dir, F_OK) == 0) {
136                      if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
137                          SLOGE("Some files failed to copy");
138                      }
139                  }
140                  if (access(keychain_removed_dir, F_OK) == 0) {
141                      if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
142                          SLOGE("Some files failed to copy");
143                      }
144                  }
145              }
146              closedir(dir);
147  
148              if (access(keychain_added_dir, F_OK) == 0) {
149                  delete_dir_contents(keychain_added_dir, 1, nullptr);
150              }
151              if (access(keychain_removed_dir, F_OK) == 0) {
152                  delete_dir_contents(keychain_removed_dir, 1, nullptr);
153              }
154          }
155  
156          version = 3;
157      }
158  
159      // Persist layout version if changed
160      if (version != oldVersion) {
            // 更新版本号
161          if (fs_write_atomic_int(version_path, version) == -1) {
162              SLOGE("Failed to save version to %s: %s", version_path, strerror(errno));
163              goto fail;
164          }
165      }
166  
167      // Success!
168      res = 0;
169  
170  fail:
171      return res;
172  }

总结:

  1. 在 /data/user 目录下,遍历每个item,根据item获取uid。
  2. 把 /data/misc/keychain/ 目录里面的内容拷贝到 /data/misc/user/uid/keychain/ 目录。
  3. 删除 /data/misc/keychain/ 目录内容
  4. 更新版本号

2.4 注册服务 InstalldNativeService

/frameworks/native/cmds/installd/InstalldNativeService.cpp

 status_t InstalldNativeService::start() {
256      IPCThreadState::self()->disableBackgroundScheduling(true);
         // 通过模板类BinderService来注册服务
257      status_t ret = BinderService<InstalldNativeService>::publish();
258      if (ret != android::OK) {
259          return ret;
260      }
261      sp<ProcessState> ps(ProcessState::self());
         // 内部通过 new PoolThread()来创建binder线程
262      ps->startThreadPool();
263      ps->giveThreadPoolName();
264      return android::OK;
265  }
  1. 通过 BinderService 模板类的publish()方法注册服务
  2. 调用 ProcessState进程单例对象的 startThreadPool() 启动binder线程

2.4.1 BinderService 模板类

 // ---------------------------------------------------------------------------
31  namespace android {
32  
33  template<typename SERVICE>
34  class BinderService
35  {
36  public:// 提供了两个方法
        //注册服务
37      static status_t publish(bool allowIsolated = false,
38                              int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
39          sp<IServiceManager> sm(defaultServiceManager());
40          return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated,
41                                dumpFlags);
42      }
43  // 注册的同时,创建binder线程,进入循环
44      static void publishAndJoinThreadPool(
45              bool allowIsolated = false,
46              int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
47          publish(allowIsolated, dumpFlags);
48          joinThreadPool();
49      }
50  
51      static void instantiate() { publish(); }
52  
53      static status_t shutdown() { return NO_ERROR; }
54  
55  private:
56      static void joinThreadPool() {
57          sp<ProcessState> ps(ProcessState::self());
58          ps->startThreadPool();
59          ps->giveThreadPoolName();
60          IPCThreadState::self()->joinThreadPool();
61      }
62  };
63  
64  
65  }; // namespace android
66  // ---------------------------------------------------------------------------
67  #endif // ANDROID_BINDER_SERVICE_H
68  

提供了两个两个方法:publish()、publishAndJoinThreadPool()。

我们回过头来再看 InstalldNativeService 的 getServiceName()方法:

/frameworks/native/cmds/installd/InstalldNativeService.h

 static char const* getServiceName() { return "installd"; }

返回名字为 installd 的服务。

三、Installd 提供的接口

Installd 提供的方法是由 InstalldNativeService 服务来实现的。因此,我们查看 InstalldNativeService.h 头文件:

frameworks/native/cmds/installd/InstalldNativeService.h

 virtual status_t dump(int fd, const Vector<String16> &args) override;
42  
43      binder::Status createUserData(const std::unique_ptr<std::string>& uuid, int32_t userId,
44              int32_t userSerial, int32_t flags);
45      binder::Status destroyUserData(const std::unique_ptr<std::string>& uuid, int32_t userId,
46              int32_t flags);
47  
48      binder::Status createAppData(const std::unique_ptr<std::string>& uuid,
49              const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
50              const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return);
51      binder::Status restoreconAppData(const std::unique_ptr<std::string>& uuid,
52              const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
53              const std::string& seInfo);
54      binder::Status migrateAppData(const std::unique_ptr<std::string>& uuid,
55              const std::string& packageName, int32_t userId, int32_t flags);
56      binder::Status clearAppData(const std::unique_ptr<std::string>& uuid,
57              const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
58      binder::Status destroyAppData(const std::unique_ptr<std::string>& uuid,
59              const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
60  
61      binder::Status fixupAppData(const std::unique_ptr<std::string>& uuid, int32_t flags);
62  
63      binder::Status snapshotAppData(const std::unique_ptr<std::string>& volumeUuid,
64              const std::string& packageName, const int32_t user, const int32_t snapshotId,
65              int32_t storageFlags, int64_t* _aidl_return);
66      binder::Status restoreAppDataSnapshot(const std::unique_ptr<std::string>& volumeUuid,
67              const std::string& packageName, const int32_t appId, const std::string& seInfo,
68              const int32_t user, const int32_t snapshotId, int32_t storageFlags);
69      binder::Status destroyAppDataSnapshot(const std::unique_ptr<std::string> &volumeUuid,
70              const std::string& packageName, const int32_t user, const int64_t ceSnapshotInode,
71              const int32_t snapshotId, int32_t storageFlags);
72  
73      binder::Status getAppSize(const std::unique_ptr<std::string>& uuid,
74              const std::vector<std::string>& packageNames, int32_t userId, int32_t flags,
75              int32_t appId, const std::vector<int64_t>& ceDataInodes,
76              const std::vector<std::string>& codePaths, std::vector<int64_t>* _aidl_return);
77      binder::Status getUserSize(const std::unique_ptr<std::string>& uuid,
78              int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
79              std::vector<int64_t>* _aidl_return);
80      binder::Status getExternalSize(const std::unique_ptr<std::string>& uuid,
81              int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
82              std::vector<int64_t>* _aidl_return);
83  
84      binder::Status setAppQuota(const std::unique_ptr<std::string>& uuid,
85              int32_t userId, int32_t appId, int64_t cacheQuota);
86  
87      binder::Status moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
88              const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
89              const std::string& dataAppName, int32_t appId, const std::string& seInfo,
90              int32_t targetSdkVersion);
91  
92      binder::Status dexopt(const std::string& apkPath, int32_t uid,
93              const std::unique_ptr<std::string>& packageName, const std::string& instructionSet,
94              int32_t dexoptNeeded, const std::unique_ptr<std::string>& outputPath, int32_t dexFlags,
95              const std::string& compilerFilter, const std::unique_ptr<std::string>& uuid,
96              const std::unique_ptr<std::string>& classLoaderContext,
97              const std::unique_ptr<std::string>& seInfo, bool downgrade,
98              int32_t targetSdkVersion, const std::unique_ptr<std::string>& profileName,
99              const std::unique_ptr<std::string>& dexMetadataPath,
100              const std::unique_ptr<std::string>& compilationReason);
101  
102      binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName,
103                                    const std::string& outDexFile, int uid, bool* _aidl_return);
104  
105      binder::Status rmdex(const std::string& codePath, const std::string& instructionSet);
106  
107      binder::Status mergeProfiles(int32_t uid, const std::string& packageName,
108              const std::string& profileName, bool* _aidl_return);
109      binder::Status dumpProfiles(int32_t uid, const std::string& packageName,
110              const std::string& profileName, const std::string& codePath, bool* _aidl_return);
111      binder::Status copySystemProfile(const std::string& systemProfile,
112              int32_t uid, const std::string& packageName, const std::string& profileName,
113              bool* _aidl_return);
114      binder::Status clearAppProfiles(const std::string& packageName, const std::string& profileName);
115      binder::Status destroyAppProfiles(const std::string& packageName);
116  
117      binder::Status createProfileSnapshot(int32_t appId, const std::string& packageName,
118              const std::string& profileName, const std::string& classpath, bool* _aidl_return);
119      binder::Status destroyProfileSnapshot(const std::string& packageName,
120              const std::string& profileName);
121  
122      binder::Status idmap(const std::string& targetApkPath, const std::string& overlayApkPath,
123              int32_t uid);
124      binder::Status removeIdmap(const std::string& overlayApkPath);
125      binder::Status rmPackageDir(const std::string& packageDir);
126      binder::Status markBootComplete(const std::string& instructionSet);
127      binder::Status freeCache(const std::unique_ptr<std::string>& uuid, int64_t targetFreeBytes,
128              int64_t cacheReservedBytes, int32_t flags);
129      binder::Status linkNativeLibraryDirectory(const std::unique_ptr<std::string>& uuid,
130              const std::string& packageName, const std::string& nativeLibPath32, int32_t userId);
131      binder::Status createOatDir(const std::string& oatDir, const std::string& instructionSet);
132      binder::Status linkFile(const std::string& relativePath, const std::string& fromBase,
133              const std::string& toBase);
134      binder::Status moveAb(const std::string& apkPath, const std::string& instructionSet,
135              const std::string& outputPath);
136      binder::Status deleteOdex(const std::string& apkPath, const std::string& instructionSet,
137              const std::unique_ptr<std::string>& outputPath);
138      binder::Status installApkVerity(const std::string& filePath,
139              const ::android::base::unique_fd& verityInput, int32_t contentSize);
140      binder::Status assertFsverityRootHashMatches(const std::string& filePath,
141              const std::vector<uint8_t>& expectedHash);
142      binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
143          const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
144          const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
145      binder::Status hashSecondaryDexFile(const std::string& dexPath,
146          const std::string& packageName, int32_t uid, const std::unique_ptr<std::string>& volumeUuid,
147          int32_t storageFlag, std::vector<uint8_t>* _aidl_return);
148  
149      binder::Status invalidateMounts();
150      binder::Status isQuotaSupported(const std::unique_ptr<std::string>& volumeUuid,
151              bool* _aidl_return);
152  
153      binder::Status prepareAppProfile(const std::string& packageName,
154              int32_t userId, int32_t appId, const std::string& profileName,
155              const std::string& codePath, const std::unique_ptr<std::string>& dexMetadata,
156              bool* _aidl_return);
157  
158      binder::Status migrateLegacyObbData();

java 层的 Installer 通过binder调用的时候,就会调用到上面对应的 native API。

五、Java 侧 Installer

SystemServer 第一个启动就是 Installer 系统服务。回调它的 onStart()方法:

@Override
public void onStart() {
    if (mIsolated) {
        mInstalld = null;
    } else {
        connect();
    }
}

里面调用了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
        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);
    }
}

5.1 调用接口

如: createAppData()、restoreconAppData()方法:

public long createAppData(String uuid, String packageName, int userId, int flags, int appId,
        String seInfo, int targetSdkVersion) throws InstallerException {
    if (!checkBeforeRemote()) return -1;
    try {
        return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo,
                targetSdkVersion);
    } catch (Exception e) {
        throw InstallerException.from(e);
    }
}

public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId,
        String seInfo) throws InstallerException {
    if (!checkBeforeRemote()) return;
    try {
        mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo);
    } catch (Exception e) {
        throw InstallerException.from(e);
    }
}

至此,整个流程基本理清,后续继续分析具体的安装、卸载等流程。

参考

gityuan.com/2016/11/13/…