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.util.Slog;
24 
25 import com.android.internal.os.InstallerConnection;
26 import com.android.internal.os.InstallerConnection.InstallerException;
27 import com.android.server.SystemService;
28 
29 import dalvik.system.VMRuntime;
30 
31 import java.util.Arrays;
32 
33 public final class Installer extends SystemService {
34     private static final String TAG = "Installer";
35 
36     /* ***************************************************************************
37      * IMPORTANT: These values are passed to native code. Keep them in sync with
38      * frameworks/native/cmds/installd/installd.h
39      * **************************************************************************/
40     /** Application should be visible to everyone */
41     public static final int DEXOPT_PUBLIC         = 1 << 1;
42     /** Application wants to run in VM safe mode */
43     public static final int DEXOPT_SAFEMODE       = 1 << 2;
44     /** Application wants to allow debugging of its code */
45     public static final int DEXOPT_DEBUGGABLE     = 1 << 3;
46     /** The system boot has finished */
47     public static final int DEXOPT_BOOTCOMPLETE   = 1 << 4;
48     /** Hint that the dexopt type is profile-guided. */
49     public static final int DEXOPT_PROFILE_GUIDED = 1 << 5;
50     /** This is an OTA update dexopt */
51     public static final int DEXOPT_OTA            = 1 << 6;
52 
53     // NOTE: keep in sync with installd
54     public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
55     public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9;
56 
57     private final InstallerConnection mInstaller;
58 
Installer(Context context)59     public Installer(Context context) {
60         super(context);
61         mInstaller = new InstallerConnection();
62     }
63 
64     /**
65      * Yell loudly if someone tries making future calls while holding a lock on
66      * the given object.
67      */
setWarnIfHeld(Object warnIfHeld)68     public void setWarnIfHeld(Object warnIfHeld) {
69         mInstaller.setWarnIfHeld(warnIfHeld);
70     }
71 
72     @Override
onStart()73     public void onStart() {
74         Slog.i(TAG, "Waiting for installd to be ready.");
75         mInstaller.waitForConnection();
76     }
77 
createAppData(String uuid, String pkgname, int userid, int flags, int appid, String seinfo, int targetSdkVersion)78     public void createAppData(String uuid, String pkgname, int userid, int flags, int appid,
79             String seinfo, int targetSdkVersion) throws InstallerException {
80         mInstaller.execute("create_app_data", uuid, pkgname, userid, flags, appid, seinfo,
81             targetSdkVersion);
82     }
83 
restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid, String seinfo)84     public void restoreconAppData(String uuid, String pkgname, int userid, int flags, int appid,
85             String seinfo) throws InstallerException {
86         mInstaller.execute("restorecon_app_data", uuid, pkgname, userid, flags, appid,
87                 seinfo);
88     }
89 
migrateAppData(String uuid, String pkgname, int userid, int flags)90     public void migrateAppData(String uuid, String pkgname, int userid, int flags)
91             throws InstallerException {
92         mInstaller.execute("migrate_app_data", uuid, pkgname, userid, flags);
93     }
94 
clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)95     public void clearAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
96             throws InstallerException {
97         mInstaller.execute("clear_app_data", uuid, pkgname, userid, flags, ceDataInode);
98     }
99 
destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)100     public void destroyAppData(String uuid, String pkgname, int userid, int flags, long ceDataInode)
101             throws InstallerException {
102         mInstaller.execute("destroy_app_data", uuid, pkgname, userid, flags, ceDataInode);
103     }
104 
moveCompleteApp(String from_uuid, String to_uuid, String package_name, String data_app_name, int appid, String seinfo, int targetSdkVersion)105     public void moveCompleteApp(String from_uuid, String to_uuid, String package_name,
106             String data_app_name, int appid, String seinfo, int targetSdkVersion)
107             throws InstallerException {
108         mInstaller.execute("move_complete_app", from_uuid, to_uuid, package_name,
109                 data_app_name, appid, seinfo, targetSdkVersion);
110     }
111 
getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode, String codePath, PackageStats stats)112     public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode,
113             String codePath, PackageStats stats) throws InstallerException {
114         final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags,
115                 ceDataInode, codePath);
116         try {
117             stats.codeSize += Long.parseLong(res[1]);
118             stats.dataSize += Long.parseLong(res[2]);
119             stats.cacheSize += Long.parseLong(res[3]);
120         } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
121             throw new InstallerException("Invalid size result: " + Arrays.toString(res));
122         }
123     }
124 
getAppDataInode(String uuid, String pkgname, int userid, int flags)125     public long getAppDataInode(String uuid, String pkgname, int userid, int flags)
126             throws InstallerException {
127         final String[] res = mInstaller.execute("get_app_data_inode", uuid, pkgname, userid, flags);
128         try {
129             return Long.parseLong(res[1]);
130         } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) {
131             throw new InstallerException("Invalid inode result: " + Arrays.toString(res));
132         }
133     }
134 
dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded, int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)135     public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
136             int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)
137             throws InstallerException {
138         assertValidInstructionSet(instructionSet);
139         mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags,
140                 compilerFilter, volumeUuid, sharedLibraries);
141     }
142 
dexopt(String apkPath, int uid, String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries)143     public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
144             int dexoptNeeded, @Nullable String outputPath, int dexFlags,
145             String compilerFilter, String volumeUuid, String sharedLibraries)
146             throws InstallerException {
147         assertValidInstructionSet(instructionSet);
148         mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
149                 outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries);
150     }
151 
mergeProfiles(int uid, String pkgName)152     public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
153         return mInstaller.mergeProfiles(uid, pkgName);
154     }
155 
dumpProfiles(String gid, String packageName, String codePaths)156     public boolean dumpProfiles(String gid, String packageName, String codePaths)
157             throws InstallerException {
158         return mInstaller.dumpProfiles(gid, packageName, codePaths);
159     }
160 
idmap(String targetApkPath, String overlayApkPath, int uid)161     public void idmap(String targetApkPath, String overlayApkPath, int uid)
162             throws InstallerException {
163         mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid);
164     }
165 
rmdex(String codePath, String instructionSet)166     public void rmdex(String codePath, String instructionSet) throws InstallerException {
167         assertValidInstructionSet(instructionSet);
168         mInstaller.execute("rmdex", codePath, instructionSet);
169     }
170 
rmPackageDir(String packageDir)171     public void rmPackageDir(String packageDir) throws InstallerException {
172         mInstaller.execute("rmpackagedir", packageDir);
173     }
174 
clearAppProfiles(String pkgName)175     public void clearAppProfiles(String pkgName) throws InstallerException {
176         mInstaller.execute("clear_app_profiles", pkgName);
177     }
178 
destroyAppProfiles(String pkgName)179     public void destroyAppProfiles(String pkgName) throws InstallerException {
180         mInstaller.execute("destroy_app_profiles", pkgName);
181     }
182 
createUserData(String uuid, int userId, int userSerial, int flags)183     public void createUserData(String uuid, int userId, int userSerial, int flags)
184             throws InstallerException {
185         mInstaller.execute("create_user_data", uuid, userId, userSerial, flags);
186     }
187 
destroyUserData(String uuid, int userId, int flags)188     public void destroyUserData(String uuid, int userId, int flags) throws InstallerException {
189         mInstaller.execute("destroy_user_data", uuid, userId, flags);
190     }
191 
markBootComplete(String instructionSet)192     public void markBootComplete(String instructionSet) throws InstallerException {
193         assertValidInstructionSet(instructionSet);
194         mInstaller.execute("markbootcomplete", instructionSet);
195     }
196 
freeCache(String uuid, long freeStorageSize)197     public void freeCache(String uuid, long freeStorageSize) throws InstallerException {
198         mInstaller.execute("freecache", uuid, freeStorageSize);
199     }
200 
201     /**
202      * Links the 32 bit native library directory in an application's data
203      * directory to the real location for backward compatibility. Note that no
204      * such symlink is created for 64 bit shared libraries.
205      */
linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, int userId)206     public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32,
207             int userId) throws InstallerException {
208         mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId);
209     }
210 
createOatDir(String oatDir, String dexInstructionSet)211     public void createOatDir(String oatDir, String dexInstructionSet)
212             throws InstallerException {
213         mInstaller.execute("createoatdir", oatDir, dexInstructionSet);
214     }
215 
linkFile(String relativePath, String fromBase, String toBase)216     public void linkFile(String relativePath, String fromBase, String toBase)
217             throws InstallerException {
218         mInstaller.execute("linkfile", relativePath, fromBase, toBase);
219     }
220 
moveAb(String apkPath, String instructionSet, String outputPath)221     public void moveAb(String apkPath, String instructionSet, String outputPath)
222             throws InstallerException {
223         mInstaller.execute("move_ab", apkPath, instructionSet, outputPath);
224     }
225 
assertValidInstructionSet(String instructionSet)226     private static void assertValidInstructionSet(String instructionSet)
227             throws InstallerException {
228         for (String abi : Build.SUPPORTED_ABIS) {
229             if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) {
230                 return;
231             }
232         }
233         throw new InstallerException("Invalid instruction set: " + instructionSet);
234     }
235 }
236