热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

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

Android系统服务PMSInstalld守护进程(二)-背景PMS中负责应用的安装、卸载工作,是由Installer系统服务来完成的。但Installer也只是java层封装
背景

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](http://aospxref.com/android-10.0.0_r47/xref/frameworks/)/[native](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/)/[cmds](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/cmds/)/[installd](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/cmds/installd/)/[globals.cpp](http://aospxref.com/android-10.0.0_r47/xref/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/
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::publish();
258 if (ret != android::OK) {
259 return ret;
260 }
261 sp 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
34 class BinderService
35 {
36 public:// 提供了两个方法
//注册服务
37 static status_t publish(bool allowIsolated = false,
38 int dumpFlags = IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT) {
39 sp 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 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](http://aospxref.com/android-10.0.0_r47/xref/frameworks/)/[native](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/)/[cmds](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/cmds/)/[installd](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/cmds/installd/)/[InstalldNativeService.h](http://aospxref.com/android-10.0.0_r47/xref/frameworks/native/cmds/installd/InstalldNativeService.h)

virtual status_t dump(int fd, const Vector &args) override;
42  
43   binder::Status createUserData(const std::unique_ptr& uuid, int32_t userId,
44   int32_t userSerial, int32_t flags);
45   binder::Status destroyUserData(const std::unique_ptr& uuid, int32_t userId,
46   int32_t flags);
47  
48   binder::Status createAppData(const std::unique_ptr& 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& 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& uuid,
55   const std::string& packageName, int32_t userId, int32_t flags);
56   binder::Status clearAppData(const std::unique_ptr& uuid,
57   const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
58   binder::Status destroyAppData(const std::unique_ptr& uuid,
59   const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
60  
61   binder::Status fixupAppData(const std::unique_ptr& uuid, int32_t flags);
62  
63   binder::Status snapshotAppData(const std::unique_ptr& 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& 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 &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& uuid,
74   const std::vector& packageNames, int32_t userId, int32_t flags,
75   int32_t appId, const std::vector& ceDataInodes,
76   const std::vector& codePaths, std::vector _aidl_return);
77   binder::Status getUserSize(const std::unique_ptr& uuid,
78   int32_t userId, int32_t flags, const std::vector& appIds,
79   std::vector
_aidl_return);
80   binder::Status getExternalSize(const std::unique_ptr& uuid,
81   int32_t userId, int32_t flags, const std::vector& appIds,
82   std::vector _aidl_return);
83  
84   binder::Status setAppQuota(const std::unique_ptr& uuid,
85   int32_t userId, int32_t appId, int64_t cacheQuota);
86  
87   binder::Status moveCompleteApp(const std::unique_ptr& fromUuid,
88   const std::unique_ptr& 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& packageName, const std::string& instructionSet,
94   int32_t dexoptNeeded, const std::unique_ptr& outputPath, int32_t dexFlags,
95   const std::string& compilerFilter, const std::unique_ptr& uuid,
96   const std::unique_ptr& classLoaderContext,
97   const std::unique_ptr& seInfo, bool downgrade,
98   int32_t targetSdkVersion, const std::unique_ptr& profileName,
99   const std::unique_ptr& dexMetadataPath,
100   const std::unique_ptr& 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& uuid, int64_t targetFreeBytes,
128   int64_t cacheReservedBytes, int32_t flags);
129   binder::Status linkNativeLibraryDirectory(const std::unique_ptr& 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& 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& expectedHash);
142   binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
143   const std::string& packageName, int32_t uid, const std::vector& isa,
144   const std::unique_ptr& 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& volumeUuid,
147   int32_t storageFlag, std::vector
_aidl_return);
148  
149   binder::Status invalidateMounts();
150   binder::Status isQuotaSupported(const std::unique_ptr& 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& 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);
}
}


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

# 参考 

http://gityuan.com/2016/11/13/android-installd/

推荐阅读
author-avatar
天使哥特式
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有