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