Installer.java revision 7d25fafea7b313cf3eee5bbf4eb959f4986ffce4
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.IBinder; 24import android.os.IBinder.DeathRecipient; 25import android.os.IInstalld; 26import android.os.RemoteException; 27import android.os.ServiceManager; 28import android.text.format.DateUtils; 29import android.util.Slog; 30 31import com.android.internal.os.BackgroundThread; 32import com.android.server.SystemService; 33 34import dalvik.system.VMRuntime; 35 36public class Installer extends SystemService { 37 private static final String TAG = "Installer"; 38 39 /* *************************************************************************** 40 * IMPORTANT: These values are passed to native code. Keep them in sync with 41 * frameworks/native/cmds/installd/installd.h 42 * **************************************************************************/ 43 /** Application should be visible to everyone */ 44 public static final int DEXOPT_PUBLIC = 1 << 1; 45 /** Application wants to run in VM safe mode */ 46 public static final int DEXOPT_SAFEMODE = 1 << 2; 47 /** Application wants to allow debugging of its code */ 48 public static final int DEXOPT_DEBUGGABLE = 1 << 3; 49 /** The system boot has finished */ 50 public static final int DEXOPT_BOOTCOMPLETE = 1 << 4; 51 /** Hint that the dexopt type is profile-guided. */ 52 public static final int DEXOPT_PROFILE_GUIDED = 1 << 5; 53 54 // NOTE: keep in sync with installd 55 public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8; 56 public static final int FLAG_CLEAR_CODE_CACHE_ONLY = 1 << 9; 57 public static final int FLAG_USE_QUOTA = 1 << 12; 58 59 private final boolean mIsolated; 60 61 private volatile IInstalld mInstalld; 62 private volatile Object mWarnIfHeld; 63 64 public Installer(Context context) { 65 this(context, false); 66 } 67 68 /** 69 * @param isolated indicates if this object should <em>not</em> connect to 70 * the real {@code installd}. All remote calls will be ignored 71 * unless you extend this class and intercept them. 72 */ 73 public Installer(Context context, boolean isolated) { 74 super(context); 75 mIsolated = isolated; 76 } 77 78 /** 79 * Yell loudly if someone tries making future calls while holding a lock on 80 * the given object. 81 */ 82 public void setWarnIfHeld(Object warnIfHeld) { 83 mWarnIfHeld = warnIfHeld; 84 } 85 86 @Override 87 public void onStart() { 88 if (mIsolated) { 89 mInstalld = null; 90 } else { 91 connect(); 92 } 93 } 94 95 private void connect() { 96 IBinder binder = ServiceManager.getService("installd"); 97 if (binder != null) { 98 try { 99 binder.linkToDeath(new DeathRecipient() { 100 @Override 101 public void binderDied() { 102 Slog.w(TAG, "installd died; reconnecting"); 103 connect(); 104 } 105 }, 0); 106 } catch (RemoteException e) { 107 binder = null; 108 } 109 } 110 111 if (binder != null) { 112 mInstalld = IInstalld.Stub.asInterface(binder); 113 } else { 114 Slog.w(TAG, "installd not found; trying again"); 115 BackgroundThread.getHandler().postDelayed(() -> { 116 connect(); 117 }, DateUtils.SECOND_IN_MILLIS); 118 } 119 } 120 121 /** 122 * Do several pre-flight checks before making a remote call. 123 * 124 * @return if the remote call should continue. 125 */ 126 private boolean checkBeforeRemote() { 127 if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) { 128 Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" 129 + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable()); 130 } 131 if (mIsolated) { 132 Slog.i(TAG, "Ignoring request because this installer is isolated"); 133 return false; 134 } else { 135 return true; 136 } 137 } 138 139 public long createAppData(String uuid, String packageName, int userId, int flags, int appId, 140 String seInfo, int targetSdkVersion) throws InstallerException { 141 if (!checkBeforeRemote()) return -1; 142 try { 143 return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, 144 targetSdkVersion); 145 } catch (Exception e) { 146 throw InstallerException.from(e); 147 } 148 } 149 150 public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId, 151 String seInfo) throws InstallerException { 152 if (!checkBeforeRemote()) return; 153 try { 154 mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo); 155 } catch (Exception e) { 156 throw InstallerException.from(e); 157 } 158 } 159 160 public void migrateAppData(String uuid, String packageName, int userId, int flags) 161 throws InstallerException { 162 if (!checkBeforeRemote()) return; 163 try { 164 mInstalld.migrateAppData(uuid, packageName, userId, flags); 165 } catch (Exception e) { 166 throw InstallerException.from(e); 167 } 168 } 169 170 public void clearAppData(String uuid, String packageName, int userId, int flags, 171 long ceDataInode) throws InstallerException { 172 if (!checkBeforeRemote()) return; 173 try { 174 mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode); 175 } catch (Exception e) { 176 throw InstallerException.from(e); 177 } 178 } 179 180 public void destroyAppData(String uuid, String packageName, int userId, int flags, 181 long ceDataInode) throws InstallerException { 182 if (!checkBeforeRemote()) return; 183 try { 184 mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode); 185 } catch (Exception e) { 186 throw InstallerException.from(e); 187 } 188 } 189 190 public void moveCompleteApp(String fromUuid, String toUuid, String packageName, 191 String dataAppName, int appId, String seInfo, int targetSdkVersion) 192 throws InstallerException { 193 if (!checkBeforeRemote()) return; 194 try { 195 mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo, 196 targetSdkVersion); 197 } catch (Exception e) { 198 throw InstallerException.from(e); 199 } 200 } 201 202 public void getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId, 203 long[] ceDataInodes, String[] codePaths, PackageStats stats) 204 throws InstallerException { 205 if (!checkBeforeRemote()) return; 206 try { 207 final long[] res = mInstalld.getAppSize(uuid, packageNames, userId, flags, 208 appId, ceDataInodes, codePaths); 209 stats.codeSize += res[0]; 210 stats.dataSize += res[1]; 211 stats.cacheSize += res[2]; 212 stats.externalCodeSize += res[3]; 213 stats.externalDataSize += res[4]; 214 stats.externalCacheSize += res[5]; 215 } catch (Exception e) { 216 throw InstallerException.from(e); 217 } 218 } 219 220 public void getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats) 221 throws InstallerException { 222 if (!checkBeforeRemote()) return; 223 try { 224 final long[] res = mInstalld.getUserSize(uuid, userId, flags, appIds); 225 stats.codeSize += res[0]; 226 stats.dataSize += res[1]; 227 stats.cacheSize += res[2]; 228 stats.externalCodeSize += res[3]; 229 stats.externalDataSize += res[4]; 230 stats.externalCacheSize += res[5]; 231 } catch (Exception e) { 232 throw InstallerException.from(e); 233 } 234 } 235 236 public long[] getExternalSize(String uuid, int userId, int flags) throws InstallerException { 237 if (!checkBeforeRemote()) return new long[4]; 238 try { 239 return mInstalld.getExternalSize(uuid, userId, flags); 240 } catch (Exception e) { 241 throw InstallerException.from(e); 242 } 243 } 244 245 public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, 246 int dexoptNeeded, @Nullable String outputPath, int dexFlags, 247 String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries) 248 throws InstallerException { 249 assertValidInstructionSet(instructionSet); 250 if (!checkBeforeRemote()) return; 251 try { 252 mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath, 253 dexFlags, compilerFilter, volumeUuid, sharedLibraries); 254 } catch (Exception e) { 255 throw InstallerException.from(e); 256 } 257 } 258 259 public boolean mergeProfiles(int uid, String packageName) throws InstallerException { 260 if (!checkBeforeRemote()) return false; 261 try { 262 return mInstalld.mergeProfiles(uid, packageName); 263 } catch (Exception e) { 264 throw InstallerException.from(e); 265 } 266 } 267 268 public boolean dumpProfiles(int uid, String packageName, String codePaths) 269 throws InstallerException { 270 if (!checkBeforeRemote()) return false; 271 try { 272 return mInstalld.dumpProfiles(uid, packageName, codePaths); 273 } catch (Exception e) { 274 throw InstallerException.from(e); 275 } 276 } 277 278 public void idmap(String targetApkPath, String overlayApkPath, int uid) 279 throws InstallerException { 280 if (!checkBeforeRemote()) return; 281 try { 282 mInstalld.idmap(targetApkPath, overlayApkPath, uid); 283 } catch (Exception e) { 284 throw InstallerException.from(e); 285 } 286 } 287 288 public void rmdex(String codePath, String instructionSet) throws InstallerException { 289 assertValidInstructionSet(instructionSet); 290 if (!checkBeforeRemote()) return; 291 try { 292 mInstalld.rmdex(codePath, instructionSet); 293 } catch (Exception e) { 294 throw InstallerException.from(e); 295 } 296 } 297 298 public void rmPackageDir(String packageDir) throws InstallerException { 299 if (!checkBeforeRemote()) return; 300 try { 301 mInstalld.rmPackageDir(packageDir); 302 } catch (Exception e) { 303 throw InstallerException.from(e); 304 } 305 } 306 307 public void clearAppProfiles(String packageName) throws InstallerException { 308 if (!checkBeforeRemote()) return; 309 try { 310 mInstalld.clearAppProfiles(packageName); 311 } catch (Exception e) { 312 throw InstallerException.from(e); 313 } 314 } 315 316 public void destroyAppProfiles(String packageName) throws InstallerException { 317 if (!checkBeforeRemote()) return; 318 try { 319 mInstalld.destroyAppProfiles(packageName); 320 } catch (Exception e) { 321 throw InstallerException.from(e); 322 } 323 } 324 325 public void createUserData(String uuid, int userId, int userSerial, int flags) 326 throws InstallerException { 327 if (!checkBeforeRemote()) return; 328 try { 329 mInstalld.createUserData(uuid, userId, userSerial, flags); 330 } catch (Exception e) { 331 throw InstallerException.from(e); 332 } 333 } 334 335 public void destroyUserData(String uuid, int userId, int flags) throws InstallerException { 336 if (!checkBeforeRemote()) return; 337 try { 338 mInstalld.destroyUserData(uuid, userId, flags); 339 } catch (Exception e) { 340 throw InstallerException.from(e); 341 } 342 } 343 344 public void markBootComplete(String instructionSet) throws InstallerException { 345 assertValidInstructionSet(instructionSet); 346 if (!checkBeforeRemote()) return; 347 try { 348 mInstalld.markBootComplete(instructionSet); 349 } catch (Exception e) { 350 throw InstallerException.from(e); 351 } 352 } 353 354 public void freeCache(String uuid, long freeStorageSize) throws InstallerException { 355 if (!checkBeforeRemote()) return; 356 try { 357 mInstalld.freeCache(uuid, freeStorageSize); 358 } catch (Exception e) { 359 throw InstallerException.from(e); 360 } 361 } 362 363 /** 364 * Links the 32 bit native library directory in an application's data 365 * directory to the real location for backward compatibility. Note that no 366 * such symlink is created for 64 bit shared libraries. 367 */ 368 public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32, 369 int userId) throws InstallerException { 370 if (!checkBeforeRemote()) return; 371 try { 372 mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId); 373 } catch (Exception e) { 374 throw InstallerException.from(e); 375 } 376 } 377 378 public void createOatDir(String oatDir, String dexInstructionSet) 379 throws InstallerException { 380 if (!checkBeforeRemote()) return; 381 try { 382 mInstalld.createOatDir(oatDir, dexInstructionSet); 383 } catch (Exception e) { 384 throw InstallerException.from(e); 385 } 386 } 387 388 public void linkFile(String relativePath, String fromBase, String toBase) 389 throws InstallerException { 390 if (!checkBeforeRemote()) return; 391 try { 392 mInstalld.linkFile(relativePath, fromBase, toBase); 393 } catch (Exception e) { 394 throw InstallerException.from(e); 395 } 396 } 397 398 public void moveAb(String apkPath, String instructionSet, String outputPath) 399 throws InstallerException { 400 if (!checkBeforeRemote()) return; 401 try { 402 mInstalld.moveAb(apkPath, instructionSet, outputPath); 403 } catch (Exception e) { 404 throw InstallerException.from(e); 405 } 406 } 407 408 public void deleteOdex(String apkPath, String instructionSet, String outputPath) 409 throws InstallerException { 410 if (!checkBeforeRemote()) return; 411 try { 412 mInstalld.deleteOdex(apkPath, instructionSet, outputPath); 413 } catch (Exception e) { 414 throw InstallerException.from(e); 415 } 416 } 417 418 public void invalidateMounts() throws InstallerException { 419 if (!checkBeforeRemote()) return; 420 try { 421 mInstalld.invalidateMounts(); 422 } catch (Exception e) { 423 throw InstallerException.from(e); 424 } 425 } 426 427 private static void assertValidInstructionSet(String instructionSet) 428 throws InstallerException { 429 for (String abi : Build.SUPPORTED_ABIS) { 430 if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) { 431 return; 432 } 433 } 434 throw new InstallerException("Invalid instruction set: " + instructionSet); 435 } 436 437 public static class InstallerException extends Exception { 438 public InstallerException(String detailMessage) { 439 super(detailMessage); 440 } 441 442 public static InstallerException from(Exception e) throws InstallerException { 443 throw new InstallerException(e.toString()); 444 } 445 } 446} 447