Installer.java revision 019ac85ef5c79c21daa29f9805ee8f98462f0e05
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 17package com.android.server.pm; 18 19import android.annotation.Nullable; 20import android.content.Context; 21import android.content.pm.PackageStats; 22import android.os.Build; 23import android.os.IInstalld; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.os.ServiceSpecificException; 27import android.util.Slog; 28 29import com.android.internal.os.InstallerConnection; 30import com.android.internal.os.InstallerConnection.InstallerException; 31import com.android.server.SystemService; 32 33import dalvik.system.VMRuntime; 34 35import java.util.Arrays; 36 37public final class Installer extends SystemService { 38 private static final String TAG = "Installer"; 39 40 /* *************************************************************************** 41 * IMPORTANT: These values are passed to native code. Keep them in sync with 42 * frameworks/native/cmds/installd/installd.h 43 * **************************************************************************/ 44 /** Application should be visible to everyone */ 45 public static final int DEXOPT_PUBLIC = 1 << 1; 46 /** Application wants to run in VM safe mode */ 47 public static final int DEXOPT_SAFEMODE = 1 << 2; 48 /** Application wants to allow debugging of its code */ 49 public static final int DEXOPT_DEBUGGABLE = 1 << 3; 50 /** The system boot has finished */ 51 public static final int DEXOPT_BOOTCOMPLETE = 1 << 4; 52 /** Hint that the dexopt type is profile-guided. */ 53 public static final int DEXOPT_PROFILE_GUIDED = 1 << 5; 54 /** This is an OTA update dexopt */ 55 public static final int DEXOPT_OTA = 1 << 6; 56 57 // NOTE: keep in sync with installd 58 public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; 59 public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; 60 61 private final InstallerConnection mInstaller; 62 private final IInstalld mInstalld; 63 64 private volatile Object mWarnIfHeld; 65 66 public Installer(Context context) { 67 super(context); 68 mInstaller = new InstallerConnection(); 69 // TODO: reconnect if installd restarts 70 mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd")); 71 } 72 73 // Package-private installer that accepts a custom InstallerConnection. Used for 74 // OtaDexoptService. 75 Installer(Context context, InstallerConnection connection) { 76 super(context); 77 mInstaller = connection; 78 // TODO: reconnect if installd restarts 79 mInstalld = IInstalld.Stub.asInterface(ServiceManager.getService("installd")); 80 } 81 82 /** 83 * Yell loudly if someone tries making future calls while holding a lock on 84 * the given object. 85 */ 86 public void setWarnIfHeld(Object warnIfHeld) { 87 mInstaller.setWarnIfHeld(warnIfHeld); 88 mWarnIfHeld = warnIfHeld; 89 } 90 91 @Override 92 public void onStart() { 93 Slog.i(TAG, "Waiting for installd to be ready."); 94 mInstaller.waitForConnection(); 95 } 96 97 private void checkLock() { 98 if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) { 99 Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" 100 + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable()); 101 } 102 } 103 104 public void createAppData(String uuid, String packageName, int userId, int flags, int appId, 105 String seInfo, int targetSdkVersion) throws InstallerException { 106 checkLock(); 107 try { 108 mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, 109 targetSdkVersion); 110 } catch (RemoteException | ServiceSpecificException e) { 111 throw new InstallerException(e.getMessage()); 112 } 113 } 114 115 public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId, 116 String seInfo) throws InstallerException { 117 checkLock(); 118 try { 119 mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo); 120 } catch (RemoteException | ServiceSpecificException e) { 121 throw new InstallerException(e.getMessage()); 122 } 123 } 124 125 public void migrateAppData(String uuid, String packageName, int userId, int flags) 126 throws InstallerException { 127 checkLock(); 128 try { 129 mInstalld.migrateAppData(uuid, packageName, userId, flags); 130 } catch (RemoteException | ServiceSpecificException e) { 131 throw new InstallerException(e.getMessage()); 132 } 133 } 134 135 public void clearAppData(String uuid, String packageName, int userId, int flags, 136 long ceDataInode) throws InstallerException { 137 checkLock(); 138 try { 139 mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode); 140 } catch (RemoteException | ServiceSpecificException e) { 141 throw new InstallerException(e.getMessage()); 142 } 143 } 144 145 public void destroyAppData(String uuid, String packageName, int userId, int flags, 146 long ceDataInode) throws InstallerException { 147 checkLock(); 148 try { 149 mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode); 150 } catch (RemoteException | ServiceSpecificException e) { 151 throw new InstallerException(e.getMessage()); 152 } 153 } 154 155 public void moveCompleteApp(String fromUuid, String toUuid, String packageName, 156 String dataAppName, int appId, String seInfo, int targetSdkVersion) 157 throws InstallerException { 158 checkLock(); 159 try { 160 mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo, 161 targetSdkVersion); 162 } catch (RemoteException | ServiceSpecificException e) { 163 throw new InstallerException(e.getMessage()); 164 } 165 } 166 167 public void getAppSize(String uuid, String pkgname, int userid, int flags, long ceDataInode, 168 String codePath, PackageStats stats) throws InstallerException { 169 final String[] res = mInstaller.execute("get_app_size", uuid, pkgname, userid, flags, 170 ceDataInode, codePath); 171 try { 172 stats.codeSize += Long.parseLong(res[1]); 173 stats.dataSize += Long.parseLong(res[2]); 174 stats.cacheSize += Long.parseLong(res[3]); 175 } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { 176 throw new InstallerException("Invalid size result: " + Arrays.toString(res)); 177 } 178 } 179 180 public long getAppDataInode(String uuid, String packageName, int userId, int flags) 181 throws InstallerException { 182 checkLock(); 183 try { 184 return mInstalld.getAppDataInode(uuid, packageName, userId, flags); 185 } catch (RemoteException | ServiceSpecificException e) { 186 throw new InstallerException(e.getMessage()); 187 } 188 } 189 190 public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded, 191 int dexFlags, String compilerFilter, String volumeUuid, String sharedLibraries) 192 throws InstallerException { 193 assertValidInstructionSet(instructionSet); 194 mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags, 195 compilerFilter, volumeUuid, sharedLibraries); 196 } 197 198 public void dexopt(String apkPath, int uid, String pkgName, String instructionSet, 199 int dexoptNeeded, @Nullable String outputPath, int dexFlags, 200 String compilerFilter, String volumeUuid, String sharedLibraries) 201 throws InstallerException { 202 assertValidInstructionSet(instructionSet); 203 mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, 204 outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries); 205 } 206 207 public boolean mergeProfiles(int uid, String pkgName) throws InstallerException { 208 return mInstaller.mergeProfiles(uid, pkgName); 209 } 210 211 public boolean dumpProfiles(String gid, String packageName, String codePaths) 212 throws InstallerException { 213 return mInstaller.dumpProfiles(gid, packageName, codePaths); 214 } 215 216 public void idmap(String targetApkPath, String overlayApkPath, int uid) 217 throws InstallerException { 218 mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid); 219 } 220 221 public void rmdex(String codePath, String instructionSet) throws InstallerException { 222 assertValidInstructionSet(instructionSet); 223 mInstaller.execute("rmdex", codePath, instructionSet); 224 } 225 226 public void rmPackageDir(String packageDir) throws InstallerException { 227 mInstaller.execute("rmpackagedir", packageDir); 228 } 229 230 public void clearAppProfiles(String pkgName) throws InstallerException { 231 mInstaller.execute("clear_app_profiles", pkgName); 232 } 233 234 public void destroyAppProfiles(String pkgName) throws InstallerException { 235 mInstaller.execute("destroy_app_profiles", pkgName); 236 } 237 238 public void createUserData(String uuid, int userId, int userSerial, int flags) 239 throws InstallerException { 240 checkLock(); 241 try { 242 mInstalld.createUserData(uuid, userId, userSerial, flags); 243 } catch (RemoteException | ServiceSpecificException e) { 244 throw new InstallerException(e.getMessage()); 245 } 246 } 247 248 public void destroyUserData(String uuid, int userId, int flags) throws InstallerException { 249 checkLock(); 250 try { 251 mInstalld.destroyUserData(uuid, userId, flags); 252 } catch (RemoteException | ServiceSpecificException e) { 253 throw new InstallerException(e.getMessage()); 254 } 255 } 256 257 public void markBootComplete(String instructionSet) throws InstallerException { 258 assertValidInstructionSet(instructionSet); 259 mInstaller.execute("markbootcomplete", instructionSet); 260 } 261 262 public void freeCache(String uuid, long freeStorageSize) throws InstallerException { 263 mInstaller.execute("freecache", uuid, freeStorageSize); 264 } 265 266 /** 267 * Links the 32 bit native library directory in an application's data 268 * directory to the real location for backward compatibility. Note that no 269 * such symlink is created for 64 bit shared libraries. 270 */ 271 public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, 272 int userId) throws InstallerException { 273 mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId); 274 } 275 276 public void createOatDir(String oatDir, String dexInstructionSet) 277 throws InstallerException { 278 mInstaller.execute("createoatdir", oatDir, dexInstructionSet); 279 } 280 281 public void linkFile(String relativePath, String fromBase, String toBase) 282 throws InstallerException { 283 mInstaller.execute("linkfile", relativePath, fromBase, toBase); 284 } 285 286 public void moveAb(String apkPath, String instructionSet, String outputPath) 287 throws InstallerException { 288 mInstaller.execute("move_ab", apkPath, instructionSet, outputPath); 289 } 290 291 public void deleteOdex(String apkPath, String instructionSet, String outputPath) 292 throws InstallerException { 293 mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath); 294 } 295 296 private static void assertValidInstructionSet(String instructionSet) 297 throws InstallerException { 298 for (String abi : Build.SUPPORTED_ABIS) { 299 if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) { 300 return; 301 } 302 } 303 throw new InstallerException("Invalid instruction set: " + instructionSet); 304 } 305} 306