• 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.content.Context;
20 import android.content.pm.PackageStats;
21 import android.os.Build;
22 import android.util.Slog;
23 import dalvik.system.VMRuntime;
24 
25 import com.android.internal.os.InstallerConnection;
26 import com.android.server.SystemService;
27 
28 public final class Installer extends SystemService {
29     private static final String TAG = "Installer";
30 
31     private final InstallerConnection mInstaller;
32 
Installer(Context context)33     public Installer(Context context) {
34         super(context);
35         mInstaller = new InstallerConnection();
36     }
37 
38     @Override
onStart()39     public void onStart() {
40         Slog.i(TAG, "Waiting for installd to be ready.");
41         ping();
42     }
43 
install(String name, int uid, int gid, String seinfo)44     public int install(String name, int uid, int gid, String seinfo) {
45         StringBuilder builder = new StringBuilder("install");
46         builder.append(' ');
47         builder.append(name);
48         builder.append(' ');
49         builder.append(uid);
50         builder.append(' ');
51         builder.append(gid);
52         builder.append(' ');
53         builder.append(seinfo != null ? seinfo : "!");
54         return mInstaller.execute(builder.toString());
55     }
56 
patchoat(String apkPath, int uid, boolean isPublic, String pkgName, String instructionSet)57     public int patchoat(String apkPath, int uid, boolean isPublic, String pkgName,
58             String instructionSet) {
59         if (!isValidInstructionSet(instructionSet)) {
60             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
61             return -1;
62         }
63 
64         return mInstaller.patchoat(apkPath, uid, isPublic, pkgName, instructionSet);
65     }
66 
patchoat(String apkPath, int uid, boolean isPublic, String instructionSet)67     public int patchoat(String apkPath, int uid, boolean isPublic, String instructionSet) {
68         if (!isValidInstructionSet(instructionSet)) {
69             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
70             return -1;
71         }
72 
73         return mInstaller.patchoat(apkPath, uid, isPublic, instructionSet);
74     }
75 
dexopt(String apkPath, int uid, boolean isPublic, String instructionSet)76     public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
77         if (!isValidInstructionSet(instructionSet)) {
78             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
79             return -1;
80         }
81 
82         return mInstaller.dexopt(apkPath, uid, isPublic, instructionSet);
83     }
84 
dexopt(String apkPath, int uid, boolean isPublic, String pkgName, String instructionSet, boolean vmSafeMode)85     public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
86             String instructionSet, boolean vmSafeMode) {
87         if (!isValidInstructionSet(instructionSet)) {
88             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
89             return -1;
90         }
91 
92         return mInstaller.dexopt(apkPath, uid, isPublic, pkgName, instructionSet, vmSafeMode);
93     }
94 
idmap(String targetApkPath, String overlayApkPath, int uid)95     public int idmap(String targetApkPath, String overlayApkPath, int uid) {
96         StringBuilder builder = new StringBuilder("idmap");
97         builder.append(' ');
98         builder.append(targetApkPath);
99         builder.append(' ');
100         builder.append(overlayApkPath);
101         builder.append(' ');
102         builder.append(uid);
103         return mInstaller.execute(builder.toString());
104     }
105 
movedex(String srcPath, String dstPath, String instructionSet)106     public int movedex(String srcPath, String dstPath, String instructionSet) {
107         if (!isValidInstructionSet(instructionSet)) {
108             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
109             return -1;
110         }
111 
112         StringBuilder builder = new StringBuilder("movedex");
113         builder.append(' ');
114         builder.append(srcPath);
115         builder.append(' ');
116         builder.append(dstPath);
117         builder.append(' ');
118         builder.append(instructionSet);
119         return mInstaller.execute(builder.toString());
120     }
121 
rmdex(String codePath, String instructionSet)122     public int rmdex(String codePath, String instructionSet) {
123         if (!isValidInstructionSet(instructionSet)) {
124             Slog.e(TAG, "Invalid instruction set: " + instructionSet);
125             return -1;
126         }
127 
128         StringBuilder builder = new StringBuilder("rmdex");
129         builder.append(' ');
130         builder.append(codePath);
131         builder.append(' ');
132         builder.append(instructionSet);
133         return mInstaller.execute(builder.toString());
134     }
135 
remove(String name, int userId)136     public int remove(String name, int userId) {
137         StringBuilder builder = new StringBuilder("remove");
138         builder.append(' ');
139         builder.append(name);
140         builder.append(' ');
141         builder.append(userId);
142         return mInstaller.execute(builder.toString());
143     }
144 
rename(String oldname, String newname)145     public int rename(String oldname, String newname) {
146         StringBuilder builder = new StringBuilder("rename");
147         builder.append(' ');
148         builder.append(oldname);
149         builder.append(' ');
150         builder.append(newname);
151         return mInstaller.execute(builder.toString());
152     }
153 
fixUid(String name, int uid, int gid)154     public int fixUid(String name, int uid, int gid) {
155         StringBuilder builder = new StringBuilder("fixuid");
156         builder.append(' ');
157         builder.append(name);
158         builder.append(' ');
159         builder.append(uid);
160         builder.append(' ');
161         builder.append(gid);
162         return mInstaller.execute(builder.toString());
163     }
164 
deleteCacheFiles(String name, int userId)165     public int deleteCacheFiles(String name, int userId) {
166         StringBuilder builder = new StringBuilder("rmcache");
167         builder.append(' ');
168         builder.append(name);
169         builder.append(' ');
170         builder.append(userId);
171         return mInstaller.execute(builder.toString());
172     }
173 
deleteCodeCacheFiles(String name, int userId)174     public int deleteCodeCacheFiles(String name, int userId) {
175         StringBuilder builder = new StringBuilder("rmcodecache");
176         builder.append(' ');
177         builder.append(name);
178         builder.append(' ');
179         builder.append(userId);
180         return mInstaller.execute(builder.toString());
181     }
182 
createUserData(String name, int uid, int userId, String seinfo)183     public int createUserData(String name, int uid, int userId, String seinfo) {
184         StringBuilder builder = new StringBuilder("mkuserdata");
185         builder.append(' ');
186         builder.append(name);
187         builder.append(' ');
188         builder.append(uid);
189         builder.append(' ');
190         builder.append(userId);
191         builder.append(' ');
192         builder.append(seinfo != null ? seinfo : "!");
193         return mInstaller.execute(builder.toString());
194     }
195 
createUserConfig(int userId)196     public int createUserConfig(int userId) {
197         StringBuilder builder = new StringBuilder("mkuserconfig");
198         builder.append(' ');
199         builder.append(userId);
200         return mInstaller.execute(builder.toString());
201     }
202 
removeUserDataDirs(int userId)203     public int removeUserDataDirs(int userId) {
204         StringBuilder builder = new StringBuilder("rmuser");
205         builder.append(' ');
206         builder.append(userId);
207         return mInstaller.execute(builder.toString());
208     }
209 
clearUserData(String name, int userId)210     public int clearUserData(String name, int userId) {
211         StringBuilder builder = new StringBuilder("rmuserdata");
212         builder.append(' ');
213         builder.append(name);
214         builder.append(' ');
215         builder.append(userId);
216         return mInstaller.execute(builder.toString());
217     }
218 
ping()219     public boolean ping() {
220         if (mInstaller.execute("ping") < 0) {
221             return false;
222         } else {
223             return true;
224         }
225     }
226 
freeCache(long freeStorageSize)227     public int freeCache(long freeStorageSize) {
228         StringBuilder builder = new StringBuilder("freecache");
229         builder.append(' ');
230         builder.append(String.valueOf(freeStorageSize));
231         return mInstaller.execute(builder.toString());
232     }
233 
getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath, String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats)234     public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
235             String fwdLockApkPath, String asecPath, String[] instructionSets, PackageStats pStats) {
236         for (String instructionSet : instructionSets) {
237             if (!isValidInstructionSet(instructionSet)) {
238                 Slog.e(TAG, "Invalid instruction set: " + instructionSet);
239                 return -1;
240             }
241         }
242 
243         StringBuilder builder = new StringBuilder("getsize");
244         builder.append(' ');
245         builder.append(pkgName);
246         builder.append(' ');
247         builder.append(persona);
248         builder.append(' ');
249         builder.append(apkPath);
250         builder.append(' ');
251         // TODO: Extend getSizeInfo to look at the full subdirectory tree,
252         // not just the first level.
253         builder.append(libDirPath != null ? libDirPath : "!");
254         builder.append(' ');
255         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
256         builder.append(' ');
257         builder.append(asecPath != null ? asecPath : "!");
258         builder.append(' ');
259         // TODO: Extend getSizeInfo to look at *all* instrution sets, not
260         // just the primary.
261         builder.append(instructionSets[0]);
262 
263         String s = mInstaller.transact(builder.toString());
264         String res[] = s.split(" ");
265 
266         if ((res == null) || (res.length != 5)) {
267             return -1;
268         }
269         try {
270             pStats.codeSize = Long.parseLong(res[1]);
271             pStats.dataSize = Long.parseLong(res[2]);
272             pStats.cacheSize = Long.parseLong(res[3]);
273             pStats.externalCodeSize = Long.parseLong(res[4]);
274             return Integer.parseInt(res[0]);
275         } catch (NumberFormatException e) {
276             return -1;
277         }
278     }
279 
moveFiles()280     public int moveFiles() {
281         return mInstaller.execute("movefiles");
282     }
283 
284     /**
285      * Links the 32 bit native library directory in an application's data directory to the
286      * real location for backward compatibility. Note that no such symlink is created for
287      * 64 bit shared libraries.
288      *
289      * @return -1 on error
290      */
linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId)291     public int linkNativeLibraryDirectory(String dataPath, String nativeLibPath32, int userId) {
292         if (dataPath == null) {
293             Slog.e(TAG, "linkNativeLibraryDirectory dataPath is null");
294             return -1;
295         } else if (nativeLibPath32 == null) {
296             Slog.e(TAG, "linkNativeLibraryDirectory nativeLibPath is null");
297             return -1;
298         }
299 
300         StringBuilder builder = new StringBuilder("linklib ");
301         builder.append(dataPath);
302         builder.append(' ');
303         builder.append(nativeLibPath32);
304         builder.append(' ');
305         builder.append(userId);
306 
307         return mInstaller.execute(builder.toString());
308     }
309 
restoreconData(String pkgName, String seinfo, int uid)310     public boolean restoreconData(String pkgName, String seinfo, int uid) {
311         StringBuilder builder = new StringBuilder("restorecondata");
312         builder.append(' ');
313         builder.append(pkgName);
314         builder.append(' ');
315         builder.append(seinfo != null ? seinfo : "!");
316         builder.append(' ');
317         builder.append(uid);
318         return (mInstaller.execute(builder.toString()) == 0);
319     }
320 
321     /**
322      * Returns true iff. {@code instructionSet} is a valid instruction set.
323      */
isValidInstructionSet(String instructionSet)324     private static boolean isValidInstructionSet(String instructionSet) {
325         if (instructionSet == null) {
326             return false;
327         }
328 
329         for (String abi : Build.SUPPORTED_ABIS) {
330             if (instructionSet.equals(VMRuntime.getInstructionSet(abi))) {
331                 return true;
332             }
333         }
334 
335         return false;
336     }
337 }
338