• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.pm;
18 
19 import android.annotation.Nullable;
20 import android.content.Context;
21 import android.content.pm.PackageStats;
22 import android.os.Build;
23 import android.text.TextUtils;
24 import android.util.Slog;
25 
26 import dalvik.system.VMRuntime;
27 
28 import com.android.internal.os.InstallerConnection;
29 import com.android.server.SystemService;
30 
31 public final class Installer extends SystemService {
32     private static final String TAG = "Installer";
33 
34     private final InstallerConnection mInstaller;
35 
Installer(Context context)36     public Installer(Context context) {
37         super(context);
38         mInstaller = new InstallerConnection();
39     }
40 
41     @Override
onStart()42     public void onStart() {
43         Slog.i(TAG, "Waiting for installd to be ready.");
44         mInstaller.waitForConnection();
45     }
46 
escapeNull(String arg)47     private static String escapeNull(String arg) {
48         if (TextUtils.isEmpty(arg)) {
49             return "!";
50         } else {
51             if (arg.indexOf('\0') != -1 || arg.indexOf(' ') != -1) {
52                 throw new IllegalArgumentException(arg);
53             }
54             return arg;
55         }
56     }
57 
58     @Deprecated
install(String name, int uid, int gid, String seinfo)59     public int install(String name, int uid, int gid, String seinfo) {
60         return install(null, name, uid, gid, seinfo);
61     }
62 
install(String uuid, String name, int uid, int gid, String seinfo)63     public int install(String uuid, String name, int uid, int gid, String seinfo) {
64         StringBuilder builder = new StringBuilder("install");
65         builder.append(' ');
66         builder.append(escapeNull(uuid));
67         builder.append(' ');
68         builder.append(name);
69         builder.append(' ');
70         builder.append(uid);
71         builder.append(' ');
72         builder.append(gid);
73         builder.append(' ');
74         builder.append(seinfo != null ? seinfo : "!");
75         return mInstaller.execute(builder.toString());
76     }
77 
dexopt(String apkPath, int uid, boolean isPublic, String instructionSet, int dexoptNeeded)78     public int dexopt(String apkPath, int uid, boolean isPublic,
79             String instructionSet, int dexoptNeeded) {
80         return dexopt(apkPath, uid, isPublic, instructionSet, dexoptNeeded, true);
81     }
82 
dexopt(String apkPath, int uid, boolean isPublic, String instructionSet, int dexoptNeeded, boolean bootComplete)83     public int dexopt(String apkPath, int uid, boolean isPublic,
84             String instructionSet, int dexoptNeeded, boolean bootComplete) {
85         if (!isValidInstructionSet(instructionSet)) {
86             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
87             return -1;
88         }
89 
90         return mInstaller.dexopt(apkPath, uid, isPublic, instructionSet, dexoptNeeded,
91                 bootComplete);
92     }
93 
dexopt(String apkPath, int uid, boolean isPublic, String pkgName, String instructionSet, int dexoptNeeded, boolean vmSafeMode, boolean debuggable, @Nullable String outputPath)94     public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
95             String instructionSet, int dexoptNeeded, boolean vmSafeMode,
96             boolean debuggable, @Nullable String outputPath) {
97         return dexopt(apkPath, uid, isPublic, pkgName, instructionSet, dexoptNeeded, vmSafeMode,
98                 debuggable, outputPath, true);
99     }
100 
dexopt(String apkPath, int uid, boolean isPublic, String pkgName, String instructionSet, int dexoptNeeded, boolean vmSafeMode, boolean debuggable, @Nullable String outputPath, boolean bootComplete)101     public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
102             String instructionSet, int dexoptNeeded, boolean vmSafeMode,
103             boolean debuggable, @Nullable String outputPath, boolean bootComplete) {
104         if (!isValidInstructionSet(instructionSet)) {
105             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
106             return -1;
107         }
108         return mInstaller.dexopt(apkPath, uid, isPublic, pkgName,
109                 instructionSet, dexoptNeeded, vmSafeMode,
110                 debuggable, outputPath, bootComplete);
111     }
112 
idmap(String targetApkPath, String overlayApkPath, int uid)113     public int idmap(String targetApkPath, String overlayApkPath, int uid) {
114         StringBuilder builder = new StringBuilder("idmap");
115         builder.append(' ');
116         builder.append(targetApkPath);
117         builder.append(' ');
118         builder.append(overlayApkPath);
119         builder.append(' ');
120         builder.append(uid);
121         return mInstaller.execute(builder.toString());
122     }
123 
movedex(String srcPath, String dstPath, String instructionSet)124     public int movedex(String srcPath, String dstPath, String instructionSet) {
125         if (!isValidInstructionSet(instructionSet)) {
126             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
127             return -1;
128         }
129 
130         StringBuilder builder = new StringBuilder("movedex");
131         builder.append(' ');
132         builder.append(srcPath);
133         builder.append(' ');
134         builder.append(dstPath);
135         builder.append(' ');
136         builder.append(instructionSet);
137         return mInstaller.execute(builder.toString());
138     }
139 
rmdex(String codePath, String instructionSet)140     public int rmdex(String codePath, String instructionSet) {
141         if (!isValidInstructionSet(instructionSet)) {
142             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
143             return -1;
144         }
145 
146         StringBuilder builder = new StringBuilder("rmdex");
147         builder.append(' ');
148         builder.append(codePath);
149         builder.append(' ');
150         builder.append(instructionSet);
151         return mInstaller.execute(builder.toString());
152     }
153 
154     /**
155      * Removes packageDir or its subdirectory
156      */
rmPackageDir(String packageDir)157     public int rmPackageDir(String packageDir) {
158         StringBuilder builder = new StringBuilder("rmpackagedir");
159         builder.append(' ');
160         builder.append(packageDir);
161         return mInstaller.execute(builder.toString());
162     }
163 
164     @Deprecated
remove(String name, int userId)165     public int remove(String name, int userId) {
166         return remove(null, name, userId);
167     }
168 
remove(String uuid, String name, int userId)169     public int remove(String uuid, String name, int userId) {
170         StringBuilder builder = new StringBuilder("remove");
171         builder.append(' ');
172         builder.append(escapeNull(uuid));
173         builder.append(' ');
174         builder.append(name);
175         builder.append(' ');
176         builder.append(userId);
177         return mInstaller.execute(builder.toString());
178     }
179 
rename(String oldname, String newname)180     public int rename(String oldname, String newname) {
181         StringBuilder builder = new StringBuilder("rename");
182         builder.append(' ');
183         builder.append(oldname);
184         builder.append(' ');
185         builder.append(newname);
186         return mInstaller.execute(builder.toString());
187     }
188 
189     @Deprecated
fixUid(String name, int uid, int gid)190     public int fixUid(String name, int uid, int gid) {
191         return fixUid(null, name, uid, gid);
192     }
193 
fixUid(String uuid, String name, int uid, int gid)194     public int fixUid(String uuid, String name, int uid, int gid) {
195         StringBuilder builder = new StringBuilder("fixuid");
196         builder.append(' ');
197         builder.append(escapeNull(uuid));
198         builder.append(' ');
199         builder.append(name);
200         builder.append(' ');
201         builder.append(uid);
202         builder.append(' ');
203         builder.append(gid);
204         return mInstaller.execute(builder.toString());
205     }
206 
207     @Deprecated
deleteCacheFiles(String name, int userId)208     public int deleteCacheFiles(String name, int userId) {
209         return deleteCacheFiles(null, name, userId);
210     }
211 
deleteCacheFiles(String uuid, String name, int userId)212     public int deleteCacheFiles(String uuid, String name, int userId) {
213         StringBuilder builder = new StringBuilder("rmcache");
214         builder.append(' ');
215         builder.append(escapeNull(uuid));
216         builder.append(' ');
217         builder.append(name);
218         builder.append(' ');
219         builder.append(userId);
220         return mInstaller.execute(builder.toString());
221     }
222 
223     @Deprecated
deleteCodeCacheFiles(String name, int userId)224     public int deleteCodeCacheFiles(String name, int userId) {
225         return deleteCodeCacheFiles(null, name, userId);
226     }
227 
deleteCodeCacheFiles(String uuid, String name, int userId)228     public int deleteCodeCacheFiles(String uuid, String name, int userId) {
229         StringBuilder builder = new StringBuilder("rmcodecache");
230         builder.append(' ');
231         builder.append(escapeNull(uuid));
232         builder.append(' ');
233         builder.append(name);
234         builder.append(' ');
235         builder.append(userId);
236         return mInstaller.execute(builder.toString());
237     }
238 
239     @Deprecated
createUserData(String name, int uid, int userId, String seinfo)240     public int createUserData(String name, int uid, int userId, String seinfo) {
241         return createUserData(null, name, uid, userId, seinfo);
242     }
243 
createUserData(String uuid, String name, int uid, int userId, String seinfo)244     public int createUserData(String uuid, String name, int uid, int userId, String seinfo) {
245         StringBuilder builder = new StringBuilder("mkuserdata");
246         builder.append(' ');
247         builder.append(escapeNull(uuid));
248         builder.append(' ');
249         builder.append(name);
250         builder.append(' ');
251         builder.append(uid);
252         builder.append(' ');
253         builder.append(userId);
254         builder.append(' ');
255         builder.append(seinfo != null ? seinfo : "!");
256         return mInstaller.execute(builder.toString());
257     }
258 
createUserConfig(int userId)259     public int createUserConfig(int userId) {
260         StringBuilder builder = new StringBuilder("mkuserconfig");
261         builder.append(' ');
262         builder.append(userId);
263         return mInstaller.execute(builder.toString());
264     }
265 
266     @Deprecated
removeUserDataDirs(int userId)267     public int removeUserDataDirs(int userId) {
268         return removeUserDataDirs(null, userId);
269     }
270 
removeUserDataDirs(String uuid, int userId)271     public int removeUserDataDirs(String uuid, int userId) {
272         StringBuilder builder = new StringBuilder("rmuser");
273         builder.append(' ');
274         builder.append(escapeNull(uuid));
275         builder.append(' ');
276         builder.append(userId);
277         return mInstaller.execute(builder.toString());
278     }
279 
copyCompleteApp(String fromUuid, String toUuid, String packageName, String dataAppName, int appId, String seinfo)280     public int copyCompleteApp(String fromUuid, String toUuid, String packageName,
281             String dataAppName, int appId, String seinfo) {
282         StringBuilder builder = new StringBuilder("cpcompleteapp");
283         builder.append(' ');
284         builder.append(escapeNull(fromUuid));
285         builder.append(' ');
286         builder.append(escapeNull(toUuid));
287         builder.append(' ');
288         builder.append(packageName);
289         builder.append(' ');
290         builder.append(dataAppName);
291         builder.append(' ');
292         builder.append(appId);
293         builder.append(' ');
294         builder.append(seinfo);
295         return mInstaller.execute(builder.toString());
296     }
297 
298     @Deprecated
clearUserData(String name, int userId)299     public int clearUserData(String name, int userId) {
300         return clearUserData(null, name, userId);
301     }
302 
clearUserData(String uuid, String name, int userId)303     public int clearUserData(String uuid, String name, int userId) {
304         StringBuilder builder = new StringBuilder("rmuserdata");
305         builder.append(' ');
306         builder.append(escapeNull(uuid));
307         builder.append(' ');
308         builder.append(name);
309         builder.append(' ');
310         builder.append(userId);
311         return mInstaller.execute(builder.toString());
312     }
313 
markBootComplete(String instructionSet)314     public int markBootComplete(String instructionSet) {
315         if (!isValidInstructionSet(instructionSet)) {
316             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
317             return -1;
318         }
319 
320         StringBuilder builder = new StringBuilder("markbootcomplete");
321         builder.append(' ');
322         builder.append(instructionSet);
323         return mInstaller.execute(builder.toString());
324     }
325 
326     @Deprecated
freeCache(long freeStorageSize)327     public int freeCache(long freeStorageSize) {
328         return freeCache(null, freeStorageSize);
329     }
330 
freeCache(String uuid, long freeStorageSize)331     public int freeCache(String uuid, long freeStorageSize) {
332         StringBuilder builder = new StringBuilder("freecache");
333         builder.append(' ');
334         builder.append(escapeNull(uuid));
335         builder.append(' ');
336         builder.append(String.valueOf(freeStorageSize));
337         return mInstaller.execute(builder.toString());
338     }
339 
340     @Deprecated
getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats)341     public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
342             String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats) {
343         return getSizeInfo(null, pkgName, persona, apkPath, libDirPath, fwdLockApkPath, asecPath,
344                 instructionSets, pStats);
345     }
346 
getSizeInfo(String uuid, String pkgName, int persona, String apkPath, String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats)347     public int getSizeInfo(String uuid, String pkgName, int persona, String apkPath,
348             String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets,
349             PackageStats pStats) {
350         for (String instructionSet : instructionSets) {
351             if (!isValidInstructionSet(instructionSet)) {
352                 Slog.e(TAG, "Invalid instruction set: " + instructionSet);
353                 return -1;
354             }
355         }
356 
357         StringBuilder builder = new StringBuilder("getsize");
358         builder.append(' ');
359         builder.append(escapeNull(uuid));
360         builder.append(' ');
361         builder.append(pkgName);
362         builder.append(' ');
363         builder.append(persona);
364         builder.append(' ');
365         builder.append(apkPath);
366         builder.append(' ');
367         // TODO: Extend getSizeInfo to look at the full subdirectory tree,
368         // not just the first level.
369         builder.append(libDirPath != null ? libDirPath : "!");
370         builder.append(' ');
371         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
372         builder.append(' ');
373         builder.append(asecPath != null ? asecPath : "!");
374         builder.append(' ');
375         // TODO: Extend getSizeInfo to look at *all* instrution sets, not
376         // just the primary.
377         builder.append(instructionSets[0]);
378 
379         String s = mInstaller.transact(builder.toString());
380         String res[] = s.split(" ");
381 
382         if ((res == null) || (res.length != 5)) {
383             return -1;
384         }
385         try {
386             pStats.codeSize = Long.parseLong(res[1]);
387             pStats.dataSize = Long.parseLong(res[2]);
388             pStats.cacheSize = Long.parseLong(res[3]);
389             pStats.externalCodeSize = Long.parseLong(res[4]);
390             return Integer.parseInt(res[0]);
391         } catch (NumberFormatException e) {
392             return -1;
393         }
394     }
395 
moveFiles()396     public int moveFiles() {
397         return mInstaller.execute("movefiles");
398     }
399 
400     @Deprecated
linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId)401     public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId) {
402         return linkNativeLibraryDirectory(null, dataPath, nativeLibPath32, userId);
403     }
404 
405     /**
406      * Links the 32 bit native library directory in an application's data directory to the
407      * real location for backward compatibility. Note that no such symlink is created for
408      * 64 bit shared libraries.
409      *
410      * @return -1 on error
411      */
linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, int userId)412     public int linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
413             int userId) {
414         if (dataPath == null) {
415             Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
416             return -1;
417         } else if (nativeLibPath32 == null) {
418             Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
419             return -1;
420         }
421 
422         StringBuilder builder = new StringBuilder("linklib");
423         builder.append(' ');
424         builder.append(escapeNull(uuid));
425         builder.append(' ');
426         builder.append(dataPath);
427         builder.append(' ');
428         builder.append(nativeLibPath32);
429         builder.append(' ');
430         builder.append(userId);
431 
432         return mInstaller.execute(builder.toString());
433     }
434 
435     @Deprecated
restoreconData(String pkgName, String seinfo, int uid)436     public boolean restoreconData(String pkgName, String seinfo, int uid) {
437         return restoreconData(null, pkgName, seinfo, uid);
438     }
439 
restoreconData(String uuid, String pkgName, String seinfo, int uid)440     public boolean restoreconData(String uuid, String pkgName, String seinfo, int uid) {
441         StringBuilder builder = new StringBuilder("restorecondata");
442         builder.append(' ');
443         builder.append(escapeNull(uuid));
444         builder.append(' ');
445         builder.append(pkgName);
446         builder.append(' ');
447         builder.append(seinfo != null ? seinfo : "!");
448         builder.append(' ');
449         builder.append(uid);
450         return (mInstaller.execute(builder.toString()) == 0);
451     }
452 
createOatDir(String oatDir, String dexInstructionSet)453     public int createOatDir(String oatDir, String dexInstructionSet) {
454         StringBuilder builder = new StringBuilder("createoatdir");
455         builder.append(' ');
456         builder.append(oatDir);
457         builder.append(' ');
458         builder.append(dexInstructionSet);
459         return mInstaller.execute(builder.toString());
460     }
461 
462 
linkFile(String relativePath, String fromBase, String toBase)463     public int linkFile(String relativePath, String fromBase, String toBase) {
464         StringBuilder builder = new StringBuilder("linkfile");
465         builder.append(' ');
466         builder.append(relativePath);
467         builder.append(' ');
468         builder.append(fromBase);
469         builder.append(' ');
470         builder.append(toBase);
471         return mInstaller.execute(builder.toString());
472     }
473 
474     /**
475      * Returns true iff. {@code instructionSet} is a valid instruction set.
476      */
isValidInstructionSet(String instructionSet)477     private static boolean isValidInstructionSet(String instructionSet) {
478         if (instructionSet == null) {
479             return false;
480         }
481 
482         for (String abi : Build.SUPPORTED_ABIS) {
483             if (instructionSet.equals(VMRuntime.getInstructionSet(abi))) {
484                 return true;
485             }
486         }
487 
488         return false;
489     }
490 }
491