我是靠谱客的博主 贪玩小懒猪,这篇文章主要介绍Android PackageManagerService流程详细分析(二)之installer,现在分享给大家,希望可以做个参考。

本节介绍下pkms与installd之间的联系以及installd服务的具体实现:
这里写图片描述
通过上图可以看出,他们之前的桥梁是installer,下面是installer主要的代码结构:
这里写图片描述

注意两点:
1、函数接口(左):
这里写图片描述

2、LocalSocket通信(右):
这里写图片描述

而服务installd在系统启动的时候,通过解析脚本文件init.rc就完成启动了:
这里写图片描述

installd的代码路径以及结构如下:
这里写图片描述

下面介绍下这两个主要文件具体代码,主要函数及流程如下:
1、installd.c

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
struct cmdinfo { const char *name; unsigned numargs; int (*func)(char **arg, char reply[REPLY_MAX]); }; struct cmdinfo cmds[] = { { "ping", 0, do_ping }, { "install", 3, do_install }, { "dexopt", 3, do_dexopt }, { "movedex", 2, do_move_dex }, { "rmdex", 1, do_rm_dex }, { "remove", 2, do_remove }, { "rename", 2, do_rename }, { "fixuid", 3, do_fixuid }, { "freecache", 1, do_free_cache }, { "rmcache", 2, do_rm_cache }, { "getsize", 5, do_get_size }, { "rmuserdata", 2, do_rm_user_data }, { "movefiles", 0, do_movefiles }, { "linklib", 3, do_linklib }, { "mkuserdata", 3, do_mk_user_data }, { "rmuser", 1, do_rm_user }, { "cloneuserdata", 3, do_clone_user_data }, }; /* Tokenize the command buffer, locate a matching command, * ensure that the required number of arguments are provided, * call the function(), return the result. */ static int execute(int s, char cmd[BUFFER_MAX]) { char reply[REPLY_MAX]; char *arg[TOKEN_MAX+1]; unsigned i; unsigned n = 0; unsigned short count; int ret = -1; // ALOGI("execute('%s')n", cmd); /* default reply is "" */ reply[0] = 0; /* n is number of args (not counting arg[0]) */ // arg[0]为命令名称,命令格式:[name arg1 arg2 arg3 arg4] arg[0] = cmd; // 计算命令参数个数 while (*cmd) { if (isspace(*cmd)) { *cmd++ = 0; n++; arg[n] = cmd; if (n == TOKEN_MAX) { ALOGE("too many argumentsn"); goto done; } } cmd++; } // 根据命令名称匹配命令数组cmds中的命令 for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) { // 命令名称比较 if (!strcmp(cmds[i].name,arg[0])) { // 判断该命令的参数个数是否满足要求 if (n != cmds[i].numargs) { ALOGE("%s requires %d arguments (%d given)n", cmds[i].name, cmds[i].numargs, n); } else { // 调用命令执行函数,执行命令 ret = cmds[i].func(arg + 1, reply); } goto done; } } ALOGE("unsupported command '%s'n", arg[0]); done: // 格式化返回结果 if (reply[0]) { n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); } else { n = snprintf(cmd, BUFFER_MAX, "%d", ret); } if (n > BUFFER_MAX) n = BUFFER_MAX; // 返回结果数据长度 count = n; // ALOGI("reply: '%s'n", cmd); // 写结果数据长度 if (writex(s, &count, sizeof(count))) return -1; // 写结果数据 if (writex(s, cmd, count)) return -1; return 0; } int initialize_globals() { // Get the android data directory. // 从环境变量中读取数据存储目录,在Android启动脚本init.rc中配置了ANDROID_DATA // 环境变量,export ANDROID_DATA /data ,因此变量android_data_dir=/data/ if (get_path_from_env(&android_data_dir, "ANDROID_DATA") < 0) { return -1; } // Get the android app directory. // 得到应用程序安装目录android_app_dir=/data/app/ if (copy_and_append(&android_app_dir, &android_data_dir, APP_SUBDIR) < 0) { return -1; } // Get the android protected app directory. // 得到应用程序私有目录android_app_private_dir=/data/app-private/ if (copy_and_append(&android_app_private_dir, &android_data_dir, PRIVATE_APP_SUBDIR) < 0) { return -1; } // Get the android app native library directory. if (copy_and_append(&android_app_lib_dir, &android_data_dir, APP_LIB_SUBDIR) < 0) { return -1; } // Get the sd-card ASEC mount point. // 从环境变量中取得sd-card ASEC的挂载点,在启动脚本init.rc中也有配置:export ASEC_MOUNTPOINT /mnt/asec // 因此android_asec_dir=/mnt/asec/ if (get_path_from_env(&android_asec_dir, "ASEC_MOUNTPOINT") < 0) { return -1; } // Get the android media directory. if (copy_and_append(&android_media_dir, &android_data_dir, MEDIA_SUBDIR) < 0) { return -1; } // Take note of the system and vendor directories. android_system_dirs.count = 2; // 定义android_system_dirs变量并分配存储空间 android_system_dirs.dirs = calloc(android_system_dirs.count, sizeof(dir_rec_t)); if (android_system_dirs.dirs == NULL) { ALOGE("Couldn't allocate array for dirs; abortingn"); return -1; } // system // 从环境变量中取得android根目录,在启动脚本init.rc中也有配置:export ANDROID_ROOT /system // 因此android_system_dirs.dirs[0]=/system/ if (get_path_from_env(&android_system_dirs.dirs[0], "ANDROID_ROOT") < 0) { free_globals(); return -1; } // append "app/" to dirs[0] char *system_app_path = build_string2(android_system_dirs.dirs[0].path, APP_SUBDIR); // android_system_dirs.dirs[0]=/system/app/ android_system_dirs.dirs[0].path = system_app_path; android_system_dirs.dirs[0].len = strlen(system_app_path); // vendor // TODO replace this with an environment variable (doesn't exist yet) android_system_dirs.dirs[1].path = "/vendor/app/"; android_system_dirs.dirs[1].len = strlen(android_system_dirs.dirs[1].path); return 0; } int initialize_directories() { int res = -1; // Read current filesystem layout version to handle upgrade paths char version_path[PATH_MAX]; snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path); int oldVersion; if (fs_read_atomic_int(version_path, &oldVersion) == -1) { oldVersion = 0; } int version = oldVersion; // /data/user char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX); // /data/data char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX); // /data/user/0 char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0"); if (!user_data_dir || !legacy_data_dir || !primary_data_dir) { goto fail; } // Make the /data/user directory if necessary if (access(user_data_dir, R_OK) < 0) { if (mkdir(user_data_dir, 0711) < 0) { goto fail; } // 修改目录权限及所有属性 if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) { goto fail; } if (chmod(user_data_dir, 0711) < 0) { goto fail; } } // Make the /data/user/0 symlink to /data/data if necessary if (access(primary_data_dir, R_OK) < 0) { if (symlink(legacy_data_dir, primary_data_dir)) { goto fail; } } if (version == 0) { // Introducing multi-user, so migrate /data/media contents into /data/media/0 ALOGD("Upgrading /data/media for multi-user"); // Ensure /data/media if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // /data/media.tmp char media_tmp_dir[PATH_MAX]; snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path); // Only copy when upgrade not already in progress if (access(media_tmp_dir, F_OK) == -1) { if (rename(android_media_dir.path, media_tmp_dir) == -1) { ALOGE("Failed to move legacy media path: %s", strerror(errno)); goto fail; } } // Create /data/media again if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // /data/media/0 char owner_media_dir[PATH_MAX]; snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path); // Move any owner data into place if (access(media_tmp_dir, F_OK) == 0) { if (rename(media_tmp_dir, owner_media_dir) == -1) { ALOGE("Failed to move owner media path: %s", strerror(errno)); goto fail; } } // Ensure media directories for any existing users DIR *dir; struct dirent *dirent; char user_media_dir[PATH_MAX]; dir = opendir(user_data_dir); if (dir != NULL) { while ((dirent = readdir(dir))) { if (dirent->d_type == DT_DIR) { const char *name = dirent->d_name; // skip "." and ".." if (name[0] == '.') { if (name[1] == 0) continue; if ((name[1] == '.') && (name[2] == 0)) continue; } // /data/media/<user_id> snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name); if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } } } closedir(dir); } version = 1; } // /data/media/obb char media_obb_dir[PATH_MAX]; snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path); if (version == 1) { // Introducing /data/media/obb for sharing OBB across users; migrate // any existing OBB files from owner. ALOGD("Upgrading to shared /data/media/obb"); // /data/media/0/Android/obb char owner_obb_path[PATH_MAX]; snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path); // Only move if target doesn't already exist if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) { if (rename(owner_obb_path, media_obb_dir) == -1) { ALOGE("Failed to move OBB from owner: %s", strerror(errno)); goto fail; } } version = 2; } if (ensure_media_user_dirs(0) == -1) { ALOGE("Failed to setup media for user 0"); goto fail; } if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) { goto fail; } // Persist layout version if changed if (version != oldVersion) { if (fs_write_atomic_int(version_path, version) == -1) { ALOGE("Failed to save version to %s: %s", version_path, strerror(errno)); goto fail; } } // Success! res = 0; fail: free(user_data_dir); free(legacy_data_dir); free(primary_data_dir); return res; } int main(const int argc, const char *argv[]) { char buf[BUFFER_MAX]; struct sockaddr addr; socklen_t alen; int lsocket, s, count; ALOGI("installd firing upn"); //初始化一些全局变量 if (initialize_globals() < 0) { ALOGE("Could not initialize globals; exiting.n"); exit(1); } //初始化安装目录 if (initialize_directories() < 0) { ALOGE("Could not create directories; exiting.n"); exit(1); } drop_privileges(); //取得installd套接字的句柄,系统中的所有socket以ANDROID_SOCKET_[name]为键, //socket句柄为值的方式保存在//环境变量中 lsocket = android_get_control_socket(SOCKET_PATH); if (lsocket < 0) { ALOGE("Failed to get socket from environment: %sn", strerror(errno)); exit(1); } if (listen(lsocket, 5)) { ALOGE("Listen on socket failed: %sn", strerror(errno)); exit(1); } //修改该socket的属性 fcntl(lsocket, F_SETFD, FD_CLOEXEC); for (;;) { alen = sizeof(addr); //循环等待接收客户端的请求 s = accept(lsocket, &addr, &alen); if (s < 0) { ALOGE("Accept failed: %sn", strerror(errno)); continue; } //接收到客户端的请求后,修改客户端请求socket属性 fcntl(s, F_SETFD, FD_CLOEXEC); ALOGI("new connectionn"); //循环读取客户端socket中的内容,直到读取内容为空为止 //客户端发送的数据格式:| 数据长度 | 数据内容 | for (;;) { unsigned short count; //读取数据长度,读取成功返回0,反之返回-1 if (readx(s, &count, sizeof(count))) { ALOGE("failed to read sizen"); break; } //如果读取成功,但是读取的数据长度超出1024字节,同样停止读取 if ((count < 1) || (count >= BUFFER_MAX)) { ALOGE("invalid size %dn", count); break; } //读取数据内容,读取成功返回0,反之返回-1 if (readx(s, buf, count)) { ALOGE("failed to read commandn"); break; } buf[count] = 0; //执行客户端发送过来的命令 if (execute(s, buf)) break; } ALOGI("closing connectionn"); //执行完客户端的请求后,关闭该socket连接,继续进入接收请求模式 close(s); } return 0; }

2、commands.c
//主要包括安装,卸载,apk优化

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
int install(const char *pkgname, uid_t uid, gid_t gid) { char pkgdir[PKG_PATH_MAX]; char libsymlink[PKG_PATH_MAX]; char applibdir[PKG_PATH_MAX]; struct stat libStat; // 权限判断 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) { ALOGE("invalid uid/gid: %d %dn", uid, gid); return -1; } // 组合应用程序安装目录pkgdir=/data/data/应用程序包名 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) { ALOGE("cannot create package pathn"); return -1; } // 组合应用程序库目录libdir=/data/data/应用程序包名/lib if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) { ALOGE("cannot create package lib symlink origin pathn"); return -1; } if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) { ALOGE("cannot create package lib symlink dest pathn"); return -1; } // 创建目录pkgdir=/data/data/应用程序包名 if (mkdir(pkgdir, 0751) < 0) { ALOGE("cannot create dir '%s': %sn", pkgdir, strerror(errno)); return -1; } // 修改/data/data/应用程序包名目录的权限 if (chmod(pkgdir, 0751) < 0) { ALOGE("cannot chmod dir '%s': %sn", pkgdir, strerror(errno)); unlink(pkgdir); return -1; } if (lstat(libsymlink, &libStat) < 0) { if (errno != ENOENT) { ALOGE("couldn't stat lib dir: %sn", strerror(errno)); return -1; } } else { if (S_ISDIR(libStat.st_mode)) { if (delete_dir_contents(libsymlink, 1, 0) < 0) { ALOGE("couldn't delete lib directory during install for: %s", libsymlink); return -1; } } else if (S_ISLNK(libStat.st_mode)) { if (unlink(libsymlink) < 0) { ALOGE("couldn't unlink lib directory during install for: %s", libsymlink); return -1; } } } if (symlink(applibdir, libsymlink) < 0) { ALOGE("couldn't symlink directory '%s' -> '%s': %sn", libsymlink, applibdir, strerror(errno)); unlink(pkgdir); return -1; } #ifdef HAVE_SELINUX if (selinux_android_setfilecon(pkgdir, pkgname, uid) < 0) { ALOGE("cannot setfilecon dir '%s': %sn", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); return -1; } #endif if (chown(pkgdir, uid, gid) < 0) { ALOGE("cannot chown dir '%s': %sn", pkgdir, strerror(errno)); unlink(libsymlink); unlink(pkgdir); return -1; } return 0; } int uninstall(const char *pkgname, uid_t persona) { char pkgdir[PKG_PATH_MAX]; // 根据包名得到应用程序安装目录路径 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, persona)) return -1; /* delete contents AND directory, no exceptions */ // 删除安装目录及目录下的文件 return delete_dir_contents(pkgdir, 1, NULL); } static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name, const char* dexopt_flags) { static const char* DEX_OPT_BIN = "/system/bin/dexopt"; static const int MAX_INT_LEN = 12; // '-'+10dig+'' -OR- 0x+8dig char zip_num[MAX_INT_LEN]; char odex_num[MAX_INT_LEN]; sprintf(zip_num, "%d", zip_fd); sprintf(odex_num, "%d", odex_fd); // 调用/system/bin/dexopt工具来优化apk文件 execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name, dexopt_flags, (char*) NULL); ALOGE("execl(%s) failed: %sn", DEX_OPT_BIN, strerror(errno)); }

最后

以上就是贪玩小懒猪最近收集整理的关于Android PackageManagerService流程详细分析(二)之installer的全部内容,更多相关Android内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(109)

评论列表共有 0 条评论

立即
投稿
返回
顶部