PMS 中负责应用的安装、卸载工作,是由 Installer
系统服务来完成的。但 Installer也只是java层封装,真正干活是installd守护进程
的Binder服务: InstalldNativeService
。
installd
进程 具有root
权限,pms的SystemServer进程只有 system
权限。
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()
。
/frameworks/native/cmds/installd/installd.cpp
int main(const int argc, char *argv[]) { 239 return android::installd::installd_main(argc, argv); 240 }
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 }
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
258 if (ret != android::OK) {
259 return ret;
260 }
261 sp
// 内部通过 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
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
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
42
43 binder::Status createUserData(const std::unique_ptr
44 int32_t userSerial, int32_t flags);
45 binder::Status destroyUserData(const std::unique_ptr
46 int32_t flags);
47
48 binder::Status createAppData(const std::unique_ptr
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
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
55 const std::string& packageName, int32_t userId, int32_t flags);
56 binder::Status clearAppData(const std::unique_ptr
57 const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
58 binder::Status destroyAppData(const std::unique_ptr
59 const std::string& packageName, int32_t userId, int32_t flags, int64_t ceDataInode);
60
61 binder::Status fixupAppData(const std::unique_ptr
62
63 binder::Status snapshotAppData(const std::unique_ptr
64 const std::string& packageName, const int32_t user, const int32_t snapshotId,
65 int32_t storageFlags, int64_t
66 binder::Status restoreAppDataSnapshot(const std::unique_ptr
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
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
74 const std::vector
75 int32_t appId, const std::vector
76 const std::vector
77 binder::Status getUserSize(const std::unique_ptr
78 int32_t userId, int32_t flags, const std::vector
79 std::vector
80 binder::Status getExternalSize(const std::unique_ptr
81 int32_t userId, int32_t flags, const std::vector
82 std::vector
83
84 binder::Status setAppQuota(const std::unique_ptr
85 int32_t userId, int32_t appId, int64_t cacheQuota);
86
87 binder::Status moveCompleteApp(const std::unique_ptr
88 const std::unique_ptr
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
94 int32_t dexoptNeeded, const std::unique_ptr
95 const std::string& compilerFilter, const std::unique_ptr
96 const std::unique_ptr
97 const std::unique_ptr
98 int32_t targetSdkVersion, const std::unique_ptr
99 const std::unique_ptr
100 const std::unique_ptr
101
102 binder::Status compileLayouts(const std::string& apkPath, const std::string& packageName,
103 const std::string& outDexFile, int uid, bool
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
128 int64_t cacheReservedBytes, int32_t flags);
129 binder::Status linkNativeLibraryDirectory(const std::unique_ptr
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
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
142 binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
143 const std::string& packageName, int32_t uid, const std::vector
144 const std::unique_ptr
145 binder::Status hashSecondaryDexFile(const std::string& dexPath,
146 const std::string& packageName, int32_t uid, const std::unique_ptr
147 int32_t storageFlag, std::vector
148
149 binder::Status invalidateMounts();
150 binder::Status isQuotaSupported(const std::unique_ptr
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
156 bool
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/