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.AppIdInt; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.UserIdInt; 23 import android.content.Context; 24 import android.content.pm.PackageStats; 25 import android.os.Build; 26 import android.os.IBinder; 27 import android.os.IBinder.DeathRecipient; 28 import android.os.IInstalld; 29 import android.os.RemoteException; 30 import android.os.ServiceManager; 31 import android.text.format.DateUtils; 32 import android.util.Slog; 33 34 import com.android.internal.os.BackgroundThread; 35 import com.android.server.SystemService; 36 37 import dalvik.system.BlockGuard; 38 import dalvik.system.VMRuntime; 39 40 import java.io.FileDescriptor; 41 42 public class Installer extends SystemService { 43 private static final String TAG = "Installer"; 44 45 /* *************************************************************************** 46 * IMPORTANT: These values are passed to native code. Keep them in sync with 47 * frameworks/native/cmds/installd/installd_constants.h 48 * **************************************************************************/ 49 /** Application should be visible to everyone */ 50 public static final int DEXOPT_PUBLIC = 1 << 1; 51 /** Application wants to allow debugging of its code */ 52 public static final int DEXOPT_DEBUGGABLE = 1 << 2; 53 /** The system boot has finished */ 54 public static final int DEXOPT_BOOTCOMPLETE = 1 << 3; 55 /** Hint that the dexopt type is profile-guided. */ 56 public static final int DEXOPT_PROFILE_GUIDED = 1 << 4; 57 /** The compilation is for a secondary dex file. */ 58 public static final int DEXOPT_SECONDARY_DEX = 1 << 5; 59 /** Ignore the result of dexoptNeeded and force compilation. */ 60 public static final int DEXOPT_FORCE = 1 << 6; 61 /** Indicates that the dex file passed to dexopt in on CE storage. */ 62 public static final int DEXOPT_STORAGE_CE = 1 << 7; 63 /** Indicates that the dex file passed to dexopt in on DE storage. */ 64 public static final int DEXOPT_STORAGE_DE = 1 << 8; 65 /** Indicates that dexopt is invoked from the background service. */ 66 public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9; 67 /** Indicates that dexopt should restrict access to private APIs. */ 68 public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10; 69 /** Indicates that dexopt should convert to CompactDex. */ 70 public static final int DEXOPT_GENERATE_COMPACT_DEX = 1 << 11; 71 /** Indicates that dexopt should generate an app image */ 72 public static final int DEXOPT_GENERATE_APP_IMAGE = 1 << 12; 73 74 public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE; 75 public static final int FLAG_STORAGE_CE = IInstalld.FLAG_STORAGE_CE; 76 public static final int FLAG_STORAGE_EXTERNAL = IInstalld.FLAG_STORAGE_EXTERNAL; 77 78 public static final int FLAG_CLEAR_CACHE_ONLY = IInstalld.FLAG_CLEAR_CACHE_ONLY; 79 public static final int FLAG_CLEAR_CODE_CACHE_ONLY = IInstalld.FLAG_CLEAR_CODE_CACHE_ONLY; 80 81 public static final int FLAG_FREE_CACHE_V2 = IInstalld.FLAG_FREE_CACHE_V2; 82 public static final int FLAG_FREE_CACHE_V2_DEFY_QUOTA = IInstalld.FLAG_FREE_CACHE_V2_DEFY_QUOTA; 83 public static final int FLAG_FREE_CACHE_NOOP = IInstalld.FLAG_FREE_CACHE_NOOP; 84 85 public static final int FLAG_USE_QUOTA = IInstalld.FLAG_USE_QUOTA; 86 public static final int FLAG_FORCE = IInstalld.FLAG_FORCE; 87 88 private final boolean mIsolated; 89 90 private volatile IInstalld mInstalld; 91 private volatile Object mWarnIfHeld; 92 Installer(Context context)93 public Installer(Context context) { 94 this(context, false); 95 } 96 97 /** 98 * @param isolated indicates if this object should <em>not</em> connect to 99 * the real {@code installd}. All remote calls will be ignored 100 * unless you extend this class and intercept them. 101 */ Installer(Context context, boolean isolated)102 public Installer(Context context, boolean isolated) { 103 super(context); 104 mIsolated = isolated; 105 } 106 107 /** 108 * Yell loudly if someone tries making future calls while holding a lock on 109 * the given object. 110 */ setWarnIfHeld(Object warnIfHeld)111 public void setWarnIfHeld(Object warnIfHeld) { 112 mWarnIfHeld = warnIfHeld; 113 } 114 115 @Override onStart()116 public void onStart() { 117 if (mIsolated) { 118 mInstalld = null; 119 } else { 120 connect(); 121 } 122 } 123 connect()124 private void connect() { 125 IBinder binder = ServiceManager.getService("installd"); 126 if (binder != null) { 127 try { 128 binder.linkToDeath(new DeathRecipient() { 129 @Override 130 public void binderDied() { 131 Slog.w(TAG, "installd died; reconnecting"); 132 connect(); 133 } 134 }, 0); 135 } catch (RemoteException e) { 136 binder = null; 137 } 138 } 139 140 if (binder != null) { 141 mInstalld = IInstalld.Stub.asInterface(binder); 142 try { 143 invalidateMounts(); 144 } catch (InstallerException ignored) { 145 } 146 } else { 147 Slog.w(TAG, "installd not found; trying again"); 148 BackgroundThread.getHandler().postDelayed(() -> { 149 connect(); 150 }, DateUtils.SECOND_IN_MILLIS); 151 } 152 } 153 154 /** 155 * Do several pre-flight checks before making a remote call. 156 * 157 * @return if the remote call should continue. 158 */ checkBeforeRemote()159 private boolean checkBeforeRemote() { 160 if (mWarnIfHeld != null && Thread.holdsLock(mWarnIfHeld)) { 161 Slog.wtf(TAG, "Calling thread " + Thread.currentThread().getName() + " is holding 0x" 162 + Integer.toHexString(System.identityHashCode(mWarnIfHeld)), new Throwable()); 163 } 164 if (mIsolated) { 165 Slog.i(TAG, "Ignoring request because this installer is isolated"); 166 return false; 167 } else { 168 return true; 169 } 170 } 171 createAppData(String uuid, String packageName, int userId, int flags, int appId, String seInfo, int targetSdkVersion)172 public long createAppData(String uuid, String packageName, int userId, int flags, int appId, 173 String seInfo, int targetSdkVersion) throws InstallerException { 174 if (!checkBeforeRemote()) return -1; 175 try { 176 return mInstalld.createAppData(uuid, packageName, userId, flags, appId, seInfo, 177 targetSdkVersion); 178 } catch (Exception e) { 179 throw InstallerException.from(e); 180 } 181 } 182 restoreconAppData(String uuid, String packageName, int userId, int flags, int appId, String seInfo)183 public void restoreconAppData(String uuid, String packageName, int userId, int flags, int appId, 184 String seInfo) throws InstallerException { 185 if (!checkBeforeRemote()) return; 186 try { 187 mInstalld.restoreconAppData(uuid, packageName, userId, flags, appId, seInfo); 188 } catch (Exception e) { 189 throw InstallerException.from(e); 190 } 191 } 192 migrateAppData(String uuid, String packageName, int userId, int flags)193 public void migrateAppData(String uuid, String packageName, int userId, int flags) 194 throws InstallerException { 195 if (!checkBeforeRemote()) return; 196 try { 197 mInstalld.migrateAppData(uuid, packageName, userId, flags); 198 } catch (Exception e) { 199 throw InstallerException.from(e); 200 } 201 } 202 clearAppData(String uuid, String packageName, int userId, int flags, long ceDataInode)203 public void clearAppData(String uuid, String packageName, int userId, int flags, 204 long ceDataInode) throws InstallerException { 205 if (!checkBeforeRemote()) return; 206 try { 207 mInstalld.clearAppData(uuid, packageName, userId, flags, ceDataInode); 208 } catch (Exception e) { 209 throw InstallerException.from(e); 210 } 211 } 212 destroyAppData(String uuid, String packageName, int userId, int flags, long ceDataInode)213 public void destroyAppData(String uuid, String packageName, int userId, int flags, 214 long ceDataInode) throws InstallerException { 215 if (!checkBeforeRemote()) return; 216 try { 217 mInstalld.destroyAppData(uuid, packageName, userId, flags, ceDataInode); 218 } catch (Exception e) { 219 throw InstallerException.from(e); 220 } 221 } 222 fixupAppData(String uuid, int flags)223 public void fixupAppData(String uuid, int flags) throws InstallerException { 224 if (!checkBeforeRemote()) return; 225 try { 226 mInstalld.fixupAppData(uuid, flags); 227 } catch (Exception e) { 228 throw InstallerException.from(e); 229 } 230 } 231 moveCompleteApp(String fromUuid, String toUuid, String packageName, String dataAppName, int appId, String seInfo, int targetSdkVersion)232 public void moveCompleteApp(String fromUuid, String toUuid, String packageName, 233 String dataAppName, int appId, String seInfo, int targetSdkVersion) 234 throws InstallerException { 235 if (!checkBeforeRemote()) return; 236 try { 237 mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo, 238 targetSdkVersion); 239 } catch (Exception e) { 240 throw InstallerException.from(e); 241 } 242 } 243 getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId, long[] ceDataInodes, String[] codePaths, PackageStats stats)244 public void getAppSize(String uuid, String[] packageNames, int userId, int flags, int appId, 245 long[] ceDataInodes, String[] codePaths, PackageStats stats) 246 throws InstallerException { 247 if (!checkBeforeRemote()) return; 248 if (codePaths != null) { 249 for (String codePath : codePaths) { 250 BlockGuard.getVmPolicy().onPathAccess(codePath); 251 } 252 } 253 try { 254 final long[] res = mInstalld.getAppSize(uuid, packageNames, userId, flags, 255 appId, ceDataInodes, codePaths); 256 stats.codeSize += res[0]; 257 stats.dataSize += res[1]; 258 stats.cacheSize += res[2]; 259 stats.externalCodeSize += res[3]; 260 stats.externalDataSize += res[4]; 261 stats.externalCacheSize += res[5]; 262 } catch (Exception e) { 263 throw InstallerException.from(e); 264 } 265 } 266 getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats)267 public void getUserSize(String uuid, int userId, int flags, int[] appIds, PackageStats stats) 268 throws InstallerException { 269 if (!checkBeforeRemote()) return; 270 try { 271 final long[] res = mInstalld.getUserSize(uuid, userId, flags, appIds); 272 stats.codeSize += res[0]; 273 stats.dataSize += res[1]; 274 stats.cacheSize += res[2]; 275 stats.externalCodeSize += res[3]; 276 stats.externalDataSize += res[4]; 277 stats.externalCacheSize += res[5]; 278 } catch (Exception e) { 279 throw InstallerException.from(e); 280 } 281 } 282 getExternalSize(String uuid, int userId, int flags, int[] appIds)283 public long[] getExternalSize(String uuid, int userId, int flags, int[] appIds) 284 throws InstallerException { 285 if (!checkBeforeRemote()) return new long[6]; 286 try { 287 return mInstalld.getExternalSize(uuid, userId, flags, appIds); 288 } catch (Exception e) { 289 throw InstallerException.from(e); 290 } 291 } 292 setAppQuota(String uuid, int userId, int appId, long cacheQuota)293 public void setAppQuota(String uuid, int userId, int appId, long cacheQuota) 294 throws InstallerException { 295 if (!checkBeforeRemote()) return; 296 try { 297 mInstalld.setAppQuota(uuid, userId, appId, cacheQuota); 298 } catch (Exception e) { 299 throw InstallerException.from(e); 300 } 301 } 302 dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, int dexoptNeeded, @Nullable String outputPath, int dexFlags, String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries, @Nullable String seInfo, boolean downgrade, int targetSdkVersion, @Nullable String profileName, @Nullable String dexMetadataPath, @Nullable String compilationReason)303 public void dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet, 304 int dexoptNeeded, @Nullable String outputPath, int dexFlags, 305 String compilerFilter, @Nullable String volumeUuid, @Nullable String sharedLibraries, 306 @Nullable String seInfo, boolean downgrade, int targetSdkVersion, 307 @Nullable String profileName, @Nullable String dexMetadataPath, 308 @Nullable String compilationReason) throws InstallerException { 309 assertValidInstructionSet(instructionSet); 310 BlockGuard.getVmPolicy().onPathAccess(apkPath); 311 BlockGuard.getVmPolicy().onPathAccess(outputPath); 312 BlockGuard.getVmPolicy().onPathAccess(dexMetadataPath); 313 if (!checkBeforeRemote()) return; 314 try { 315 mInstalld.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded, outputPath, 316 dexFlags, compilerFilter, volumeUuid, sharedLibraries, seInfo, downgrade, 317 targetSdkVersion, profileName, dexMetadataPath, compilationReason); 318 } catch (Exception e) { 319 throw InstallerException.from(e); 320 } 321 } 322 mergeProfiles(int uid, String packageName, String profileName)323 public boolean mergeProfiles(int uid, String packageName, String profileName) 324 throws InstallerException { 325 if (!checkBeforeRemote()) return false; 326 try { 327 return mInstalld.mergeProfiles(uid, packageName, profileName); 328 } catch (Exception e) { 329 throw InstallerException.from(e); 330 } 331 } 332 dumpProfiles(int uid, String packageName, String profileName, String codePath)333 public boolean dumpProfiles(int uid, String packageName, String profileName, String codePath) 334 throws InstallerException { 335 if (!checkBeforeRemote()) return false; 336 BlockGuard.getVmPolicy().onPathAccess(codePath); 337 try { 338 return mInstalld.dumpProfiles(uid, packageName, profileName, codePath); 339 } catch (Exception e) { 340 throw InstallerException.from(e); 341 } 342 } 343 copySystemProfile(String systemProfile, int uid, String packageName, String profileName)344 public boolean copySystemProfile(String systemProfile, int uid, String packageName, 345 String profileName) throws InstallerException { 346 if (!checkBeforeRemote()) return false; 347 try { 348 return mInstalld.copySystemProfile(systemProfile, uid, packageName, profileName); 349 } catch (Exception e) { 350 throw InstallerException.from(e); 351 } 352 } 353 idmap(String targetApkPath, String overlayApkPath, int uid)354 public void idmap(String targetApkPath, String overlayApkPath, int uid) 355 throws InstallerException { 356 if (!checkBeforeRemote()) return; 357 BlockGuard.getVmPolicy().onPathAccess(targetApkPath); 358 BlockGuard.getVmPolicy().onPathAccess(overlayApkPath); 359 try { 360 mInstalld.idmap(targetApkPath, overlayApkPath, uid); 361 } catch (Exception e) { 362 throw InstallerException.from(e); 363 } 364 } 365 removeIdmap(String overlayApkPath)366 public void removeIdmap(String overlayApkPath) throws InstallerException { 367 if (!checkBeforeRemote()) return; 368 BlockGuard.getVmPolicy().onPathAccess(overlayApkPath); 369 try { 370 mInstalld.removeIdmap(overlayApkPath); 371 } catch (Exception e) { 372 throw InstallerException.from(e); 373 } 374 } 375 rmdex(String codePath, String instructionSet)376 public void rmdex(String codePath, String instructionSet) throws InstallerException { 377 assertValidInstructionSet(instructionSet); 378 if (!checkBeforeRemote()) return; 379 BlockGuard.getVmPolicy().onPathAccess(codePath); 380 try { 381 mInstalld.rmdex(codePath, instructionSet); 382 } catch (Exception e) { 383 throw InstallerException.from(e); 384 } 385 } 386 rmPackageDir(String packageDir)387 public void rmPackageDir(String packageDir) throws InstallerException { 388 if (!checkBeforeRemote()) return; 389 BlockGuard.getVmPolicy().onPathAccess(packageDir); 390 try { 391 mInstalld.rmPackageDir(packageDir); 392 } catch (Exception e) { 393 throw InstallerException.from(e); 394 } 395 } 396 clearAppProfiles(String packageName, String profileName)397 public void clearAppProfiles(String packageName, String profileName) throws InstallerException { 398 if (!checkBeforeRemote()) return; 399 try { 400 mInstalld.clearAppProfiles(packageName, profileName); 401 } catch (Exception e) { 402 throw InstallerException.from(e); 403 } 404 } 405 destroyAppProfiles(String packageName)406 public void destroyAppProfiles(String packageName) throws InstallerException { 407 if (!checkBeforeRemote()) return; 408 try { 409 mInstalld.destroyAppProfiles(packageName); 410 } catch (Exception e) { 411 throw InstallerException.from(e); 412 } 413 } 414 createUserData(String uuid, int userId, int userSerial, int flags)415 public void createUserData(String uuid, int userId, int userSerial, int flags) 416 throws InstallerException { 417 if (!checkBeforeRemote()) return; 418 try { 419 mInstalld.createUserData(uuid, userId, userSerial, flags); 420 } catch (Exception e) { 421 throw InstallerException.from(e); 422 } 423 } 424 destroyUserData(String uuid, int userId, int flags)425 public void destroyUserData(String uuid, int userId, int flags) throws InstallerException { 426 if (!checkBeforeRemote()) return; 427 try { 428 mInstalld.destroyUserData(uuid, userId, flags); 429 } catch (Exception e) { 430 throw InstallerException.from(e); 431 } 432 } 433 markBootComplete(String instructionSet)434 public void markBootComplete(String instructionSet) throws InstallerException { 435 assertValidInstructionSet(instructionSet); 436 if (!checkBeforeRemote()) return; 437 try { 438 mInstalld.markBootComplete(instructionSet); 439 } catch (Exception e) { 440 throw InstallerException.from(e); 441 } 442 } 443 freeCache(String uuid, long targetFreeBytes, long cacheReservedBytes, int flags)444 public void freeCache(String uuid, long targetFreeBytes, long cacheReservedBytes, int flags) 445 throws InstallerException { 446 if (!checkBeforeRemote()) return; 447 try { 448 mInstalld.freeCache(uuid, targetFreeBytes, cacheReservedBytes, flags); 449 } catch (Exception e) { 450 throw InstallerException.from(e); 451 } 452 } 453 454 /** 455 * Links the 32 bit native library directory in an application's data 456 * directory to the real location for backward compatibility. Note that no 457 * such symlink is created for 64 bit shared libraries. 458 */ linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32, int userId)459 public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32, 460 int userId) throws InstallerException { 461 if (!checkBeforeRemote()) return; 462 BlockGuard.getVmPolicy().onPathAccess(nativeLibPath32); 463 try { 464 mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId); 465 } catch (Exception e) { 466 throw InstallerException.from(e); 467 } 468 } 469 createOatDir(String oatDir, String dexInstructionSet)470 public void createOatDir(String oatDir, String dexInstructionSet) 471 throws InstallerException { 472 if (!checkBeforeRemote()) return; 473 try { 474 mInstalld.createOatDir(oatDir, dexInstructionSet); 475 } catch (Exception e) { 476 throw InstallerException.from(e); 477 } 478 } 479 linkFile(String relativePath, String fromBase, String toBase)480 public void linkFile(String relativePath, String fromBase, String toBase) 481 throws InstallerException { 482 if (!checkBeforeRemote()) return; 483 BlockGuard.getVmPolicy().onPathAccess(fromBase); 484 BlockGuard.getVmPolicy().onPathAccess(toBase); 485 try { 486 mInstalld.linkFile(relativePath, fromBase, toBase); 487 } catch (Exception e) { 488 throw InstallerException.from(e); 489 } 490 } 491 moveAb(String apkPath, String instructionSet, String outputPath)492 public void moveAb(String apkPath, String instructionSet, String outputPath) 493 throws InstallerException { 494 if (!checkBeforeRemote()) return; 495 BlockGuard.getVmPolicy().onPathAccess(apkPath); 496 BlockGuard.getVmPolicy().onPathAccess(outputPath); 497 try { 498 mInstalld.moveAb(apkPath, instructionSet, outputPath); 499 } catch (Exception e) { 500 throw InstallerException.from(e); 501 } 502 } 503 deleteOdex(String apkPath, String instructionSet, String outputPath)504 public void deleteOdex(String apkPath, String instructionSet, String outputPath) 505 throws InstallerException { 506 if (!checkBeforeRemote()) return; 507 BlockGuard.getVmPolicy().onPathAccess(apkPath); 508 BlockGuard.getVmPolicy().onPathAccess(outputPath); 509 try { 510 mInstalld.deleteOdex(apkPath, instructionSet, outputPath); 511 } catch (Exception e) { 512 throw InstallerException.from(e); 513 } 514 } 515 installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)516 public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize) 517 throws InstallerException { 518 if (!checkBeforeRemote()) return; 519 BlockGuard.getVmPolicy().onPathAccess(filePath); 520 try { 521 mInstalld.installApkVerity(filePath, verityInput, contentSize); 522 } catch (Exception e) { 523 throw InstallerException.from(e); 524 } 525 } 526 assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)527 public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash) 528 throws InstallerException { 529 if (!checkBeforeRemote()) return; 530 BlockGuard.getVmPolicy().onPathAccess(filePath); 531 try { 532 mInstalld.assertFsverityRootHashMatches(filePath, expectedHash); 533 } catch (Exception e) { 534 throw InstallerException.from(e); 535 } 536 } 537 reconcileSecondaryDexFile(String apkPath, String packageName, int uid, String[] isas, @Nullable String volumeUuid, int flags)538 public boolean reconcileSecondaryDexFile(String apkPath, String packageName, int uid, 539 String[] isas, @Nullable String volumeUuid, int flags) throws InstallerException { 540 for (int i = 0; i < isas.length; i++) { 541 assertValidInstructionSet(isas[i]); 542 } 543 if (!checkBeforeRemote()) return false; 544 BlockGuard.getVmPolicy().onPathAccess(apkPath); 545 try { 546 return mInstalld.reconcileSecondaryDexFile(apkPath, packageName, uid, isas, 547 volumeUuid, flags); 548 } catch (Exception e) { 549 throw InstallerException.from(e); 550 } 551 } 552 hashSecondaryDexFile(String dexPath, String packageName, int uid, @Nullable String volumeUuid, int flags)553 public byte[] hashSecondaryDexFile(String dexPath, String packageName, int uid, 554 @Nullable String volumeUuid, int flags) throws InstallerException { 555 if (!checkBeforeRemote()) return new byte[0]; 556 BlockGuard.getVmPolicy().onPathAccess(dexPath); 557 try { 558 return mInstalld.hashSecondaryDexFile(dexPath, packageName, uid, volumeUuid, flags); 559 } catch (Exception e) { 560 throw InstallerException.from(e); 561 } 562 } 563 createProfileSnapshot(int appId, String packageName, String profileName, String classpath)564 public boolean createProfileSnapshot(int appId, String packageName, String profileName, 565 String classpath) throws InstallerException { 566 if (!checkBeforeRemote()) return false; 567 try { 568 return mInstalld.createProfileSnapshot(appId, packageName, profileName, classpath); 569 } catch (Exception e) { 570 throw InstallerException.from(e); 571 } 572 } 573 destroyProfileSnapshot(String packageName, String profileName)574 public void destroyProfileSnapshot(String packageName, String profileName) 575 throws InstallerException { 576 if (!checkBeforeRemote()) return; 577 try { 578 mInstalld.destroyProfileSnapshot(packageName, profileName); 579 } catch (Exception e) { 580 throw InstallerException.from(e); 581 } 582 } 583 invalidateMounts()584 public void invalidateMounts() throws InstallerException { 585 if (!checkBeforeRemote()) return; 586 try { 587 mInstalld.invalidateMounts(); 588 } catch (Exception e) { 589 throw InstallerException.from(e); 590 } 591 } 592 isQuotaSupported(String volumeUuid)593 public boolean isQuotaSupported(String volumeUuid) throws InstallerException { 594 if (!checkBeforeRemote()) return false; 595 try { 596 return mInstalld.isQuotaSupported(volumeUuid); 597 } catch (Exception e) { 598 throw InstallerException.from(e); 599 } 600 } 601 prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId, String profileName, String codePath, String dexMetadataPath)602 public boolean prepareAppProfile(String pkg, @UserIdInt int userId, @AppIdInt int appId, 603 String profileName, String codePath, String dexMetadataPath) throws InstallerException { 604 if (!checkBeforeRemote()) return false; 605 BlockGuard.getVmPolicy().onPathAccess(codePath); 606 BlockGuard.getVmPolicy().onPathAccess(dexMetadataPath); 607 try { 608 return mInstalld.prepareAppProfile(pkg, userId, appId, profileName, codePath, 609 dexMetadataPath); 610 } catch (Exception e) { 611 throw InstallerException.from(e); 612 } 613 } 614 615 /** 616 * Snapshots user data of the given package. 617 * 618 * @param pkg name of the package to snapshot user data for. 619 * @param userId id of the user whose data to snapshot. 620 * @param snapshotId id of this snapshot. 621 * @param storageFlags flags controlling which data (CE or DE) to snapshot. 622 * 623 * @return inode of the snapshot of users CE package data, or {@code 0} if a remote calls 624 * shouldn't be continued. See {@link #checkBeforeRemote}. 625 * 626 * @throws InstallerException if failed to snapshot user data. 627 */ snapshotAppData(String pkg, @UserIdInt int userId, int snapshotId, int storageFlags)628 public long snapshotAppData(String pkg, @UserIdInt int userId, int snapshotId, int storageFlags) 629 throws InstallerException { 630 if (!checkBeforeRemote()) return 0; 631 632 try { 633 return mInstalld.snapshotAppData(null, pkg, userId, snapshotId, storageFlags); 634 } catch (Exception e) { 635 throw InstallerException.from(e); 636 } 637 } 638 639 /** 640 * Restores user data snapshot of the given package. 641 * 642 * @param pkg name of the package to restore user data for. 643 * @param appId id of the package to restore user data for. 644 * @param userId id of the user whose data to restore. 645 * @param snapshotId id of the snapshot to restore. 646 * @param storageFlags flags controlling which data (CE or DE) to restore. 647 * 648 * @return {@code true} if user data restore was successful, or {@code false} if a remote call 649 * shouldn't be continued. See {@link #checkBeforeRemote}. 650 * 651 * @throws InstallerException if failed to restore user data. 652 */ restoreAppDataSnapshot(String pkg, @AppIdInt int appId, String seInfo, @UserIdInt int userId, int snapshotId, int storageFlags)653 public boolean restoreAppDataSnapshot(String pkg, @AppIdInt int appId, String seInfo, 654 @UserIdInt int userId, int snapshotId, int storageFlags) throws InstallerException { 655 if (!checkBeforeRemote()) return false; 656 657 try { 658 mInstalld.restoreAppDataSnapshot(null, pkg, appId, seInfo, userId, snapshotId, 659 storageFlags); 660 return true; 661 } catch (Exception e) { 662 throw InstallerException.from(e); 663 } 664 } 665 666 /** 667 * Deletes user data snapshot of the given package. 668 * 669 * @param pkg name of the package to delete user data snapshot for. 670 * @param userId id of the user whose user data snapshot to delete. 671 * @param ceSnapshotInode inode of CE user data snapshot. 672 * @param snapshotId id of the snapshot to delete. 673 * @param storageFlags flags controlling which user data snapshot (CE or DE) to delete. 674 * 675 * @return {@code true} if user data snapshot was successfully deleted, or {@code false} if a 676 * remote call shouldn't be continued. See {@link #checkBeforeRemote}. 677 * 678 * @throws InstallerException if failed to delete user data snapshot. 679 */ destroyAppDataSnapshot(String pkg, @UserIdInt int userId, long ceSnapshotInode, int snapshotId, int storageFlags)680 public boolean destroyAppDataSnapshot(String pkg, @UserIdInt int userId, long ceSnapshotInode, 681 int snapshotId, int storageFlags) throws InstallerException { 682 if (!checkBeforeRemote()) return false; 683 684 try { 685 mInstalld.destroyAppDataSnapshot(null, pkg, userId, ceSnapshotInode, snapshotId, 686 storageFlags); 687 return true; 688 } catch (Exception e) { 689 throw InstallerException.from(e); 690 } 691 } 692 693 /** 694 * Migrates obb data from its legacy location {@code /data/media/obb} to 695 * {@code /data/media/0/Android/obb}. This call is idempotent and a fast no-op if data has 696 * already been migrated. 697 * 698 * @throws InstallerException if an error occurs. 699 */ migrateLegacyObbData()700 public boolean migrateLegacyObbData() throws InstallerException { 701 if (!checkBeforeRemote()) return false; 702 703 try { 704 mInstalld.migrateLegacyObbData(); 705 return true; 706 } catch (Exception e) { 707 throw InstallerException.from(e); 708 } 709 } 710 assertValidInstructionSet(String instructionSet)711 private static void assertValidInstructionSet(String instructionSet) 712 throws InstallerException { 713 for (String abi : Build.SUPPORTED_ABIS) { 714 if (VMRuntime.getInstructionSet(abi).equals(instructionSet)) { 715 return; 716 } 717 } 718 throw new InstallerException("Invalid instruction set: " + instructionSet); 719 } 720 compileLayouts(String apkPath, String packageName, String outDexFile, int uid)721 public boolean compileLayouts(String apkPath, String packageName, String outDexFile, int uid) { 722 try { 723 return mInstalld.compileLayouts(apkPath, packageName, outDexFile, uid); 724 } catch (RemoteException e) { 725 return false; 726 } 727 } 728 729 public static class InstallerException extends Exception { InstallerException(String detailMessage)730 public InstallerException(String detailMessage) { 731 super(detailMessage); 732 } 733 from(Exception e)734 public static InstallerException from(Exception e) throws InstallerException { 735 throw new InstallerException(e.toString()); 736 } 737 } 738 } 739