1 /* 2 * Copyright (C) 2021 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 static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; 20 import static android.content.pm.PackageManager.INSTALL_FAILED_PROCESS_NOT_DEFINED; 21 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; 22 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; 23 24 import static com.android.server.pm.PackageManagerService.DEBUG_ABI_SELECTION; 25 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING; 26 import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME; 27 import static com.android.server.pm.PackageManagerService.SCAN_AS_FULL_APP; 28 import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP; 29 import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM; 30 import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM; 31 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; 32 import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT; 33 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; 34 import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT; 35 import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR; 36 import static com.android.server.pm.PackageManagerService.SCAN_AS_VIRTUAL_PRELOAD; 37 import static com.android.server.pm.PackageManagerService.SCAN_BOOTING; 38 import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE; 39 import static com.android.server.pm.PackageManagerService.SCAN_MOVE; 40 import static com.android.server.pm.PackageManagerService.SCAN_NEW_INSTALL; 41 import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX; 42 import static com.android.server.pm.PackageManagerService.SCAN_UPDATE_TIME; 43 import static com.android.server.pm.PackageManagerService.TAG; 44 import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures; 45 import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists; 46 import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride; 47 import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime; 48 49 import android.annotation.NonNull; 50 import android.annotation.Nullable; 51 import android.content.pm.ApplicationInfo; 52 import android.content.pm.PackageManager; 53 import android.content.pm.SharedLibraryInfo; 54 import android.content.pm.SigningDetails; 55 import android.content.pm.parsing.result.ParseResult; 56 import android.content.pm.parsing.result.ParseTypeImpl; 57 import android.os.Build; 58 import android.os.Environment; 59 import android.os.Process; 60 import android.os.SystemProperties; 61 import android.os.Trace; 62 import android.os.UserHandle; 63 import android.text.TextUtils; 64 import android.util.ArrayMap; 65 import android.util.ArraySet; 66 import android.util.Log; 67 import android.util.Pair; 68 import android.util.Slog; 69 import android.util.apk.ApkSignatureVerifier; 70 import android.util.jar.StrictJarFile; 71 72 import com.android.internal.annotations.GuardedBy; 73 import com.android.internal.annotations.VisibleForTesting; 74 import com.android.internal.util.ArrayUtils; 75 import com.android.server.SystemConfig; 76 import com.android.server.pm.parsing.PackageInfoUtils; 77 import com.android.server.pm.parsing.library.PackageBackwardCompatibility; 78 import com.android.server.pm.parsing.pkg.AndroidPackage; 79 import com.android.server.pm.parsing.pkg.AndroidPackageUtils; 80 import com.android.server.pm.parsing.pkg.ParsedPackage; 81 import com.android.server.pm.pkg.PackageStateUtils; 82 import com.android.server.pm.pkg.component.ComponentMutateUtils; 83 import com.android.server.pm.pkg.component.ParsedActivity; 84 import com.android.server.pm.pkg.component.ParsedMainComponent; 85 import com.android.server.pm.pkg.component.ParsedProcess; 86 import com.android.server.pm.pkg.component.ParsedProvider; 87 import com.android.server.pm.pkg.component.ParsedService; 88 import com.android.server.pm.pkg.parsing.ParsingPackageUtils; 89 import com.android.server.utils.WatchedArraySet; 90 91 import dalvik.system.VMRuntime; 92 93 import java.io.File; 94 import java.io.IOException; 95 import java.util.ArrayList; 96 import java.util.List; 97 import java.util.Map; 98 import java.util.Objects; 99 import java.util.UUID; 100 101 /** 102 * Helper class that handles package scanning logic 103 */ 104 final class ScanPackageUtils { 105 /** 106 * Just scans the package without any side effects. 107 * 108 * @param injector injector for acquiring dependencies 109 * @param request Information about the package to be scanned 110 * @param isUnderFactoryTest Whether or not the device is under factory test 111 * @param currentTime The current time, in millis 112 * @return The results of the scan 113 */ 114 @GuardedBy("mPm.mInstallLock") 115 @VisibleForTesting 116 @NonNull scanPackageOnlyLI(@onNull ScanRequest request, PackageManagerServiceInjector injector, boolean isUnderFactoryTest, long currentTime)117 public static ScanResult scanPackageOnlyLI(@NonNull ScanRequest request, 118 PackageManagerServiceInjector injector, 119 boolean isUnderFactoryTest, long currentTime) 120 throws PackageManagerException { 121 final PackageAbiHelper packageAbiHelper = injector.getAbiHelper(); 122 ParsedPackage parsedPackage = request.mParsedPackage; 123 PackageSetting pkgSetting = request.mPkgSetting; 124 final PackageSetting disabledPkgSetting = request.mDisabledPkgSetting; 125 final PackageSetting originalPkgSetting = request.mOriginalPkgSetting; 126 final @ParsingPackageUtils.ParseFlags int parseFlags = request.mParseFlags; 127 final @PackageManagerService.ScanFlags int scanFlags = request.mScanFlags; 128 final String realPkgName = request.mRealPkgName; 129 final SharedUserSetting oldSharedUserSetting = request.mOldSharedUserSetting; 130 final SharedUserSetting sharedUserSetting = request.mSharedUserSetting; 131 final UserHandle user = request.mUser; 132 final boolean isPlatformPackage = request.mIsPlatformPackage; 133 134 List<String> changedAbiCodePath = null; 135 136 if (DEBUG_PACKAGE_SCANNING) { 137 if ((parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0) { 138 Log.d(TAG, "Scanning package " + parsedPackage.getPackageName()); 139 } 140 } 141 142 // Initialize package source and resource directories 143 final File destCodeFile = new File(parsedPackage.getPath()); 144 145 // We keep references to the derived CPU Abis from settings in oder to reuse 146 // them in the case where we're not upgrading or booting for the first time. 147 String primaryCpuAbiFromSettings = null; 148 String secondaryCpuAbiFromSettings = null; 149 boolean needToDeriveAbi = (scanFlags & SCAN_FIRST_BOOT_OR_UPGRADE) != 0; 150 if (!needToDeriveAbi) { 151 if (pkgSetting != null) { 152 // TODO(b/154610922): if it is not first boot or upgrade, we should directly use 153 // API info from existing package setting. However, stub packages currently do not 154 // preserve ABI info, thus the special condition check here. Remove the special 155 // check after we fix the stub generation. 156 if (pkgSetting.getPkg() != null && pkgSetting.getPkg().isStub()) { 157 needToDeriveAbi = true; 158 } else { 159 primaryCpuAbiFromSettings = pkgSetting.getPrimaryCpuAbi(); 160 secondaryCpuAbiFromSettings = pkgSetting.getSecondaryCpuAbi(); 161 } 162 } else { 163 // Re-scanning a system package after uninstalling updates; need to derive ABI 164 needToDeriveAbi = true; 165 } 166 } 167 168 if (pkgSetting != null && oldSharedUserSetting != sharedUserSetting) { 169 PackageManagerService.reportSettingsProblem(Log.WARN, 170 "Package " + parsedPackage.getPackageName() + " shared user changed from " 171 + (oldSharedUserSetting != null 172 ? oldSharedUserSetting.name : "<nothing>") 173 + " to " 174 + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>") 175 + "; replacing with new"); 176 pkgSetting = null; 177 } 178 179 String[] usesSdkLibraries = null; 180 if (!parsedPackage.getUsesSdkLibraries().isEmpty()) { 181 usesSdkLibraries = new String[parsedPackage.getUsesSdkLibraries().size()]; 182 parsedPackage.getUsesSdkLibraries().toArray(usesSdkLibraries); 183 } 184 185 String[] usesStaticLibraries = null; 186 if (!parsedPackage.getUsesStaticLibraries().isEmpty()) { 187 usesStaticLibraries = new String[parsedPackage.getUsesStaticLibraries().size()]; 188 parsedPackage.getUsesStaticLibraries().toArray(usesStaticLibraries); 189 } 190 191 final UUID newDomainSetId = injector.getDomainVerificationManagerInternal().generateNewId(); 192 193 // TODO(b/135203078): Remove appInfoFlag usage in favor of individually assigned booleans 194 // to avoid adding something that's unsupported due to lack of state, since it's called 195 // with null. 196 final boolean createNewPackage = (pkgSetting == null); 197 if (createNewPackage) { 198 final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; 199 final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0; 200 201 // Flags contain system values stored in the server variant of AndroidPackage, 202 // and so the server-side PackageInfoUtils is still called, even without a 203 // PackageSetting to pass in. 204 int pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, null); 205 int pkgPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(parsedPackage, null); 206 207 // REMOVE SharedUserSetting from method; update in a separate call 208 pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(), 209 originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting, 210 destCodeFile, parsedPackage.getNativeLibraryRootDir(), 211 AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage), 212 AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage), 213 parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user, 214 true /*allowInstall*/, instantApp, virtualPreload, 215 UserManagerService.getInstance(), usesSdkLibraries, 216 parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries, 217 parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(), 218 newDomainSetId); 219 } else { 220 // make a deep copy to avoid modifying any existing system state. 221 pkgSetting = new PackageSetting(pkgSetting); 222 pkgSetting.setPkg(parsedPackage); 223 224 // REMOVE SharedUserSetting from method; update in a separate call. 225 // 226 // TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi, 227 // secondaryCpuAbi are not known at this point so we always update them 228 // to null here, only to reset them at a later point. 229 Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, oldSharedUserSetting, 230 sharedUserSetting, destCodeFile, parsedPackage.getNativeLibraryDir(), 231 AndroidPackageUtils.getPrimaryCpuAbi(parsedPackage, pkgSetting), 232 AndroidPackageUtils.getSecondaryCpuAbi(parsedPackage, pkgSetting), 233 PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting), 234 PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting), 235 UserManagerService.getInstance(), 236 usesSdkLibraries, parsedPackage.getUsesSdkLibrariesVersionsMajor(), 237 usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(), 238 parsedPackage.getMimeGroups(), newDomainSetId); 239 } 240 if (createNewPackage && originalPkgSetting != null) { 241 // This is the initial transition from the original package, so, 242 // fix up the new package's name now. We must do this after looking 243 // up the package under its new name, so getPackageLP takes care of 244 // fiddling things correctly. 245 parsedPackage.setPackageName(originalPkgSetting.getPackageName()); 246 247 // File a report about this. 248 String msg = "New package " + pkgSetting.getRealName() 249 + " renamed to replace old package " + pkgSetting.getPackageName(); 250 PackageManagerService.reportSettingsProblem(Log.WARN, msg); 251 } 252 253 final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier()); 254 // for existing packages, change the install state; but, only if it's explicitly specified 255 if (!createNewPackage) { 256 final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0; 257 final boolean fullApp = (scanFlags & SCAN_AS_FULL_APP) != 0; 258 setInstantAppForUser(injector, pkgSetting, userId, instantApp, fullApp); 259 } 260 // TODO(patb): see if we can do away with disabled check here. 261 if (disabledPkgSetting != null 262 || (0 != (scanFlags & SCAN_NEW_INSTALL) 263 && pkgSetting != null && pkgSetting.isSystem())) { 264 pkgSetting.getPkgState().setUpdatedSystemApp(true); 265 } 266 267 parsedPackage.setSeInfo(SELinuxMMAC.getSeInfo(parsedPackage, sharedUserSetting, 268 injector.getCompatibility())); 269 270 if (parsedPackage.isSystem()) { 271 configurePackageComponents(parsedPackage); 272 } 273 274 final String cpuAbiOverride = deriveAbiOverride(request.mCpuAbiOverride); 275 final boolean isUpdatedSystemApp = pkgSetting.getPkgState().isUpdatedSystemApp(); 276 277 final File appLib32InstallDir = getAppLib32InstallDir(); 278 if ((scanFlags & SCAN_NEW_INSTALL) == 0) { 279 if (needToDeriveAbi) { 280 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi"); 281 final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi = 282 packageAbiHelper.derivePackageAbi(parsedPackage, isUpdatedSystemApp, 283 cpuAbiOverride, appLib32InstallDir); 284 derivedAbi.first.applyTo(parsedPackage); 285 derivedAbi.second.applyTo(parsedPackage); 286 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 287 288 // Some system apps still use directory structure for native libraries 289 // in which case we might end up not detecting abi solely based on apk 290 // structure. Try to detect abi based on directory structure. 291 292 String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage); 293 if (parsedPackage.isSystem() && !isUpdatedSystemApp 294 && pkgRawPrimaryCpuAbi == null) { 295 final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis( 296 parsedPackage); 297 abis.applyTo(parsedPackage); 298 abis.applyTo(pkgSetting); 299 final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = 300 packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, 301 isUpdatedSystemApp, appLib32InstallDir); 302 nativeLibraryPaths.applyTo(parsedPackage); 303 } 304 } else { 305 // This is not a first boot or an upgrade, don't bother deriving the 306 // ABI during the scan. Instead, trust the value that was stored in the 307 // package setting. 308 parsedPackage.setPrimaryCpuAbi(primaryCpuAbiFromSettings) 309 .setSecondaryCpuAbi(secondaryCpuAbiFromSettings); 310 311 final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = 312 packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, 313 isUpdatedSystemApp, appLib32InstallDir); 314 nativeLibraryPaths.applyTo(parsedPackage); 315 316 if (DEBUG_ABI_SELECTION) { 317 Slog.i(TAG, "Using ABIS and native lib paths from settings : " 318 + parsedPackage.getPackageName() + " " 319 + AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage) 320 + ", " 321 + AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage)); 322 } 323 } 324 } else { 325 if ((scanFlags & SCAN_MOVE) != 0) { 326 // We haven't run dex-opt for this move (since we've moved the compiled output too) 327 // but we already have this packages package info in the PackageSetting. We just 328 // use that and derive the native library path based on the new code path. 329 parsedPackage.setPrimaryCpuAbi(pkgSetting.getPrimaryCpuAbi()) 330 .setSecondaryCpuAbi(pkgSetting.getSecondaryCpuAbi()); 331 } 332 333 // Set native library paths again. For moves, the path will be updated based on the 334 // ABIs we've determined above. For non-moves, the path will be updated based on the 335 // ABIs we determined during compilation, but the path will depend on the final 336 // package path (after the rename away from the stage path). 337 final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths = 338 packageAbiHelper.deriveNativeLibraryPaths(parsedPackage, isUpdatedSystemApp, 339 appLib32InstallDir); 340 nativeLibraryPaths.applyTo(parsedPackage); 341 } 342 343 // This is a special case for the "system" package, where the ABI is 344 // dictated by the zygote configuration (and init.rc). We should keep track 345 // of this ABI so that we can deal with "normal" applications that run under 346 // the same UID correctly. 347 if (isPlatformPackage) { 348 parsedPackage.setPrimaryCpuAbi(VMRuntime.getRuntime().is64Bit() 349 ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]); 350 } 351 352 // If there's a mismatch between the abi-override in the package setting 353 // and the abiOverride specified for the install. Warn about this because we 354 // would've already compiled the app without taking the package setting into 355 // account. 356 if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) { 357 if (cpuAbiOverride == null) { 358 Slog.w(TAG, "Ignoring persisted ABI override for package " 359 + parsedPackage.getPackageName()); 360 } 361 } 362 363 pkgSetting.setPrimaryCpuAbi(AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage)) 364 .setSecondaryCpuAbi(AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage)) 365 .setCpuAbiOverride(cpuAbiOverride); 366 367 if (DEBUG_ABI_SELECTION) { 368 Slog.d(TAG, "Resolved nativeLibraryRoot for " + parsedPackage.getPackageName() 369 + " to root=" + parsedPackage.getNativeLibraryRootDir() 370 + ", to dir=" + parsedPackage.getNativeLibraryDir() 371 + ", isa=" + parsedPackage.isNativeLibraryRootRequiresIsa()); 372 } 373 374 // Push the derived path down into PackageSettings so we know what to 375 // clean up at uninstall time. 376 pkgSetting.setLegacyNativeLibraryPath(parsedPackage.getNativeLibraryRootDir()); 377 378 if (DEBUG_ABI_SELECTION) { 379 Log.d(TAG, "Abis for package[" + parsedPackage.getPackageName() + "] are" 380 + " primary=" + pkgSetting.getPrimaryCpuAbi() 381 + " secondary=" + pkgSetting.getSecondaryCpuAbi() 382 + " abiOverride=" + pkgSetting.getCpuAbiOverride()); 383 } 384 385 if ((scanFlags & SCAN_BOOTING) == 0 && oldSharedUserSetting != null) { 386 // We don't do this here during boot because we can do it all 387 // at once after scanning all existing packages. 388 // 389 // We also do this *before* we perform dexopt on this package, so that 390 // we can avoid redundant dexopts, and also to make sure we've got the 391 // code and package path correct. 392 changedAbiCodePath = applyAdjustedAbiToSharedUser(oldSharedUserSetting, 393 parsedPackage, packageAbiHelper.getAdjustedAbiForSharedUser( 394 oldSharedUserSetting.getPackageStates(), parsedPackage)); 395 } 396 397 parsedPackage.setFactoryTest(isUnderFactoryTest && parsedPackage.getRequestedPermissions() 398 .contains(android.Manifest.permission.FACTORY_TEST)); 399 400 if (parsedPackage.isSystem()) { 401 pkgSetting.setIsOrphaned(true); 402 } 403 404 // Take care of first install / last update times. 405 final long scanFileTime = getLastModifiedTime(parsedPackage); 406 final long existingFirstInstallTime = userId == UserHandle.USER_ALL 407 ? PackageStateUtils.getEarliestFirstInstallTime(pkgSetting.getUserStates()) 408 : pkgSetting.readUserState(userId).getFirstInstallTime(); 409 if (currentTime != 0) { 410 if (existingFirstInstallTime == 0) { 411 pkgSetting.setFirstInstallTime(currentTime, userId) 412 .setLastUpdateTime(currentTime); 413 } else if ((scanFlags & SCAN_UPDATE_TIME) != 0) { 414 pkgSetting.setLastUpdateTime(currentTime); 415 } 416 } else if (existingFirstInstallTime == 0) { 417 // We need *something*. Take time stamp of the file. 418 pkgSetting.setFirstInstallTime(scanFileTime, userId) 419 .setLastUpdateTime(scanFileTime); 420 } else if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0) { 421 if (scanFileTime != pkgSetting.getLastModifiedTime()) { 422 // A package on the system image has changed; consider this 423 // to be an update. 424 pkgSetting.setLastUpdateTime(scanFileTime); 425 } 426 } 427 pkgSetting.setLastModifiedTime(scanFileTime); 428 // TODO(b/135203078): Remove, move to constructor 429 pkgSetting.setPkg(parsedPackage) 430 .setPkgFlags(PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting), 431 PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting)); 432 if (parsedPackage.getLongVersionCode() != pkgSetting.getVersionCode()) { 433 pkgSetting.setLongVersionCode(parsedPackage.getLongVersionCode()); 434 } 435 // Update volume if needed 436 final String volumeUuid = parsedPackage.getVolumeUuid(); 437 if (!Objects.equals(volumeUuid, pkgSetting.getVolumeUuid())) { 438 Slog.i(PackageManagerService.TAG, 439 "Update" + (pkgSetting.isSystem() ? " system" : "") 440 + " package " + parsedPackage.getPackageName() 441 + " volume from " + pkgSetting.getVolumeUuid() 442 + " to " + volumeUuid); 443 pkgSetting.setVolumeUuid(volumeUuid); 444 } 445 446 SharedLibraryInfo sdkLibraryInfo = null; 447 if (!TextUtils.isEmpty(parsedPackage.getSdkLibName())) { 448 sdkLibraryInfo = AndroidPackageUtils.createSharedLibraryForSdk(parsedPackage); 449 } 450 SharedLibraryInfo staticSharedLibraryInfo = null; 451 if (!TextUtils.isEmpty(parsedPackage.getStaticSharedLibName())) { 452 staticSharedLibraryInfo = 453 AndroidPackageUtils.createSharedLibraryForStatic(parsedPackage); 454 } 455 List<SharedLibraryInfo> dynamicSharedLibraryInfos = null; 456 if (!ArrayUtils.isEmpty(parsedPackage.getLibraryNames())) { 457 dynamicSharedLibraryInfos = new ArrayList<>(parsedPackage.getLibraryNames().size()); 458 for (String name : parsedPackage.getLibraryNames()) { 459 dynamicSharedLibraryInfos.add( 460 AndroidPackageUtils.createSharedLibraryForDynamic(parsedPackage, name)); 461 } 462 } 463 464 return new ScanResult(request, true, pkgSetting, changedAbiCodePath, 465 !createNewPackage /* existingSettingCopied */, 466 Process.INVALID_UID /* previousAppId */ , sdkLibraryInfo, 467 staticSharedLibraryInfo, dynamicSharedLibraryInfos); 468 } 469 470 /** 471 * Returns the actual scan flags depending upon the state of the other settings. 472 * <p>Updated system applications will not have the following flags set 473 * by default and need to be adjusted after the fact: 474 * <ul> 475 * <li>{@link PackageManagerService.SCAN_AS_SYSTEM}</li> 476 * <li>{@link PackageManagerService.SCAN_AS_PRIVILEGED}</li> 477 * <li>{@link PackageManagerService.SCAN_AS_OEM}</li> 478 * <li>{@link PackageManagerService.SCAN_AS_VENDOR}</li> 479 * <li>{@link PackageManagerService.SCAN_AS_PRODUCT}</li> 480 * <li>{@link PackageManagerService.SCAN_AS_SYSTEM_EXT}</li> 481 * <li>{@link PackageManagerService.SCAN_AS_INSTANT_APP}</li> 482 * <li>{@link PackageManagerService.SCAN_AS_VIRTUAL_PRELOAD}</li> 483 * <li>{@link PackageManagerService.SCAN_AS_ODM}</li> 484 * </ul> 485 */ adjustScanFlagsWithPackageSetting( @ackageManagerService.ScanFlags int scanFlags, PackageSetting pkgSetting, PackageSetting disabledPkgSetting, UserHandle user)486 public static @PackageManagerService.ScanFlags int adjustScanFlagsWithPackageSetting( 487 @PackageManagerService.ScanFlags int scanFlags, 488 PackageSetting pkgSetting, PackageSetting disabledPkgSetting, UserHandle user) { 489 490 // TODO(patb): Do away entirely with disabledPkgSetting here. PkgSetting will always contain 491 // the correct isSystem value now that we don't disable system packages before scan. 492 final PackageSetting systemPkgSetting = 493 (scanFlags & SCAN_NEW_INSTALL) != 0 && disabledPkgSetting == null 494 && pkgSetting != null && pkgSetting.isSystem() 495 ? pkgSetting 496 : disabledPkgSetting; 497 if (systemPkgSetting != null) { 498 // updated system application, must at least have SCAN_AS_SYSTEM 499 scanFlags |= SCAN_AS_SYSTEM; 500 if ((systemPkgSetting.getPrivateFlags() 501 & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0) { 502 scanFlags |= SCAN_AS_PRIVILEGED; 503 } 504 if ((systemPkgSetting.getPrivateFlags() 505 & ApplicationInfo.PRIVATE_FLAG_OEM) != 0) { 506 scanFlags |= SCAN_AS_OEM; 507 } 508 if ((systemPkgSetting.getPrivateFlags() 509 & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) { 510 scanFlags |= SCAN_AS_VENDOR; 511 } 512 if ((systemPkgSetting.getPrivateFlags() 513 & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) { 514 scanFlags |= SCAN_AS_PRODUCT; 515 } 516 if ((systemPkgSetting.getPrivateFlags() 517 & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0) { 518 scanFlags |= SCAN_AS_SYSTEM_EXT; 519 } 520 if ((systemPkgSetting.getPrivateFlags() 521 & ApplicationInfo.PRIVATE_FLAG_ODM) != 0) { 522 scanFlags |= SCAN_AS_ODM; 523 } 524 } 525 if (pkgSetting != null) { 526 final int userId = ((user == null) ? 0 : user.getIdentifier()); 527 if (pkgSetting.getInstantApp(userId)) { 528 scanFlags |= SCAN_AS_INSTANT_APP; 529 } 530 if (pkgSetting.getVirtualPreload(userId)) { 531 scanFlags |= SCAN_AS_VIRTUAL_PRELOAD; 532 } 533 } 534 535 return scanFlags; 536 } 537 538 /** 539 * Enforces code policy for the package. This ensures that if an APK has 540 * declared hasCode="true" in its manifest that the APK actually contains 541 * code. 542 * 543 * @throws PackageManagerException If bytecode could not be found when it should exist 544 */ assertCodePolicy(AndroidPackage pkg)545 public static void assertCodePolicy(AndroidPackage pkg) 546 throws PackageManagerException { 547 final boolean shouldHaveCode = pkg.isHasCode(); 548 if (shouldHaveCode && !apkHasCode(pkg.getBaseApkPath())) { 549 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 550 "Package " + pkg.getBaseApkPath() + " code is missing"); 551 } 552 553 if (!ArrayUtils.isEmpty(pkg.getSplitCodePaths())) { 554 for (int i = 0; i < pkg.getSplitCodePaths().length; i++) { 555 final boolean splitShouldHaveCode = 556 (pkg.getSplitFlags()[i] & ApplicationInfo.FLAG_HAS_CODE) != 0; 557 if (splitShouldHaveCode && !apkHasCode(pkg.getSplitCodePaths()[i])) { 558 throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 559 "Package " + pkg.getSplitCodePaths()[i] + " code is missing"); 560 } 561 } 562 } 563 } 564 assertStaticSharedLibraryIsValid(AndroidPackage pkg, @PackageManagerService.ScanFlags int scanFlags)565 public static void assertStaticSharedLibraryIsValid(AndroidPackage pkg, 566 @PackageManagerService.ScanFlags int scanFlags) throws PackageManagerException { 567 // Static shared libraries should have at least O target SDK 568 if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.O) { 569 throw new PackageManagerException( 570 "Packages declaring static-shared libs must target O SDK or higher"); 571 } 572 573 // Package declaring static a shared lib cannot be instant apps 574 if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) { 575 throw new PackageManagerException( 576 "Packages declaring static-shared libs cannot be instant apps"); 577 } 578 579 // Package declaring static a shared lib cannot be renamed since the package 580 // name is synthetic and apps can't code around package manager internals. 581 if (!ArrayUtils.isEmpty(pkg.getOriginalPackages())) { 582 throw new PackageManagerException( 583 "Packages declaring static-shared libs cannot be renamed"); 584 } 585 586 // Package declaring static a shared lib cannot declare dynamic libs 587 if (!ArrayUtils.isEmpty(pkg.getLibraryNames())) { 588 throw new PackageManagerException( 589 "Packages declaring static-shared libs cannot declare dynamic libs"); 590 } 591 592 // Package declaring static a shared lib cannot declare shared users 593 if (pkg.getSharedUserId() != null) { 594 throw new PackageManagerException( 595 "Packages declaring static-shared libs cannot declare shared users"); 596 } 597 598 // Static shared libs cannot declare activities 599 if (!pkg.getActivities().isEmpty()) { 600 throw new PackageManagerException( 601 "Static shared libs cannot declare activities"); 602 } 603 604 // Static shared libs cannot declare services 605 if (!pkg.getServices().isEmpty()) { 606 throw new PackageManagerException( 607 "Static shared libs cannot declare services"); 608 } 609 610 // Static shared libs cannot declare providers 611 if (!pkg.getProviders().isEmpty()) { 612 throw new PackageManagerException( 613 "Static shared libs cannot declare content providers"); 614 } 615 616 // Static shared libs cannot declare receivers 617 if (!pkg.getReceivers().isEmpty()) { 618 throw new PackageManagerException( 619 "Static shared libs cannot declare broadcast receivers"); 620 } 621 622 // Static shared libs cannot declare permission groups 623 if (!pkg.getPermissionGroups().isEmpty()) { 624 throw new PackageManagerException( 625 "Static shared libs cannot declare permission groups"); 626 } 627 628 // Static shared libs cannot declare attributions 629 if (!pkg.getAttributions().isEmpty()) { 630 throw new PackageManagerException( 631 "Static shared libs cannot declare features"); 632 } 633 634 // Static shared libs cannot declare permissions 635 if (!pkg.getPermissions().isEmpty()) { 636 throw new PackageManagerException( 637 "Static shared libs cannot declare permissions"); 638 } 639 640 // Static shared libs cannot declare protected broadcasts 641 if (!pkg.getProtectedBroadcasts().isEmpty()) { 642 throw new PackageManagerException( 643 "Static shared libs cannot declare protected broadcasts"); 644 } 645 646 // Static shared libs cannot be overlay targets 647 if (pkg.getOverlayTarget() != null) { 648 throw new PackageManagerException( 649 "Static shared libs cannot be overlay targets"); 650 } 651 } 652 assertProcessesAreValid(AndroidPackage pkg)653 public static void assertProcessesAreValid(AndroidPackage pkg) throws PackageManagerException { 654 final Map<String, ParsedProcess> procs = pkg.getProcesses(); 655 if (!procs.isEmpty()) { 656 if (!procs.containsKey(pkg.getProcessName())) { 657 throw new PackageManagerException( 658 INSTALL_FAILED_PROCESS_NOT_DEFINED, 659 "Can't install because application tag's process attribute " 660 + pkg.getProcessName() 661 + " (in package " + pkg.getPackageName() 662 + ") is not included in the <processes> list"); 663 } 664 assertPackageProcesses(pkg, pkg.getActivities(), procs, "activity"); 665 assertPackageProcesses(pkg, pkg.getServices(), procs, "service"); 666 assertPackageProcesses(pkg, pkg.getReceivers(), procs, "receiver"); 667 assertPackageProcesses(pkg, pkg.getProviders(), procs, "provider"); 668 } 669 } 670 assertPackageProcesses(AndroidPackage pkg, List<T> components, Map<String, ParsedProcess> procs, String compName)671 private static <T extends ParsedMainComponent> void assertPackageProcesses(AndroidPackage pkg, 672 List<T> components, Map<String, ParsedProcess> procs, String compName) 673 throws PackageManagerException { 674 if (components == null) { 675 return; 676 } 677 for (int i = components.size() - 1; i >= 0; i--) { 678 final ParsedMainComponent component = components.get(i); 679 if (!procs.containsKey(component.getProcessName())) { 680 throw new PackageManagerException( 681 INSTALL_FAILED_PROCESS_NOT_DEFINED, 682 "Can't install because " + compName + " " + component.getClassName() 683 + "'s process attribute " + component.getProcessName() 684 + " (in package " + pkg.getPackageName() 685 + ") is not included in the <processes> list"); 686 } 687 } 688 } 689 assertMinSignatureSchemeIsValid(AndroidPackage pkg, @ParsingPackageUtils.ParseFlags int parseFlags)690 public static void assertMinSignatureSchemeIsValid(AndroidPackage pkg, 691 @ParsingPackageUtils.ParseFlags int parseFlags) throws PackageManagerException { 692 int minSignatureSchemeVersion = 693 ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk( 694 pkg.getTargetSdkVersion()); 695 if (pkg.getSigningDetails().getSignatureSchemeVersion() 696 < minSignatureSchemeVersion) { 697 throw new PackageManagerException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, 698 "No signature found in package of version " + minSignatureSchemeVersion 699 + " or newer for package " + pkg.getPackageName()); 700 } 701 } 702 703 /** 704 * Returns the "real" name of the package. 705 * <p>This may differ from the package's actual name if the application has already 706 * been installed under one of this package's original names. 707 */ getRealPackageName(@onNull AndroidPackage pkg, @Nullable String renamedPkgName)708 public static @Nullable String getRealPackageName(@NonNull AndroidPackage pkg, 709 @Nullable String renamedPkgName) { 710 if (isPackageRenamed(pkg, renamedPkgName)) { 711 return AndroidPackageUtils.getRealPackageOrNull(pkg); 712 } 713 return null; 714 } 715 716 /** Returns {@code true} if the package has been renamed. Otherwise, {@code false}. */ isPackageRenamed(@onNull AndroidPackage pkg, @Nullable String renamedPkgName)717 public static boolean isPackageRenamed(@NonNull AndroidPackage pkg, 718 @Nullable String renamedPkgName) { 719 return pkg.getOriginalPackages().contains(renamedPkgName); 720 } 721 722 /** 723 * Renames the package if it was installed under a different name. 724 * <p>When we've already installed the package under an original name, update 725 * the new package so we can continue to have the old name. 726 */ ensurePackageRenamed(@onNull ParsedPackage parsedPackage, @NonNull String renamedPackageName)727 public static void ensurePackageRenamed(@NonNull ParsedPackage parsedPackage, 728 @NonNull String renamedPackageName) { 729 if (!parsedPackage.getOriginalPackages().contains(renamedPackageName) 730 || parsedPackage.getPackageName().equals(renamedPackageName)) { 731 return; 732 } 733 parsedPackage.setPackageName(renamedPackageName); 734 } 735 736 /** 737 * Returns {@code true} if the given file contains code. Otherwise {@code false}. 738 */ apkHasCode(String fileName)739 public static boolean apkHasCode(String fileName) { 740 StrictJarFile jarFile = null; 741 try { 742 jarFile = new StrictJarFile(fileName, 743 false /*verify*/, false /*signatureSchemeRollbackProtectionsEnforced*/); 744 return jarFile.findEntry("classes.dex") != null; 745 } catch (IOException ignore) { 746 } finally { 747 try { 748 if (jarFile != null) { 749 jarFile.close(); 750 } 751 } catch (IOException ignore) { 752 } 753 } 754 return false; 755 } 756 757 /** 758 * Sets the enabled state of components configured through {@link SystemConfig}. 759 * This modifies the {@link PackageSetting} object. 760 * 761 * TODO(b/135203078): Move this to package parsing 762 **/ configurePackageComponents(AndroidPackage pkg)763 public static void configurePackageComponents(AndroidPackage pkg) { 764 final ArrayMap<String, Boolean> componentsEnabledStates = SystemConfig.getInstance() 765 .getComponentsEnabledStates(pkg.getPackageName()); 766 if (componentsEnabledStates == null) { 767 return; 768 } 769 770 for (int i = ArrayUtils.size(pkg.getActivities()) - 1; i >= 0; i--) { 771 final ParsedActivity component = pkg.getActivities().get(i); 772 final Boolean enabled = componentsEnabledStates.get(component.getName()); 773 if (enabled != null) { 774 ComponentMutateUtils.setEnabled(component, enabled); 775 } 776 } 777 778 for (int i = ArrayUtils.size(pkg.getReceivers()) - 1; i >= 0; i--) { 779 final ParsedActivity component = pkg.getReceivers().get(i); 780 final Boolean enabled = componentsEnabledStates.get(component.getName()); 781 if (enabled != null) { 782 ComponentMutateUtils.setEnabled(component, enabled); 783 } 784 } 785 786 for (int i = ArrayUtils.size(pkg.getProviders()) - 1; i >= 0; i--) { 787 final ParsedProvider component = pkg.getProviders().get(i); 788 final Boolean enabled = componentsEnabledStates.get(component.getName()); 789 if (enabled != null) { 790 ComponentMutateUtils.setEnabled(component, enabled); 791 } 792 } 793 794 for (int i = ArrayUtils.size(pkg.getServices()) - 1; i >= 0; i--) { 795 final ParsedService component = pkg.getServices().get(i); 796 final Boolean enabled = componentsEnabledStates.get(component.getName()); 797 if (enabled != null) { 798 ComponentMutateUtils.setEnabled(component, enabled); 799 } 800 } 801 } 802 getVendorPartitionVersion()803 public static int getVendorPartitionVersion() { 804 final String version = SystemProperties.get("ro.vndk.version"); 805 if (!version.isEmpty()) { 806 try { 807 return Integer.parseInt(version); 808 } catch (NumberFormatException ignore) { 809 if (ArrayUtils.contains(Build.VERSION.ACTIVE_CODENAMES, version)) { 810 return Build.VERSION_CODES.CUR_DEVELOPMENT; 811 } 812 } 813 } 814 return Build.VERSION_CODES.P; 815 } 816 817 /** 818 * Applies policy to the parsed package based upon the given policy flags. 819 * Ensures the package is in a good state. 820 * <p> 821 * Implementation detail: This method must NOT have any side effect. It would 822 * ideally be static, but, it requires locks to read system state. 823 */ applyPolicy(ParsedPackage parsedPackage, final @PackageManagerService.ScanFlags int scanFlags, AndroidPackage platformPkg, boolean isUpdatedSystemApp)824 public static void applyPolicy(ParsedPackage parsedPackage, 825 final @PackageManagerService.ScanFlags int scanFlags, AndroidPackage platformPkg, 826 boolean isUpdatedSystemApp) { 827 if ((scanFlags & SCAN_AS_SYSTEM) != 0) { 828 parsedPackage.setSystem(true); 829 // TODO(b/135203078): Can this be done in PackageParser? Or just inferred when the flag 830 // is set during parse. 831 if (parsedPackage.isDirectBootAware()) { 832 parsedPackage.setAllComponentsDirectBootAware(true); 833 } 834 if (compressedFileExists(parsedPackage.getPath())) { 835 parsedPackage.setStub(true); 836 } 837 } else { 838 parsedPackage 839 // Non system apps cannot mark any broadcast as protected 840 .clearProtectedBroadcasts() 841 // non system apps can't be flagged as core 842 .setCoreApp(false) 843 // clear flags not applicable to regular apps 844 .setPersistent(false) 845 .setDefaultToDeviceProtectedStorage(false) 846 .setDirectBootAware(false) 847 // non system apps can't have permission priority 848 .capPermissionPriorities(); 849 } 850 if ((scanFlags & SCAN_AS_PRIVILEGED) == 0) { 851 parsedPackage 852 .markNotActivitiesAsNotExportedIfSingleUser(); 853 } 854 855 parsedPackage.setPrivileged((scanFlags & SCAN_AS_PRIVILEGED) != 0) 856 .setOem((scanFlags & SCAN_AS_OEM) != 0) 857 .setVendor((scanFlags & SCAN_AS_VENDOR) != 0) 858 .setProduct((scanFlags & SCAN_AS_PRODUCT) != 0) 859 .setSystemExt((scanFlags & SCAN_AS_SYSTEM_EXT) != 0) 860 .setOdm((scanFlags & SCAN_AS_ODM) != 0); 861 862 // Check if the package is signed with the same key as the platform package. 863 parsedPackage.setSignedWithPlatformKey( 864 (PLATFORM_PACKAGE_NAME.equals(parsedPackage.getPackageName()) 865 || (platformPkg != null && compareSignatures( 866 platformPkg.getSigningDetails().getSignatures(), 867 parsedPackage.getSigningDetails().getSignatures() 868 ) == PackageManager.SIGNATURE_MATCH)) 869 ); 870 871 if (!parsedPackage.isSystem()) { 872 // Only system apps can use these features. 873 parsedPackage.clearOriginalPackages() 874 .clearAdoptPermissions(); 875 } 876 877 PackageBackwardCompatibility.modifySharedLibraries(parsedPackage, isUpdatedSystemApp); 878 } 879 880 /** 881 * Applies the adjusted ABI calculated by 882 * {@link PackageAbiHelper#getAdjustedAbiForSharedUser(ArraySet, AndroidPackage)} to all 883 * relevant packages and settings. 884 * @param sharedUserSetting The {@code SharedUserSetting} to adjust 885 * @param scannedPackage the package being scanned or null 886 * @param adjustedAbi the adjusted ABI calculated by {@link PackageAbiHelper} 887 * @return the list of code paths that belong to packages that had their ABIs adjusted. 888 */ applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting, ParsedPackage scannedPackage, String adjustedAbi)889 public static List<String> applyAdjustedAbiToSharedUser(SharedUserSetting sharedUserSetting, 890 ParsedPackage scannedPackage, String adjustedAbi) { 891 if (scannedPackage != null) { 892 scannedPackage.setPrimaryCpuAbi(adjustedAbi); 893 } 894 List<String> changedAbiCodePath = null; 895 final WatchedArraySet<PackageSetting> sharedUserPackageSettings = 896 sharedUserSetting.getPackageSettings(); 897 for (int i = 0; i < sharedUserPackageSettings.size(); i++) { 898 PackageSetting ps = sharedUserPackageSettings.valueAt(i); 899 if (scannedPackage == null 900 || !scannedPackage.getPackageName().equals(ps.getPackageName())) { 901 if (ps.getPrimaryCpuAbi() != null) { 902 continue; 903 } 904 905 ps.setPrimaryCpuAbi(adjustedAbi); 906 ps.onChanged(); 907 if (ps.getPkg() != null) { 908 if (!TextUtils.equals(adjustedAbi, 909 AndroidPackageUtils.getRawPrimaryCpuAbi(ps.getPkg()))) { 910 if (DEBUG_ABI_SELECTION) { 911 Slog.i(TAG, 912 "Adjusting ABI for " + ps.getPackageName() + " to " 913 + adjustedAbi + " (scannedPackage=" 914 + (scannedPackage != null ? scannedPackage : "null") 915 + ")"); 916 } 917 if (changedAbiCodePath == null) { 918 changedAbiCodePath = new ArrayList<>(); 919 } 920 changedAbiCodePath.add(ps.getPathString()); 921 } 922 } 923 } 924 } 925 return changedAbiCodePath; 926 } 927 collectCertificatesLI(PackageSetting ps, ParsedPackage parsedPackage, Settings.VersionInfo settingsVersionForPackage, boolean forceCollect, boolean skipVerify, boolean isPreNMR1Upgrade)928 public static void collectCertificatesLI(PackageSetting ps, ParsedPackage parsedPackage, 929 Settings.VersionInfo settingsVersionForPackage, boolean forceCollect, 930 boolean skipVerify, boolean isPreNMR1Upgrade) 931 throws PackageManagerException { 932 // When upgrading from pre-N MR1, verify the package time stamp using the package 933 // directory and not the APK file. 934 final long lastModifiedTime = isPreNMR1Upgrade 935 ? new File(parsedPackage.getPath()).lastModified() 936 : getLastModifiedTime(parsedPackage); 937 if (ps != null && !forceCollect 938 && ps.getPathString().equals(parsedPackage.getPath()) 939 && ps.getLastModifiedTime() == lastModifiedTime 940 && !ReconcilePackageUtils.isCompatSignatureUpdateNeeded(settingsVersionForPackage) 941 && !ReconcilePackageUtils.isRecoverSignatureUpdateNeeded( 942 settingsVersionForPackage)) { 943 if (ps.getSigningDetails().getSignatures() != null 944 && ps.getSigningDetails().getSignatures().length != 0 945 && ps.getSigningDetails().getSignatureSchemeVersion() 946 != SigningDetails.SignatureSchemeVersion.UNKNOWN) { 947 // Optimization: reuse the existing cached signing data 948 // if the package appears to be unchanged. 949 parsedPackage.setSigningDetails( 950 new SigningDetails(ps.getSigningDetails())); 951 return; 952 } 953 954 Slog.w(TAG, "PackageSetting for " + ps.getPackageName() 955 + " is missing signatures. Collecting certs again to recover them."); 956 } else { 957 Slog.i(TAG, parsedPackage.getPath() + " changed; collecting certs" 958 + (forceCollect ? " (forced)" : "")); 959 } 960 961 try { 962 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates"); 963 final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); 964 final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails( 965 input, parsedPackage, skipVerify); 966 if (result.isError()) { 967 throw new PackageManagerException( 968 result.getErrorCode(), result.getErrorMessage(), result.getException()); 969 } 970 parsedPackage.setSigningDetails(result.getResult()); 971 } finally { 972 Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); 973 } 974 } 975 setInstantAppForUser(PackageManagerServiceInjector injector, PackageSetting pkgSetting, int userId, boolean instantApp, boolean fullApp)976 public static void setInstantAppForUser(PackageManagerServiceInjector injector, 977 PackageSetting pkgSetting, int userId, boolean instantApp, boolean fullApp) { 978 // no state specified; do nothing 979 if (!instantApp && !fullApp) { 980 return; 981 } 982 if (userId != UserHandle.USER_ALL) { 983 if (instantApp && !pkgSetting.getInstantApp(userId)) { 984 pkgSetting.setInstantApp(true /*instantApp*/, userId); 985 } else if (fullApp && pkgSetting.getInstantApp(userId)) { 986 pkgSetting.setInstantApp(false /*instantApp*/, userId); 987 } 988 } else { 989 for (int currentUserId : injector.getUserManagerInternal().getUserIds()) { 990 if (instantApp && !pkgSetting.getInstantApp(currentUserId)) { 991 pkgSetting.setInstantApp(true /*instantApp*/, currentUserId); 992 } else if (fullApp && pkgSetting.getInstantApp(currentUserId)) { 993 pkgSetting.setInstantApp(false /*instantApp*/, currentUserId); 994 } 995 } 996 } 997 } 998 999 /** Directory where installed application's 32-bit native libraries are copied. */ getAppLib32InstallDir()1000 public static File getAppLib32InstallDir() { 1001 return new File(Environment.getDataDirectory(), "app-lib"); 1002 } 1003 } 1004