Merge "[pm] extract InstallParams from PackageManagerService class"
This commit is contained in:
35
services/core/java/com/android/server/pm/CommitRequest.java
Normal file
35
services/core/java/com/android/server/pm/CommitRequest.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Package state to commit to memory and disk after reconciliation has completed.
|
||||
*/
|
||||
final class CommitRequest {
|
||||
final Map<String, ReconciledPackage> mReconciledPackages;
|
||||
@NonNull final int[] mAllUsers;
|
||||
|
||||
CommitRequest(Map<String, ReconciledPackage> reconciledPackages,
|
||||
@NonNull int[] allUsers) {
|
||||
mReconciledPackages = reconciledPackages;
|
||||
mAllUsers = allUsers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.os.UserHandle;
|
||||
|
||||
final class DeletePackageAction {
|
||||
public final PackageSetting mDeletingPs;
|
||||
public final PackageSetting mDisabledPs;
|
||||
public final PackageRemovedInfo mRemovedInfo;
|
||||
public final int mFlags;
|
||||
public final UserHandle mUser;
|
||||
|
||||
DeletePackageAction(PackageSetting deletingPs, PackageSetting disabledPs,
|
||||
PackageRemovedInfo removedInfo, int flags, UserHandle user) {
|
||||
mDeletingPs = deletingPs;
|
||||
mDisabledPs = disabledPs;
|
||||
mRemovedInfo = removedInfo;
|
||||
mFlags = flags;
|
||||
mUser = user;
|
||||
}
|
||||
}
|
||||
263
services/core/java/com/android/server/pm/FileInstallArgs.java
Normal file
263
services/core/java/com/android/server/pm/FileInstallArgs.java
Normal file
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.app.AppOpsManager.MODE_DEFAULT;
|
||||
import static android.content.pm.PackageManager.INSTALL_STAGED;
|
||||
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
|
||||
import static android.os.incremental.IncrementalManager.isIncrementalPath;
|
||||
|
||||
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
|
||||
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
|
||||
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
|
||||
import static com.android.server.pm.PackageManagerService.TAG;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
|
||||
|
||||
import android.content.pm.DataLoaderType;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.SigningDetails;
|
||||
import android.content.pm.parsing.ApkLiteParseUtils;
|
||||
import android.content.pm.parsing.PackageLite;
|
||||
import android.content.pm.parsing.result.ParseResult;
|
||||
import android.content.pm.parsing.result.ParseTypeImpl;
|
||||
import android.os.Environment;
|
||||
import android.os.FileUtils;
|
||||
import android.os.SELinux;
|
||||
import android.os.Trace;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.content.NativeLibraryHelper;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Logic to handle installation of new applications, including copying
|
||||
* and renaming logic.
|
||||
*/
|
||||
class FileInstallArgs extends InstallArgs {
|
||||
private File mCodeFile;
|
||||
|
||||
// Example topology:
|
||||
// /data/app/com.example/base.apk
|
||||
// /data/app/com.example/split_foo.apk
|
||||
// /data/app/com.example/lib/arm/libfoo.so
|
||||
// /data/app/com.example/lib/arm64/libfoo.so
|
||||
// /data/app/com.example/dalvik/arm/base.apk@classes.dex
|
||||
|
||||
/** New install */
|
||||
FileInstallArgs(InstallParams params) {
|
||||
super(params);
|
||||
}
|
||||
|
||||
/** Existing install */
|
||||
FileInstallArgs(String codePath, String[] instructionSets, PackageManagerService pm) {
|
||||
super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
|
||||
null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
|
||||
SigningDetails.UNKNOWN,
|
||||
PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.INSTALL_SCENARIO_DEFAULT,
|
||||
false, DataLoaderType.NONE, pm);
|
||||
mCodeFile = (codePath != null) ? new File(codePath) : null;
|
||||
}
|
||||
|
||||
int copyApk() {
|
||||
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "copyApk");
|
||||
try {
|
||||
return doCopyApk();
|
||||
} finally {
|
||||
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
|
||||
}
|
||||
}
|
||||
|
||||
private int doCopyApk() {
|
||||
if (mOriginInfo.mStaged) {
|
||||
if (DEBUG_INSTALL) Slog.d(TAG, mOriginInfo.mFile + " already staged; skipping copy");
|
||||
mCodeFile = mOriginInfo.mFile;
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
}
|
||||
|
||||
try {
|
||||
final boolean isEphemeral = (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
|
||||
final File tempDir =
|
||||
mPm.mInstallerService.allocateStageDirLegacy(mVolumeUuid, isEphemeral);
|
||||
mCodeFile = tempDir;
|
||||
} catch (IOException e) {
|
||||
Slog.w(TAG, "Failed to create copy file: " + e);
|
||||
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
|
||||
int ret = PackageManagerServiceUtils.copyPackage(
|
||||
mOriginInfo.mFile.getAbsolutePath(), mCodeFile);
|
||||
if (ret != PackageManager.INSTALL_SUCCEEDED) {
|
||||
Slog.e(TAG, "Failed to copy package");
|
||||
return ret;
|
||||
}
|
||||
|
||||
final boolean isIncremental = isIncrementalPath(mCodeFile.getAbsolutePath());
|
||||
final File libraryRoot = new File(mCodeFile, LIB_DIR_NAME);
|
||||
NativeLibraryHelper.Handle handle = null;
|
||||
try {
|
||||
handle = NativeLibraryHelper.Handle.create(mCodeFile);
|
||||
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
|
||||
mAbiOverride, isIncremental);
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Copying native libraries failed", e);
|
||||
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(handle);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int doPreInstall(int status) {
|
||||
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||
cleanUp();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean doRename(int status, ParsedPackage parsedPackage) {
|
||||
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||
cleanUp();
|
||||
return false;
|
||||
}
|
||||
|
||||
final File targetDir = resolveTargetDir();
|
||||
final File beforeCodeFile = mCodeFile;
|
||||
final File afterCodeFile = PackageManagerService.getNextCodePath(targetDir,
|
||||
parsedPackage.getPackageName());
|
||||
|
||||
if (DEBUG_INSTALL) Slog.d(TAG, "Renaming " + beforeCodeFile + " to " + afterCodeFile);
|
||||
final boolean onIncremental = mPm.mIncrementalManager != null
|
||||
&& isIncrementalPath(beforeCodeFile.getAbsolutePath());
|
||||
try {
|
||||
makeDirRecursive(afterCodeFile.getParentFile(), 0775);
|
||||
if (onIncremental) {
|
||||
// Just link files here. The stage dir will be removed when the installation
|
||||
// session is completed.
|
||||
mPm.mIncrementalManager.linkCodePath(beforeCodeFile, afterCodeFile);
|
||||
} else {
|
||||
Os.rename(beforeCodeFile.getAbsolutePath(), afterCodeFile.getAbsolutePath());
|
||||
}
|
||||
} catch (IOException | ErrnoException e) {
|
||||
Slog.w(TAG, "Failed to rename", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!onIncremental && !SELinux.restoreconRecursive(afterCodeFile)) {
|
||||
Slog.w(TAG, "Failed to restorecon");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reflect the rename internally
|
||||
mCodeFile = afterCodeFile;
|
||||
|
||||
// Reflect the rename in scanned details
|
||||
try {
|
||||
parsedPackage.setPath(afterCodeFile.getCanonicalPath());
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Failed to get path: " + afterCodeFile, e);
|
||||
return false;
|
||||
}
|
||||
parsedPackage.setBaseApkPath(FileUtils.rewriteAfterRename(beforeCodeFile,
|
||||
afterCodeFile, parsedPackage.getBaseApkPath()));
|
||||
parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile,
|
||||
afterCodeFile, parsedPackage.getSplitCodePaths()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(b/168126411): Once staged install flow starts using the same folder as non-staged
|
||||
// flow, we won't need this method anymore.
|
||||
private File resolveTargetDir() {
|
||||
boolean isStagedInstall = (mInstallFlags & INSTALL_STAGED) != 0;
|
||||
if (isStagedInstall) {
|
||||
return Environment.getDataAppDirectory(null);
|
||||
} else {
|
||||
return mCodeFile.getParentFile();
|
||||
}
|
||||
}
|
||||
|
||||
int doPostInstall(int status, int uid) {
|
||||
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||
cleanUp();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getCodePath() {
|
||||
return (mCodeFile != null) ? mCodeFile.getAbsolutePath() : null;
|
||||
}
|
||||
|
||||
private boolean cleanUp() {
|
||||
if (mCodeFile == null || !mCodeFile.exists()) {
|
||||
return false;
|
||||
}
|
||||
mPm.removeCodePathLI(mCodeFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
void cleanUpResourcesLI() {
|
||||
// Try enumerating all code paths before deleting
|
||||
List<String> allCodePaths = Collections.EMPTY_LIST;
|
||||
if (mCodeFile != null && mCodeFile.exists()) {
|
||||
final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
|
||||
final ParseResult<PackageLite> result = ApkLiteParseUtils.parsePackageLite(
|
||||
input.reset(), mCodeFile, /* flags */ 0);
|
||||
if (result.isSuccess()) {
|
||||
// Ignore error; we tried our best
|
||||
allCodePaths = result.getResult().getAllApkPaths();
|
||||
}
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
removeDexFiles(allCodePaths, mInstructionSets);
|
||||
}
|
||||
|
||||
void removeDexFiles(List<String> allCodePaths, String[] instructionSets) {
|
||||
if (!allCodePaths.isEmpty()) {
|
||||
if (instructionSets == null) {
|
||||
throw new IllegalStateException("instructionSet == null");
|
||||
}
|
||||
String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
|
||||
for (String codePath : allCodePaths) {
|
||||
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
|
||||
try {
|
||||
mPm.mInstaller.rmdex(codePath, dexCodeInstructionSet);
|
||||
} catch (Installer.InstallerException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean doPostDeleteLI(boolean delete) {
|
||||
// XXX err, shouldn't we respect the delete flag?
|
||||
cleanUpResourcesLI();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
57
services/core/java/com/android/server/pm/HandlerParams.java
Normal file
57
services/core/java/com/android/server/pm/HandlerParams.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
|
||||
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
|
||||
import static com.android.server.pm.PackageManagerService.TAG;
|
||||
|
||||
abstract class HandlerParams {
|
||||
/** User handle for the user requesting the information or installation. */
|
||||
private final UserHandle mUser;
|
||||
String mTraceMethod;
|
||||
int mTraceCookie;
|
||||
|
||||
HandlerParams(UserHandle user) {
|
||||
mUser = user;
|
||||
}
|
||||
|
||||
UserHandle getUser() {
|
||||
return mUser;
|
||||
}
|
||||
|
||||
HandlerParams setTraceMethod(String traceMethod) {
|
||||
mTraceMethod = traceMethod;
|
||||
return this;
|
||||
}
|
||||
|
||||
HandlerParams setTraceCookie(int traceCookie) {
|
||||
mTraceCookie = traceCookie;
|
||||
return this;
|
||||
}
|
||||
|
||||
final void startCopy() {
|
||||
if (DEBUG_INSTALL) Slog.i(TAG, "startCopy " + mUser + ": " + this);
|
||||
handleStartCopy();
|
||||
handleReturnCode();
|
||||
}
|
||||
|
||||
abstract void handleStartCopy();
|
||||
abstract void handleReturnCode();
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.content.pm.IPackageLoadingProgressCallback;
|
||||
|
||||
/**
|
||||
* Loading progress callback, used to listen for progress changes and update package setting
|
||||
*/
|
||||
final class IncrementalProgressListener extends IPackageLoadingProgressCallback.Stub {
|
||||
private final String mPackageName;
|
||||
private final PackageManagerService mPm;
|
||||
IncrementalProgressListener(String packageName, PackageManagerService pm) {
|
||||
mPackageName = packageName;
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageLoadingProgressChanged(float progress) {
|
||||
final PackageSetting ps;
|
||||
synchronized (mPm.mLock) {
|
||||
ps = mPm.mSettings.getPackageLPr(mPackageName);
|
||||
if (ps == null) {
|
||||
return;
|
||||
}
|
||||
ps.setLoadingProgress(progress);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
/**
|
||||
* Package states callback, used to listen for package state changes and send broadcasts
|
||||
*/
|
||||
final class IncrementalStatesCallback implements IncrementalStates.Callback {
|
||||
private final String mPackageName;
|
||||
private final PackageManagerService mPm;
|
||||
|
||||
IncrementalStatesCallback(String packageName, PackageManagerService pm) {
|
||||
mPackageName = packageName;
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageFullyLoaded() {
|
||||
final String codePath;
|
||||
synchronized (mPm.mLock) {
|
||||
final PackageSetting ps = mPm.mSettings.getPackageLPr(mPackageName);
|
||||
if (ps == null) {
|
||||
return;
|
||||
}
|
||||
codePath = ps.getPathString();
|
||||
}
|
||||
// Unregister progress listener
|
||||
mPm.mIncrementalManager.unregisterLoadingProgressCallbacks(codePath);
|
||||
// Make sure the information is preserved
|
||||
mPm.scheduleWriteSettingsLocked();
|
||||
}
|
||||
}
|
||||
149
services/core/java/com/android/server/pm/InstallArgs.java
Normal file
149
services/core/java/com/android/server/pm/InstallArgs.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.IPackageInstallObserver2;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.SigningDetails;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
abstract class InstallArgs {
|
||||
/** @see InstallParams#mOriginInfo */
|
||||
final OriginInfo mOriginInfo;
|
||||
/** @see InstallParams#mMoveInfo */
|
||||
final MoveInfo mMoveInfo;
|
||||
|
||||
final IPackageInstallObserver2 mObserver;
|
||||
// Always refers to PackageManager flags only
|
||||
final int mInstallFlags;
|
||||
@NonNull
|
||||
final InstallSource mInstallSource;
|
||||
final String mVolumeUuid;
|
||||
final UserHandle mUser;
|
||||
final String mAbiOverride;
|
||||
final String[] mInstallGrantPermissions;
|
||||
final List<String> mAllowlistedRestrictedPermissions;
|
||||
final int mAutoRevokePermissionsMode;
|
||||
/** If non-null, drop an async trace when the install completes */
|
||||
final String mTraceMethod;
|
||||
final int mTraceCookie;
|
||||
final SigningDetails mSigningDetails;
|
||||
final int mInstallReason;
|
||||
final int mInstallScenario;
|
||||
final boolean mForceQueryableOverride;
|
||||
final int mDataLoaderType;
|
||||
|
||||
// The list of instruction sets supported by this app. This is currently
|
||||
// only used during the rmdex() phase to clean up resources. We can get rid of this
|
||||
// if we move dex files under the common app path.
|
||||
@Nullable String[] mInstructionSets;
|
||||
|
||||
@NonNull final PackageManagerService mPm;
|
||||
|
||||
InstallArgs(OriginInfo originInfo, MoveInfo moveInfo, IPackageInstallObserver2 observer,
|
||||
int installFlags, InstallSource installSource, String volumeUuid,
|
||||
UserHandle user, String[] instructionSets,
|
||||
String abiOverride, String[] installGrantPermissions,
|
||||
List<String> allowlistedRestrictedPermissions,
|
||||
int autoRevokePermissionsMode,
|
||||
String traceMethod, int traceCookie, SigningDetails signingDetails,
|
||||
int installReason, int installScenario, boolean forceQueryableOverride,
|
||||
int dataLoaderType, PackageManagerService pm) {
|
||||
mOriginInfo = originInfo;
|
||||
mMoveInfo = moveInfo;
|
||||
mInstallFlags = installFlags;
|
||||
mObserver = observer;
|
||||
mInstallSource = Preconditions.checkNotNull(installSource);
|
||||
mVolumeUuid = volumeUuid;
|
||||
mUser = user;
|
||||
mInstructionSets = instructionSets;
|
||||
mAbiOverride = abiOverride;
|
||||
mInstallGrantPermissions = installGrantPermissions;
|
||||
mAllowlistedRestrictedPermissions = allowlistedRestrictedPermissions;
|
||||
mAutoRevokePermissionsMode = autoRevokePermissionsMode;
|
||||
mTraceMethod = traceMethod;
|
||||
mTraceCookie = traceCookie;
|
||||
mSigningDetails = signingDetails;
|
||||
mInstallReason = installReason;
|
||||
mInstallScenario = installScenario;
|
||||
mForceQueryableOverride = forceQueryableOverride;
|
||||
mDataLoaderType = dataLoaderType;
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
/** New install */
|
||||
InstallArgs(InstallParams params) {
|
||||
this(params.mOriginInfo, params.mMoveInfo, params.mObserver, params.mInstallFlags,
|
||||
params.mInstallSource, params.mVolumeUuid,
|
||||
params.getUser(), null /*instructionSets*/, params.mPackageAbiOverride,
|
||||
params.mGrantedRuntimePermissions, params.mAllowlistedRestrictedPermissions,
|
||||
params.mAutoRevokePermissionsMode,
|
||||
params.mTraceMethod, params.mTraceCookie, params.mSigningDetails,
|
||||
params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride,
|
||||
params.mDataLoaderType, params.mPm);
|
||||
}
|
||||
|
||||
abstract int copyApk();
|
||||
abstract int doPreInstall(int status);
|
||||
|
||||
/**
|
||||
* Rename package into final resting place. All paths on the given
|
||||
* scanned package should be updated to reflect the rename.
|
||||
*/
|
||||
abstract boolean doRename(int status, ParsedPackage parsedPackage);
|
||||
abstract int doPostInstall(int status, int uid);
|
||||
|
||||
/** @see PackageSettingBase#getPath() */
|
||||
abstract String getCodePath();
|
||||
|
||||
// Need installer lock especially for dex file removal.
|
||||
abstract void cleanUpResourcesLI();
|
||||
abstract boolean doPostDeleteLI(boolean delete);
|
||||
|
||||
/**
|
||||
* Called before the source arguments are copied. This is used mostly
|
||||
* for MoveParams when it needs to read the source file to put it in the
|
||||
* destination.
|
||||
*/
|
||||
int doPreCopy() {
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the source arguments are copied. This is used mostly for
|
||||
* MoveParams when it needs to read the source file to put it in the
|
||||
* destination.
|
||||
*/
|
||||
int doPostCopy(int uid) {
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
}
|
||||
|
||||
protected boolean isEphemeral() {
|
||||
return (mInstallFlags & PackageManager.INSTALL_INSTANT_APP) != 0;
|
||||
}
|
||||
|
||||
UserHandle getUser() {
|
||||
return mUser;
|
||||
}
|
||||
}
|
||||
2159
services/core/java/com/android/server/pm/InstallParams.java
Normal file
2159
services/core/java/com/android/server/pm/InstallParams.java
Normal file
File diff suppressed because it is too large
Load Diff
27
services/core/java/com/android/server/pm/InstallRequest.java
Normal file
27
services/core/java/com/android/server/pm/InstallRequest.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
final class InstallRequest {
|
||||
public final InstallArgs mArgs;
|
||||
public final PackageInstalledInfo mInstallResult;
|
||||
|
||||
InstallRequest(InstallArgs args, PackageInstalledInfo res) {
|
||||
mArgs = args;
|
||||
mInstallResult = res;
|
||||
}
|
||||
}
|
||||
41
services/core/java/com/android/server/pm/MoveInfo.java
Normal file
41
services/core/java/com/android/server/pm/MoveInfo.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
final class MoveInfo {
|
||||
final int mMoveId;
|
||||
final String mFromUuid;
|
||||
final String mToUuid;
|
||||
final String mPackageName;
|
||||
final int mAppId;
|
||||
final String mSeInfo;
|
||||
final int mTargetSdkVersion;
|
||||
final String mFromCodePath;
|
||||
|
||||
MoveInfo(int moveId, String fromUuid, String toUuid, String packageName,
|
||||
int appId, String seInfo, int targetSdkVersion,
|
||||
String fromCodePath) {
|
||||
mMoveId = moveId;
|
||||
mFromUuid = fromUuid;
|
||||
mToUuid = toUuid;
|
||||
mPackageName = packageName;
|
||||
mAppId = appId;
|
||||
mSeInfo = seInfo;
|
||||
mTargetSdkVersion = targetSdkVersion;
|
||||
mFromCodePath = fromCodePath;
|
||||
}
|
||||
}
|
||||
133
services/core/java/com/android/server/pm/MoveInstallArgs.java
Normal file
133
services/core/java/com/android/server/pm/MoveInstallArgs.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
|
||||
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
|
||||
|
||||
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
|
||||
import static com.android.server.pm.PackageManagerService.TAG;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Environment;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Logic to handle movement of existing installed applications.
|
||||
*/
|
||||
final class MoveInstallArgs extends InstallArgs {
|
||||
private File mCodeFile;
|
||||
|
||||
/** New install */
|
||||
MoveInstallArgs(InstallParams params) {
|
||||
super(params);
|
||||
}
|
||||
|
||||
int copyApk() {
|
||||
if (DEBUG_INSTALL) {
|
||||
Slog.d(TAG, "Moving " + mMoveInfo.mPackageName + " from "
|
||||
+ mMoveInfo.mFromUuid + " to " + mMoveInfo.mToUuid);
|
||||
}
|
||||
synchronized (mPm.mInstaller) {
|
||||
try {
|
||||
mPm.mInstaller.moveCompleteApp(mMoveInfo.mFromUuid, mMoveInfo.mToUuid,
|
||||
mMoveInfo.mPackageName, mMoveInfo.mAppId, mMoveInfo.mSeInfo,
|
||||
mMoveInfo.mTargetSdkVersion, mMoveInfo.mFromCodePath);
|
||||
} catch (Installer.InstallerException e) {
|
||||
Slog.w(TAG, "Failed to move app", e);
|
||||
return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
final String toPathName = new File(mMoveInfo.mFromCodePath).getName();
|
||||
mCodeFile = new File(Environment.getDataAppDirectory(mMoveInfo.mToUuid), toPathName);
|
||||
if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + mCodeFile);
|
||||
|
||||
return PackageManager.INSTALL_SUCCEEDED;
|
||||
}
|
||||
|
||||
int doPreInstall(int status) {
|
||||
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||
cleanUp(mMoveInfo.mToUuid);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean doRename(int status, ParsedPackage parsedPackage) {
|
||||
if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||
cleanUp(mMoveInfo.mToUuid);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int doPostInstall(int status, int uid) {
|
||||
if (status == PackageManager.INSTALL_SUCCEEDED) {
|
||||
cleanUp(mMoveInfo.mFromUuid);
|
||||
} else {
|
||||
cleanUp(mMoveInfo.mToUuid);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getCodePath() {
|
||||
return (mCodeFile != null) ? mCodeFile.getAbsolutePath() : null;
|
||||
}
|
||||
|
||||
private void cleanUp(String volumeUuid) {
|
||||
final String toPathName = new File(mMoveInfo.mFromCodePath).getName();
|
||||
final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid),
|
||||
toPathName);
|
||||
Slog.d(TAG, "Cleaning up " + mMoveInfo.mPackageName + " on " + volumeUuid);
|
||||
final int[] userIds = mPm.mUserManager.getUserIds();
|
||||
synchronized (mPm.mInstallLock) {
|
||||
// Clean up both app data and code
|
||||
// All package moves are frozen until finished
|
||||
|
||||
// We purposefully exclude FLAG_STORAGE_EXTERNAL here, since
|
||||
// this task was only focused on moving data on internal storage.
|
||||
// We don't want ART profiles cleared, because they don't move,
|
||||
// so we would be deleting the only copy (b/149200535).
|
||||
final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE
|
||||
| Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
|
||||
for (int userId : userIds) {
|
||||
try {
|
||||
mPm.mInstaller.destroyAppData(volumeUuid, mMoveInfo.mPackageName, userId, flags,
|
||||
0);
|
||||
} catch (Installer.InstallerException e) {
|
||||
Slog.w(TAG, String.valueOf(e));
|
||||
}
|
||||
}
|
||||
mPm.removeCodePathLI(codeFile);
|
||||
}
|
||||
}
|
||||
|
||||
void cleanUpResourcesLI() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
boolean doPostDeleteLI(boolean delete) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
68
services/core/java/com/android/server/pm/OriginInfo.java
Normal file
68
services/core/java/com/android/server/pm/OriginInfo.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
final class OriginInfo {
|
||||
/**
|
||||
* Location where install is coming from, before it has been
|
||||
* copied/renamed into place. This could be a single monolithic APK
|
||||
* file, or a cluster directory. This location may be untrusted.
|
||||
*/
|
||||
final File mFile;
|
||||
|
||||
/**
|
||||
* Flag indicating that {@link #mFile} has already been staged, meaning downstream users
|
||||
* don't need to defensively copy the contents.
|
||||
*/
|
||||
final boolean mStaged;
|
||||
|
||||
/**
|
||||
* Flag indicating that {@link #mFile} is an already installed app that is being moved.
|
||||
*/
|
||||
final boolean mExisting;
|
||||
|
||||
final String mResolvedPath;
|
||||
final File mResolvedFile;
|
||||
|
||||
static OriginInfo fromNothing() {
|
||||
return new OriginInfo(null, false, false);
|
||||
}
|
||||
|
||||
static OriginInfo fromExistingFile(File file) {
|
||||
return new OriginInfo(file, false, true);
|
||||
}
|
||||
|
||||
static OriginInfo fromStagedFile(File file) {
|
||||
return new OriginInfo(file, true, false);
|
||||
}
|
||||
|
||||
private OriginInfo(File file, boolean staged, boolean existing) {
|
||||
mFile = file;
|
||||
mStaged = staged;
|
||||
mExisting = existing;
|
||||
|
||||
if (file != null) {
|
||||
mResolvedPath = file.getAbsolutePath();
|
||||
mResolvedFile = file;
|
||||
} else {
|
||||
mResolvedPath = null;
|
||||
mResolvedFile = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
91
services/core/java/com/android/server/pm/PackageFreezer.java
Normal file
91
services/core/java/com/android/server/pm/PackageFreezer.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Class that freezes and kills the given package upon creation, and
|
||||
* unfreezes it upon closing. This is typically used when doing surgery on
|
||||
* app code/data to prevent the app from running while you're working.
|
||||
*/
|
||||
final class PackageFreezer implements AutoCloseable {
|
||||
private final String mPackageName;
|
||||
|
||||
private final boolean mWeFroze;
|
||||
|
||||
private final AtomicBoolean mClosed = new AtomicBoolean();
|
||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||
|
||||
@NonNull
|
||||
private final PackageManagerService mPm;
|
||||
|
||||
/**
|
||||
* Create and return a stub freezer that doesn't actually do anything,
|
||||
* typically used when someone requested
|
||||
* {@link PackageManager#INSTALL_DONT_KILL_APP} or
|
||||
* {@link PackageManager#DELETE_DONT_KILL_APP}.
|
||||
*/
|
||||
PackageFreezer(PackageManagerService pm) {
|
||||
mPm = pm;
|
||||
mPackageName = null;
|
||||
mWeFroze = false;
|
||||
mCloseGuard.open("close");
|
||||
}
|
||||
|
||||
PackageFreezer(String packageName, int userId, String killReason,
|
||||
PackageManagerService pm) {
|
||||
mPm = pm;
|
||||
mPackageName = packageName;
|
||||
final PackageSetting ps;
|
||||
synchronized (mPm.mLock) {
|
||||
mWeFroze = mPm.mFrozenPackages.add(mPackageName);
|
||||
ps = mPm.mSettings.getPackageLPr(mPackageName);
|
||||
}
|
||||
if (ps != null) {
|
||||
mPm.killApplication(ps.name, ps.appId, userId, killReason);
|
||||
}
|
||||
mCloseGuard.open("close");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
mCloseGuard.warnIfOpen();
|
||||
close();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mCloseGuard.close();
|
||||
if (mClosed.compareAndSet(false, true)) {
|
||||
synchronized (mPm.mLock) {
|
||||
if (mWeFroze) {
|
||||
mPm.mFrozenPackages.remove(mPackageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static com.android.server.pm.PackageManagerService.TAG;
|
||||
|
||||
import android.content.pm.PackageParser;
|
||||
import android.util.ExceptionUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
final class PackageInstalledInfo {
|
||||
String mName;
|
||||
int mUid;
|
||||
// The set of users that originally had this package installed.
|
||||
int[] mOrigUsers;
|
||||
// The set of users that now have this package installed.
|
||||
int[] mNewUsers;
|
||||
AndroidPackage mPkg;
|
||||
int mReturnCode;
|
||||
String mReturnMsg;
|
||||
String mInstallerPackageName;
|
||||
PackageRemovedInfo mRemovedInfo;
|
||||
// The set of packages consuming this shared library or null if no consumers exist.
|
||||
ArrayList<AndroidPackage> mLibraryConsumers;
|
||||
PackageFreezer mFreezer;
|
||||
|
||||
// In some error cases we want to convey more info back to the observer
|
||||
String mOrigPackage;
|
||||
String mOrigPermission;
|
||||
|
||||
PackageInstalledInfo(int currentStatus) {
|
||||
mReturnCode = currentStatus;
|
||||
mUid = -1;
|
||||
mPkg = null;
|
||||
mRemovedInfo = null;
|
||||
}
|
||||
|
||||
public void setError(int code, String msg) {
|
||||
setReturnCode(code);
|
||||
setReturnMessage(msg);
|
||||
Slog.w(TAG, msg);
|
||||
}
|
||||
|
||||
public void setError(String msg, PackageParser.PackageParserException e) {
|
||||
setReturnCode(e.error);
|
||||
setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e));
|
||||
Slog.w(TAG, msg, e);
|
||||
}
|
||||
|
||||
public void setError(String msg, PackageManagerException e) {
|
||||
mReturnCode = e.error;
|
||||
setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e));
|
||||
Slog.w(TAG, msg, e);
|
||||
}
|
||||
|
||||
public void setReturnCode(int returnCode) {
|
||||
mReturnCode = returnCode;
|
||||
}
|
||||
|
||||
private void setReturnMessage(String returnMsg) {
|
||||
mReturnMsg = returnMsg;
|
||||
}
|
||||
}
|
||||
@@ -2384,8 +2384,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
|
||||
private void verifyNonStaged()
|
||||
throws PackageManagerException {
|
||||
final PackageManagerService.VerificationParams verifyingSession =
|
||||
prepareForVerification();
|
||||
final VerificationParams verifyingSession = prepareForVerification();
|
||||
if (isMultiPackage()) {
|
||||
final List<PackageInstallerSession> childSessions = getChildSessions();
|
||||
// Spot check to reject a non-staged multi package install of APEXes and APKs.
|
||||
@@ -2395,14 +2394,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
PackageManager.INSTALL_FAILED_SESSION_INVALID,
|
||||
"Non-staged multi package install of APEX and APK packages is not supported");
|
||||
}
|
||||
List<PackageManagerService.VerificationParams> verifyingChildSessions =
|
||||
List<VerificationParams> verifyingChildSessions =
|
||||
new ArrayList<>(childSessions.size());
|
||||
boolean success = true;
|
||||
PackageManagerException failure = null;
|
||||
for (int i = 0; i < childSessions.size(); ++i) {
|
||||
final PackageInstallerSession session = childSessions.get(i);
|
||||
try {
|
||||
final PackageManagerService.VerificationParams verifyingChildSession =
|
||||
final VerificationParams verifyingChildSession =
|
||||
session.prepareForVerification();
|
||||
verifyingChildSessions.add(verifyingChildSession);
|
||||
} catch (PackageManagerException e) {
|
||||
@@ -2416,9 +2415,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
failure.error, failure.getLocalizedMessage(), null);
|
||||
return;
|
||||
}
|
||||
mPm.verifyStage(verifyingSession, verifyingChildSessions);
|
||||
verifyingSession.verifyStage(verifyingChildSessions);
|
||||
} else {
|
||||
mPm.verifyStage(verifyingSession);
|
||||
verifyingSession.verifyStage();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2433,21 +2432,20 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
|
||||
private void installNonStaged()
|
||||
throws PackageManagerException {
|
||||
final PackageManagerService.InstallParams installingSession = makeInstallParams();
|
||||
final InstallParams installingSession = makeInstallParams();
|
||||
if (installingSession == null) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
|
||||
"Session should contain at least one apk session for installation");
|
||||
}
|
||||
if (isMultiPackage()) {
|
||||
final List<PackageInstallerSession> childSessions = getChildSessions();
|
||||
List<PackageManagerService.InstallParams> installingChildSessions =
|
||||
new ArrayList<>(childSessions.size());
|
||||
List<InstallParams> installingChildSessions = new ArrayList<>(childSessions.size());
|
||||
boolean success = true;
|
||||
PackageManagerException failure = null;
|
||||
for (int i = 0; i < childSessions.size(); ++i) {
|
||||
final PackageInstallerSession session = childSessions.get(i);
|
||||
try {
|
||||
final PackageManagerService.InstallParams installingChildSession =
|
||||
final InstallParams installingChildSession =
|
||||
session.makeInstallParams();
|
||||
if (installingChildSession != null) {
|
||||
installingChildSessions.add(installingChildSession);
|
||||
@@ -2463,20 +2461,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
failure.error, failure.getLocalizedMessage(), null);
|
||||
return;
|
||||
}
|
||||
mPm.installStage(installingSession, installingChildSessions);
|
||||
installingSession.installStage(installingChildSessions);
|
||||
} else {
|
||||
mPm.installStage(installingSession);
|
||||
installingSession.installStage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stages this session for verification and returns a
|
||||
* {@link PackageManagerService.VerificationParams} representing this new staged state or null
|
||||
* {@link VerificationParams} representing this new staged state or null
|
||||
* in case permissions need to be requested before verification can proceed.
|
||||
*/
|
||||
@NonNull
|
||||
private PackageManagerService.VerificationParams prepareForVerification()
|
||||
throws PackageManagerException {
|
||||
private VerificationParams prepareForVerification() throws PackageManagerException {
|
||||
assertNotLocked("makeSessionActive");
|
||||
|
||||
synchronized (mLock) {
|
||||
@@ -2603,9 +2600,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
@GuardedBy("mLock")
|
||||
@Nullable
|
||||
/**
|
||||
* Returns a {@link com.android.server.pm.PackageManagerService.VerificationParams}
|
||||
* Returns a {@link com.android.server.pm.VerificationParams}
|
||||
*/
|
||||
private PackageManagerService.VerificationParams makeVerificationParamsLocked() {
|
||||
private VerificationParams makeVerificationParamsLocked() {
|
||||
final IPackageInstallObserver2 localObserver;
|
||||
if (!hasParentSessionId()) {
|
||||
// Avoid attaching this observer to child session since they won't use it.
|
||||
@@ -2638,8 +2635,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
|
||||
mRelinquished = true;
|
||||
|
||||
return mPm.new VerificationParams(user, stageDir, localObserver, params,
|
||||
mInstallSource, mInstallerUid, mSigningDetails, sessionId, mPackageLite);
|
||||
return new VerificationParams(user, stageDir, localObserver, params,
|
||||
mInstallSource, mInstallerUid, mSigningDetails, sessionId, mPackageLite, mPm);
|
||||
}
|
||||
|
||||
private void onVerificationComplete() {
|
||||
@@ -2656,10 +2653,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
|
||||
/**
|
||||
* Stages this session for install and returns a
|
||||
* {@link PackageManagerService.InstallParams} representing this new staged state.
|
||||
* {@link InstallParams} representing this new staged state.
|
||||
*/
|
||||
@Nullable
|
||||
private PackageManagerService.InstallParams makeInstallParams()
|
||||
private InstallParams makeInstallParams()
|
||||
throws PackageManagerException {
|
||||
synchronized (mLock) {
|
||||
if (mDestroyed) {
|
||||
@@ -2722,8 +2719,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
|
||||
synchronized (mLock) {
|
||||
return mPm.new InstallParams(stageDir, localObserver, params, mInstallSource, user,
|
||||
mSigningDetails, mInstallerUid, mPackageLite);
|
||||
return new InstallParams(stageDir, localObserver, params, mInstallSource, user,
|
||||
mSigningDetails, mInstallerUid, mPackageLite, mPm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
179
services/core/java/com/android/server/pm/PackageRemovedInfo.java
Normal file
179
services/core/java/com/android/server/pm/PackageRemovedInfo.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
|
||||
import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
|
||||
|
||||
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityManagerInternal;
|
||||
import android.app.BroadcastOptions;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerExemptionManager;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.android.internal.util.ArrayUtils;
|
||||
import com.android.server.LocalServices;
|
||||
|
||||
final class PackageRemovedInfo {
|
||||
final PackageSender mPackageSender;
|
||||
String mRemovedPackage;
|
||||
String mInstallerPackageName;
|
||||
int mUid = -1;
|
||||
int mRemovedAppId = -1;
|
||||
int[] mOrigUsers;
|
||||
int[] mRemovedUsers = null;
|
||||
int[] mBroadcastUsers = null;
|
||||
int[] mInstantUserIds = null;
|
||||
SparseArray<Integer> mInstallReasons;
|
||||
SparseArray<Integer> mUninstallReasons;
|
||||
boolean mIsRemovedPackageSystemUpdate = false;
|
||||
boolean mIsUpdate;
|
||||
boolean mDataRemoved;
|
||||
boolean mRemovedForAllUsers;
|
||||
boolean mIsStaticSharedLib;
|
||||
// a two dimensional array mapping userId to the set of appIds that can receive notice
|
||||
// of package changes
|
||||
SparseArray<int[]> mBroadcastAllowList;
|
||||
// Clean up resources deleted packages.
|
||||
InstallArgs mArgs = null;
|
||||
private static final int[] EMPTY_INT_ARRAY = new int[0];
|
||||
|
||||
PackageRemovedInfo(PackageSender packageSender) {
|
||||
mPackageSender = packageSender;
|
||||
}
|
||||
|
||||
void sendPackageRemovedBroadcasts(boolean killApp, boolean removedBySystem) {
|
||||
sendPackageRemovedBroadcastInternal(killApp, removedBySystem);
|
||||
}
|
||||
|
||||
void sendSystemPackageUpdatedBroadcasts() {
|
||||
if (mIsRemovedPackageSystemUpdate) {
|
||||
sendSystemPackageUpdatedBroadcastsInternal();
|
||||
}
|
||||
}
|
||||
|
||||
private void sendSystemPackageUpdatedBroadcastsInternal() {
|
||||
Bundle extras = new Bundle(2);
|
||||
extras.putInt(Intent.EXTRA_UID, mRemovedAppId >= 0 ? mRemovedAppId : mUid);
|
||||
extras.putBoolean(Intent.EXTRA_REPLACING, true);
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, mRemovedPackage, extras,
|
||||
0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, mRemovedPackage,
|
||||
extras, 0, null /*targetPackage*/, null, null, null, mBroadcastAllowList, null);
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED, null, null, 0,
|
||||
mRemovedPackage, null, null, null, null /* broadcastAllowList */,
|
||||
getTemporaryAppAllowlistBroadcastOptions(REASON_PACKAGE_REPLACED).toBundle());
|
||||
if (mInstallerPackageName != null) {
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED,
|
||||
mRemovedPackage, extras, 0 /*flags*/,
|
||||
mInstallerPackageName, null, null, null, null /* broadcastAllowList */,
|
||||
null);
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
|
||||
mRemovedPackage, extras, 0 /*flags*/,
|
||||
mInstallerPackageName, null, null, null, null /* broadcastAllowList */,
|
||||
null);
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
|
||||
@PowerExemptionManager.ReasonCode int reasonCode) {
|
||||
long duration = 10_000;
|
||||
final ActivityManagerInternal amInternal =
|
||||
LocalServices.getService(ActivityManagerInternal.class);
|
||||
if (amInternal != null) {
|
||||
duration = amInternal.getBootTimeTempAllowListDuration();
|
||||
}
|
||||
final BroadcastOptions bOptions = BroadcastOptions.makeBasic();
|
||||
bOptions.setTemporaryAppAllowlist(duration,
|
||||
TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
|
||||
reasonCode, "");
|
||||
return bOptions;
|
||||
}
|
||||
|
||||
private void sendPackageRemovedBroadcastInternal(boolean killApp, boolean removedBySystem) {
|
||||
// Don't send static shared library removal broadcasts as these
|
||||
// libs are visible only the apps that depend on them an one
|
||||
// cannot remove the library if it has a dependency.
|
||||
if (mIsStaticSharedLib) {
|
||||
return;
|
||||
}
|
||||
Bundle extras = new Bundle(2);
|
||||
final int removedUid = mRemovedAppId >= 0 ? mRemovedAppId : mUid;
|
||||
extras.putInt(Intent.EXTRA_UID, removedUid);
|
||||
extras.putBoolean(Intent.EXTRA_DATA_REMOVED, mDataRemoved);
|
||||
extras.putBoolean(Intent.EXTRA_DONT_KILL_APP, !killApp);
|
||||
extras.putBoolean(Intent.EXTRA_USER_INITIATED, !removedBySystem);
|
||||
if (mIsUpdate || mIsRemovedPackageSystemUpdate) {
|
||||
extras.putBoolean(Intent.EXTRA_REPLACING, true);
|
||||
}
|
||||
extras.putBoolean(Intent.EXTRA_REMOVED_FOR_ALL_USERS, mRemovedForAllUsers);
|
||||
if (mRemovedPackage != null) {
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
|
||||
mRemovedPackage, extras, 0, null /*targetPackage*/, null,
|
||||
mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null);
|
||||
if (mInstallerPackageName != null) {
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED,
|
||||
mRemovedPackage, extras, 0 /*flags*/,
|
||||
mInstallerPackageName, null, mBroadcastUsers, mInstantUserIds, null, null);
|
||||
}
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED_INTERNAL,
|
||||
mRemovedPackage, extras, 0 /*flags*/, PLATFORM_PACKAGE_NAME,
|
||||
null /*finishedReceiver*/, mBroadcastUsers, mInstantUserIds,
|
||||
mBroadcastAllowList, null /*bOptions*/);
|
||||
if (mDataRemoved && !mIsRemovedPackageSystemUpdate) {
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_PACKAGE_FULLY_REMOVED,
|
||||
mRemovedPackage, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND, null,
|
||||
null, mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null);
|
||||
mPackageSender.notifyPackageRemoved(mRemovedPackage, removedUid);
|
||||
}
|
||||
}
|
||||
if (mRemovedAppId >= 0) {
|
||||
// If a system app's updates are uninstalled the UID is not actually removed. Some
|
||||
// services need to know the package name affected.
|
||||
if (extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
|
||||
extras.putString(Intent.EXTRA_PACKAGE_NAME, mRemovedPackage);
|
||||
}
|
||||
|
||||
mPackageSender.sendPackageBroadcast(Intent.ACTION_UID_REMOVED,
|
||||
null, extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND,
|
||||
null, null, mBroadcastUsers, mInstantUserIds, mBroadcastAllowList, null);
|
||||
}
|
||||
}
|
||||
|
||||
void populateUsers(int[] userIds, PackageSetting deletedPackageSetting) {
|
||||
mRemovedUsers = userIds;
|
||||
if (mRemovedUsers == null) {
|
||||
mBroadcastUsers = null;
|
||||
return;
|
||||
}
|
||||
|
||||
mBroadcastUsers = EMPTY_INT_ARRAY;
|
||||
mInstantUserIds = EMPTY_INT_ARRAY;
|
||||
for (int i = userIds.length - 1; i >= 0; --i) {
|
||||
final int userId = userIds[i];
|
||||
if (deletedPackageSetting.getInstantApp(userId)) {
|
||||
mInstantUserIds = ArrayUtils.appendInt(mInstantUserIds, userId);
|
||||
} else {
|
||||
mBroadcastUsers = ArrayUtils.appendInt(mBroadcastUsers, userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
39
services/core/java/com/android/server/pm/PackageSender.java
Normal file
39
services/core/java/com/android/server/pm/PackageSender.java
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.os.Bundle;
|
||||
import android.util.SparseArray;
|
||||
|
||||
interface PackageSender {
|
||||
/**
|
||||
* @param userIds User IDs where the action occurred on a full application
|
||||
* @param instantUserIds User IDs where the action occurred on an instant application
|
||||
*/
|
||||
void sendPackageBroadcast(String action, String pkg,
|
||||
Bundle extras, int flags, String targetPkg,
|
||||
IIntentReceiver finishedReceiver, int[] userIds, int[] instantUserIds,
|
||||
@Nullable SparseArray<int[]> broadcastAllowList, @Nullable Bundle bOptions);
|
||||
void sendPackageAddedForNewUsers(String packageName, boolean sendBootCompleted,
|
||||
boolean includeStopped, int appId, int[] userIds, int[] instantUserIds,
|
||||
int dataLoaderType);
|
||||
void notifyPackageAdded(String packageName, int uid);
|
||||
void notifyPackageChanged(String packageName, int uid);
|
||||
void notifyPackageRemoved(String packageName, int uid);
|
||||
}
|
||||
@@ -19,8 +19,6 @@ package com.android.server.pm;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import com.android.server.pm.PackageManagerService.VerificationParams;
|
||||
|
||||
/**
|
||||
* Tracks the package verification state for a particular package. Each package verification has a
|
||||
* required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list
|
||||
|
||||
45
services/core/java/com/android/server/pm/PrepareFailure.java
Normal file
45
services/core/java/com/android/server/pm/PrepareFailure.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.util.ExceptionUtils;
|
||||
|
||||
final class PrepareFailure extends PackageManagerException {
|
||||
|
||||
public String mConflictingPackage;
|
||||
public String mConflictingPermission;
|
||||
|
||||
PrepareFailure(int error) {
|
||||
super(error, "Failed to prepare for install.");
|
||||
}
|
||||
|
||||
PrepareFailure(int error, String detailMessage) {
|
||||
super(error, detailMessage);
|
||||
}
|
||||
|
||||
PrepareFailure(String message, Exception e) {
|
||||
super(((PackageManagerException) e).error,
|
||||
ExceptionUtils.getCompleteMessage(message, e));
|
||||
}
|
||||
|
||||
PrepareFailure conflictsWithExistingPermission(String conflictingPermission,
|
||||
String conflictingPackage) {
|
||||
mConflictingPermission = conflictingPermission;
|
||||
mConflictingPackage = conflictingPackage;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
54
services/core/java/com/android/server/pm/PrepareResult.java
Normal file
54
services/core/java/com/android/server/pm/PrepareResult.java
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
|
||||
/**
|
||||
* The set of data needed to successfully install the prepared package. This includes data that
|
||||
* will be used to scan and reconcile the package.
|
||||
*/
|
||||
final class PrepareResult {
|
||||
public final boolean mReplace;
|
||||
public final int mScanFlags;
|
||||
public final int mParseFlags;
|
||||
@Nullable /* The original Package if it is being replaced, otherwise {@code null} */
|
||||
public final AndroidPackage mExistingPackage;
|
||||
public final ParsedPackage mPackageToScan;
|
||||
public final boolean mClearCodeCache;
|
||||
public final boolean mSystem;
|
||||
public final PackageSetting mOriginalPs;
|
||||
public final PackageSetting mDisabledPs;
|
||||
|
||||
PrepareResult(boolean replace, int scanFlags,
|
||||
int parseFlags, AndroidPackage existingPackage,
|
||||
ParsedPackage packageToScan, boolean clearCodeCache, boolean system,
|
||||
PackageSetting originalPs, PackageSetting disabledPs) {
|
||||
mReplace = replace;
|
||||
mScanFlags = scanFlags;
|
||||
mParseFlags = parseFlags;
|
||||
mExistingPackage = existingPackage;
|
||||
mPackageToScan = packageToScan;
|
||||
mClearCodeCache = clearCodeCache;
|
||||
mSystem = system;
|
||||
mOriginalPs = originalPs;
|
||||
mDisabledPs = disabledPs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
final class ReconcileFailure extends PackageManagerException {
|
||||
ReconcileFailure(String message) {
|
||||
super("Reconcile failed: " + message);
|
||||
}
|
||||
ReconcileFailure(int reason, String message) {
|
||||
super(reason, "Reconcile failed: " + message);
|
||||
}
|
||||
ReconcileFailure(PackageManagerException e) {
|
||||
this(e.error, e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.content.pm.SharedLibraryInfo;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.utils.WatchedLongSparseArray;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Package scan results and related request details used to reconcile the potential addition of
|
||||
* one or more packages to the system.
|
||||
*
|
||||
* Reconcile will take a set of package details that need to be committed to the system and make
|
||||
* sure that they are valid in the context of the system and the other installing apps. Any
|
||||
* invalid state or app will result in a failed reconciliation and thus whatever operation (such
|
||||
* as install) led to the request.
|
||||
*/
|
||||
final class ReconcileRequest {
|
||||
public final Map<String, ScanResult> mScannedPackages;
|
||||
|
||||
public final Map<String, AndroidPackage> mAllPackages;
|
||||
public final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> mSharedLibrarySource;
|
||||
public final Map<String, InstallArgs> mInstallArgs;
|
||||
public final Map<String, PackageInstalledInfo> mInstallResults;
|
||||
public final Map<String, PrepareResult> mPreparedPackages;
|
||||
public final Map<String, Settings.VersionInfo> mVersionInfos;
|
||||
public final Map<String, PackageSetting> mLastStaticSharedLibSettings;
|
||||
|
||||
ReconcileRequest(Map<String, ScanResult> scannedPackages,
|
||||
Map<String, InstallArgs> installArgs,
|
||||
Map<String, PackageInstalledInfo> installResults,
|
||||
Map<String, PrepareResult> preparedPackages,
|
||||
Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
|
||||
Map<String, AndroidPackage> allPackages,
|
||||
Map<String, Settings.VersionInfo> versionInfos,
|
||||
Map<String, PackageSetting> lastStaticSharedLibSettings) {
|
||||
mScannedPackages = scannedPackages;
|
||||
mInstallArgs = installArgs;
|
||||
mInstallResults = installResults;
|
||||
mPreparedPackages = preparedPackages;
|
||||
mSharedLibrarySource = sharedLibrarySource;
|
||||
mAllPackages = allPackages;
|
||||
mVersionInfos = versionInfos;
|
||||
mLastStaticSharedLibSettings = lastStaticSharedLibSettings;
|
||||
}
|
||||
|
||||
ReconcileRequest(Map<String, ScanResult> scannedPackages,
|
||||
Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
|
||||
Map<String, AndroidPackage> allPackages,
|
||||
Map<String, Settings.VersionInfo> versionInfos,
|
||||
Map<String, PackageSetting> lastStaticSharedLibSettings) {
|
||||
this(scannedPackages, Collections.emptyMap(), Collections.emptyMap(),
|
||||
Collections.emptyMap(), sharedLibrarySource, allPackages, versionInfos,
|
||||
lastStaticSharedLibSettings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.SharedLibraryInfo;
|
||||
import android.content.pm.SigningDetails;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A container of all data needed to commit a package to in-memory data structures and to disk.
|
||||
* TODO: move most of the data contained here into a PackageSetting for commit.
|
||||
*/
|
||||
final class ReconciledPackage {
|
||||
public final ReconcileRequest mRequest;
|
||||
public final PackageSetting mPkgSetting;
|
||||
public final ScanResult mScanResult;
|
||||
// TODO: Remove install-specific details from the reconcile result
|
||||
public final PackageInstalledInfo mInstallResult;
|
||||
@Nullable public final PrepareResult mPrepareResult;
|
||||
@Nullable public final InstallArgs mInstallArgs;
|
||||
public final DeletePackageAction mDeletePackageAction;
|
||||
public final List<SharedLibraryInfo> mAllowedSharedLibraryInfos;
|
||||
public final SigningDetails mSigningDetails;
|
||||
public final boolean mSharedUserSignaturesChanged;
|
||||
public ArrayList<SharedLibraryInfo> mCollectedSharedLibraryInfos;
|
||||
public final boolean mRemoveAppKeySetData;
|
||||
|
||||
ReconciledPackage(ReconcileRequest request,
|
||||
InstallArgs installArgs,
|
||||
PackageSetting pkgSetting,
|
||||
PackageInstalledInfo installResult,
|
||||
PrepareResult prepareResult,
|
||||
ScanResult scanResult,
|
||||
DeletePackageAction deletePackageAction,
|
||||
List<SharedLibraryInfo> allowedSharedLibraryInfos,
|
||||
SigningDetails signingDetails,
|
||||
boolean sharedUserSignaturesChanged,
|
||||
boolean removeAppKeySetData) {
|
||||
mRequest = request;
|
||||
mInstallArgs = installArgs;
|
||||
mPkgSetting = pkgSetting;
|
||||
mInstallResult = installResult;
|
||||
mPrepareResult = prepareResult;
|
||||
mScanResult = scanResult;
|
||||
mDeletePackageAction = deletePackageAction;
|
||||
mAllowedSharedLibraryInfos = allowedSharedLibraryInfos;
|
||||
mSigningDetails = signingDetails;
|
||||
mSharedUserSignaturesChanged = sharedUserSignaturesChanged;
|
||||
mRemoveAppKeySetData = removeAppKeySetData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a combined set of packages containing the packages already installed combined
|
||||
* with the package(s) currently being installed. The to-be installed packages take
|
||||
* precedence and may shadow already installed packages.
|
||||
*/
|
||||
Map<String, AndroidPackage> getCombinedAvailablePackages() {
|
||||
final ArrayMap<String, AndroidPackage> combined =
|
||||
new ArrayMap<>(mRequest.mAllPackages.size() + mRequest.mScannedPackages.size());
|
||||
|
||||
combined.putAll(mRequest.mAllPackages);
|
||||
|
||||
for (ScanResult scanResult : mRequest.mScannedPackages.values()) {
|
||||
combined.put(scanResult.mPkgSetting.name, scanResult.mRequest.mParsedPackage);
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
87
services/core/java/com/android/server/pm/ScanRequest.java
Normal file
87
services/core/java/com/android/server/pm/ScanRequest.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.parsing.ParsingPackageUtils;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
|
||||
/** A package to be scanned */
|
||||
@VisibleForTesting
|
||||
final class ScanRequest {
|
||||
/** The parsed package */
|
||||
@NonNull public final ParsedPackage mParsedPackage;
|
||||
/** The package this package replaces */
|
||||
@Nullable public final AndroidPackage mOldPkg;
|
||||
/** Shared user settings, if the package has a shared user */
|
||||
@Nullable public final SharedUserSetting mSharedUserSetting;
|
||||
/**
|
||||
* Package settings of the currently installed version.
|
||||
* <p><em>IMPORTANT:</em> The contents of this object may be modified
|
||||
* during scan.
|
||||
*/
|
||||
@Nullable public final PackageSetting mPkgSetting;
|
||||
/** A copy of the settings for the currently installed version */
|
||||
@Nullable public final PackageSetting mOldPkgSetting;
|
||||
/** Package settings for the disabled version on the /system partition */
|
||||
@Nullable public final PackageSetting mDisabledPkgSetting;
|
||||
/** Package settings for the installed version under its original package name */
|
||||
@Nullable public final PackageSetting mOriginalPkgSetting;
|
||||
/** The real package name of a renamed application */
|
||||
@Nullable public final String mRealPkgName;
|
||||
public final @ParsingPackageUtils.ParseFlags int mParseFlags;
|
||||
public final @PackageManagerService.ScanFlags int mScanFlags;
|
||||
/** The user for which the package is being scanned */
|
||||
@Nullable public final UserHandle mUser;
|
||||
/** Whether or not the platform package is being scanned */
|
||||
public final boolean mIsPlatformPackage;
|
||||
/** Override value for package ABI if set during install */
|
||||
@Nullable public final String mCpuAbiOverride;
|
||||
|
||||
ScanRequest(
|
||||
@NonNull ParsedPackage parsedPackage,
|
||||
@Nullable SharedUserSetting sharedUserSetting,
|
||||
@Nullable AndroidPackage oldPkg,
|
||||
@Nullable PackageSetting pkgSetting,
|
||||
@Nullable PackageSetting disabledPkgSetting,
|
||||
@Nullable PackageSetting originalPkgSetting,
|
||||
@Nullable String realPkgName,
|
||||
@ParsingPackageUtils.ParseFlags int parseFlags,
|
||||
@PackageManagerService.ScanFlags int scanFlags,
|
||||
boolean isPlatformPackage,
|
||||
@Nullable UserHandle user,
|
||||
@Nullable String cpuAbiOverride) {
|
||||
mParsedPackage = parsedPackage;
|
||||
mOldPkg = oldPkg;
|
||||
mPkgSetting = pkgSetting;
|
||||
mSharedUserSetting = sharedUserSetting;
|
||||
mOldPkgSetting = pkgSetting == null ? null : new PackageSetting(pkgSetting);
|
||||
mDisabledPkgSetting = disabledPkgSetting;
|
||||
mOriginalPkgSetting = originalPkgSetting;
|
||||
mRealPkgName = realPkgName;
|
||||
mParseFlags = parseFlags;
|
||||
mScanFlags = scanFlags;
|
||||
mIsPlatformPackage = isPlatformPackage;
|
||||
mUser = user;
|
||||
mCpuAbiOverride = cpuAbiOverride;
|
||||
}
|
||||
}
|
||||
65
services/core/java/com/android/server/pm/ScanResult.java
Normal file
65
services/core/java/com/android/server/pm/ScanResult.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.content.pm.SharedLibraryInfo;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** The result of a package scan. */
|
||||
@VisibleForTesting
|
||||
final class ScanResult {
|
||||
/** The request that initiated the scan that produced this result. */
|
||||
public final ScanRequest mRequest;
|
||||
/** Whether or not the package scan was successful */
|
||||
public final boolean mSuccess;
|
||||
/**
|
||||
* Whether or not the original PackageSetting needs to be updated with this result on
|
||||
* commit.
|
||||
*/
|
||||
public final boolean mExistingSettingCopied;
|
||||
/**
|
||||
* The final package settings. This may be the same object passed in
|
||||
* the {@link ScanRequest}, but, with modified values.
|
||||
*/
|
||||
@Nullable
|
||||
public final PackageSetting mPkgSetting;
|
||||
/** ABI code paths that have changed in the package scan */
|
||||
@Nullable public final List<String> mChangedAbiCodePath;
|
||||
|
||||
public final SharedLibraryInfo mStaticSharedLibraryInfo;
|
||||
|
||||
public final List<SharedLibraryInfo> mDynamicSharedLibraryInfos;
|
||||
|
||||
ScanResult(
|
||||
ScanRequest request, boolean success,
|
||||
@Nullable PackageSetting pkgSetting,
|
||||
@Nullable List<String> changedAbiCodePath, boolean existingSettingCopied,
|
||||
SharedLibraryInfo staticSharedLibraryInfo,
|
||||
List<SharedLibraryInfo> dynamicSharedLibraryInfos) {
|
||||
mRequest = request;
|
||||
mSuccess = success;
|
||||
mPkgSetting = pkgSetting;
|
||||
mChangedAbiCodePath = changedAbiCodePath;
|
||||
mExistingSettingCopied = existingSettingCopied;
|
||||
mStaticSharedLibraryInfo = staticSharedLibraryInfo;
|
||||
mDynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
final class SystemDeleteException extends Exception {
|
||||
final PackageManagerException mReason;
|
||||
|
||||
SystemDeleteException(PackageManagerException reason) {
|
||||
mReason = reason;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
final class VerificationInfo {
|
||||
/** URI referencing where the package was downloaded from. */
|
||||
final Uri mOriginatingUri;
|
||||
|
||||
/** HTTP referrer URI associated with the originatingURI. */
|
||||
final Uri mReferrer;
|
||||
|
||||
/** UID of the application that the install request originated from. */
|
||||
final int mOriginatingUid;
|
||||
|
||||
/** UID of application requesting the install */
|
||||
final int mInstallerUid;
|
||||
|
||||
VerificationInfo(Uri originatingUri, Uri referrer, int originatingUid, int installerUid) {
|
||||
mOriginatingUri = originatingUri;
|
||||
mReferrer = referrer;
|
||||
mOriginatingUid = originatingUid;
|
||||
mInstallerUid = installerUid;
|
||||
}
|
||||
}
|
||||
778
services/core/java/com/android/server/pm/VerificationParams.java
Normal file
778
services/core/java/com/android/server/pm/VerificationParams.java
Normal file
@@ -0,0 +1,778 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.pm;
|
||||
|
||||
import static android.content.Intent.EXTRA_LONG_VERSION_CODE;
|
||||
import static android.content.Intent.EXTRA_PACKAGE_NAME;
|
||||
import static android.content.Intent.EXTRA_VERSION_CODE;
|
||||
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
|
||||
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
|
||||
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
|
||||
import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4;
|
||||
import static android.os.PowerWhitelistManager.REASON_PACKAGE_VERIFIER;
|
||||
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
|
||||
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
|
||||
|
||||
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_INTEGRITY_VERIFICATION;
|
||||
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
|
||||
import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY;
|
||||
import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_TIMEOUT;
|
||||
import static com.android.server.pm.PackageManagerService.PACKAGE_MIME_TYPE;
|
||||
import static com.android.server.pm.PackageManagerService.TAG;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.BroadcastOptions;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.DataLoaderType;
|
||||
import android.content.pm.IPackageInstallObserver2;
|
||||
import android.content.pm.PackageInfoLite;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.SigningDetails;
|
||||
import android.content.pm.VerifierInfo;
|
||||
import android.content.pm.parsing.PackageLite;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Message;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.DeviceIdleInternal;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
final class VerificationParams extends HandlerParams {
|
||||
/**
|
||||
* Whether integrity verification is enabled by default.
|
||||
*/
|
||||
private static final boolean DEFAULT_INTEGRITY_VERIFY_ENABLE = true;
|
||||
/**
|
||||
* The default maximum time to wait for the integrity verification to return in
|
||||
* milliseconds.
|
||||
*/
|
||||
private static final long DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT = 30 * 1000;
|
||||
/**
|
||||
* Whether verification is enabled by default.
|
||||
*/
|
||||
private static final boolean DEFAULT_VERIFY_ENABLE = true;
|
||||
/**
|
||||
* Timeout duration in milliseconds for enabling package rollback. If we fail to enable
|
||||
* rollback within that period, the install will proceed without rollback enabled.
|
||||
*
|
||||
* <p>If flag value is negative, the default value will be assigned.
|
||||
*
|
||||
* Flag type: {@code long}
|
||||
* Namespace: NAMESPACE_ROLLBACK
|
||||
*/
|
||||
private static final String PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS = "enable_rollback_timeout";
|
||||
/**
|
||||
* The default duration to wait for rollback to be enabled in
|
||||
* milliseconds.
|
||||
*/
|
||||
private static final long DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS = 10 * 1000;
|
||||
|
||||
final OriginInfo mOriginInfo;
|
||||
final IPackageInstallObserver2 mObserver;
|
||||
final int mInstallFlags;
|
||||
@NonNull
|
||||
final InstallSource mInstallSource;
|
||||
final String mPackageAbiOverride;
|
||||
final VerificationInfo mVerificationInfo;
|
||||
final SigningDetails mSigningDetails;
|
||||
@Nullable
|
||||
MultiPackageVerificationParams mParentVerificationParams;
|
||||
final long mRequiredInstalledVersionCode;
|
||||
final int mDataLoaderType;
|
||||
final int mSessionId;
|
||||
|
||||
private boolean mWaitForVerificationToComplete;
|
||||
private boolean mWaitForIntegrityVerificationToComplete;
|
||||
private boolean mWaitForEnableRollbackToComplete;
|
||||
private int mRet = PackageManager.INSTALL_SUCCEEDED;
|
||||
private String mErrorMessage = null;
|
||||
|
||||
final PackageLite mPackageLite;
|
||||
final PackageManagerService mPm;
|
||||
|
||||
VerificationParams(UserHandle user, File stagedDir, IPackageInstallObserver2 observer,
|
||||
PackageInstaller.SessionParams sessionParams, InstallSource installSource,
|
||||
int installerUid, SigningDetails signingDetails, int sessionId, PackageLite lite,
|
||||
PackageManagerService pm) {
|
||||
super(user);
|
||||
mOriginInfo = OriginInfo.fromStagedFile(stagedDir);
|
||||
mObserver = observer;
|
||||
mInstallFlags = sessionParams.installFlags;
|
||||
mInstallSource = installSource;
|
||||
mPackageAbiOverride = sessionParams.abiOverride;
|
||||
mVerificationInfo = new VerificationInfo(
|
||||
sessionParams.originatingUri,
|
||||
sessionParams.referrerUri,
|
||||
sessionParams.originatingUid,
|
||||
installerUid
|
||||
);
|
||||
mSigningDetails = signingDetails;
|
||||
mRequiredInstalledVersionCode = sessionParams.requiredInstalledVersionCode;
|
||||
mDataLoaderType = (sessionParams.dataLoaderParams != null)
|
||||
? sessionParams.dataLoaderParams.getType() : DataLoaderType.NONE;
|
||||
mSessionId = sessionId;
|
||||
mPackageLite = lite;
|
||||
mPm = pm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InstallParams{" + Integer.toHexString(System.identityHashCode(this))
|
||||
+ " file=" + mOriginInfo.mFile + "}";
|
||||
}
|
||||
|
||||
public void handleStartCopy() {
|
||||
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mPm.mContext,
|
||||
mPackageLite, mOriginInfo.mResolvedPath, mInstallFlags, mPackageAbiOverride);
|
||||
|
||||
Pair<Integer, String> ret = mPm.verifyReplacingVersionCode(
|
||||
pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
|
||||
setReturnCode(ret.first, ret.second);
|
||||
if (mRet != INSTALL_SUCCEEDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Perform package verification and enable rollback (unless we are simply moving the
|
||||
// package).
|
||||
if (!mOriginInfo.mExisting) {
|
||||
if ((mInstallFlags & PackageManager.INSTALL_APEX) == 0) {
|
||||
// TODO(b/182426975): treat APEX as APK when APK verification is concerned
|
||||
sendApkVerificationRequest(pkgLite);
|
||||
}
|
||||
if ((mInstallFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
|
||||
sendEnableRollbackRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sendApkVerificationRequest(PackageInfoLite pkgLite) {
|
||||
final int verificationId = mPm.mPendingVerificationToken++;
|
||||
|
||||
PackageVerificationState verificationState =
|
||||
new PackageVerificationState(this);
|
||||
mPm.mPendingVerification.append(verificationId, verificationState);
|
||||
|
||||
sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
|
||||
sendPackageVerificationRequest(
|
||||
verificationId, pkgLite, verificationState);
|
||||
|
||||
// If both verifications are skipped, we should remove the state.
|
||||
if (verificationState.areAllVerificationsComplete()) {
|
||||
mPm.mPendingVerification.remove(verificationId);
|
||||
}
|
||||
}
|
||||
|
||||
void sendEnableRollbackRequest() {
|
||||
final int enableRollbackToken = mPm.mPendingEnableRollbackToken++;
|
||||
Trace.asyncTraceBegin(
|
||||
TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
|
||||
mPm.mPendingEnableRollback.append(enableRollbackToken, this);
|
||||
|
||||
Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);
|
||||
enableRollbackIntent.putExtra(
|
||||
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
|
||||
enableRollbackToken);
|
||||
enableRollbackIntent.putExtra(
|
||||
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_SESSION_ID,
|
||||
mSessionId);
|
||||
enableRollbackIntent.setType(PACKAGE_MIME_TYPE);
|
||||
enableRollbackIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
// Allow the broadcast to be sent before boot complete.
|
||||
// This is needed when committing the apk part of a staged
|
||||
// session in early boot. The rollback manager registers
|
||||
// its receiver early enough during the boot process that
|
||||
// it will not miss the broadcast.
|
||||
enableRollbackIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
||||
|
||||
mPm.mContext.sendBroadcastAsUser(enableRollbackIntent, UserHandle.SYSTEM,
|
||||
android.Manifest.permission.PACKAGE_ROLLBACK_AGENT);
|
||||
|
||||
mWaitForEnableRollbackToComplete = true;
|
||||
|
||||
// the duration to wait for rollback to be enabled, in millis
|
||||
long rollbackTimeout = DeviceConfig.getLong(
|
||||
DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS,
|
||||
DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS);
|
||||
if (rollbackTimeout < 0) {
|
||||
rollbackTimeout = DEFAULT_ENABLE_ROLLBACK_TIMEOUT_MILLIS;
|
||||
}
|
||||
final Message msg = mPm.mHandler.obtainMessage(ENABLE_ROLLBACK_TIMEOUT);
|
||||
msg.arg1 = enableRollbackToken;
|
||||
msg.arg2 = mSessionId;
|
||||
mPm.mHandler.sendMessageDelayed(msg, rollbackTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to check the integrity of the package.
|
||||
*/
|
||||
void sendIntegrityVerificationRequest(
|
||||
int verificationId,
|
||||
PackageInfoLite pkgLite,
|
||||
PackageVerificationState verificationState) {
|
||||
if (!isIntegrityVerificationEnabled()) {
|
||||
// Consider the integrity check as passed.
|
||||
verificationState.setIntegrityVerificationResult(
|
||||
PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
|
||||
return;
|
||||
}
|
||||
|
||||
final Intent integrityVerification =
|
||||
new Intent(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
|
||||
|
||||
integrityVerification.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
|
||||
PACKAGE_MIME_TYPE);
|
||||
|
||||
final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
| Intent.FLAG_RECEIVER_REGISTERED_ONLY
|
||||
| Intent.FLAG_RECEIVER_FOREGROUND;
|
||||
integrityVerification.addFlags(flags);
|
||||
|
||||
integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
|
||||
integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
|
||||
integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
|
||||
integrityVerification.putExtra(EXTRA_LONG_VERSION_CODE, pkgLite.getLongVersionCode());
|
||||
populateInstallerExtras(integrityVerification);
|
||||
|
||||
// send to integrity component only.
|
||||
integrityVerification.setPackage("android");
|
||||
|
||||
final BroadcastOptions options = BroadcastOptions.makeBasic();
|
||||
|
||||
mPm.mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
|
||||
/* receiverPermission= */ null,
|
||||
/* appOp= */ AppOpsManager.OP_NONE,
|
||||
/* options= */ options.toBundle(),
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final Message msg =
|
||||
mPm.mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
|
||||
msg.arg1 = verificationId;
|
||||
mPm.mHandler.sendMessageDelayed(msg, getIntegrityVerificationTimeout());
|
||||
}
|
||||
}, /* scheduler= */ null,
|
||||
/* initialCode= */ 0,
|
||||
/* initialData= */ null,
|
||||
/* initialExtras= */ null);
|
||||
|
||||
Trace.asyncTraceBegin(
|
||||
TRACE_TAG_PACKAGE_MANAGER, "integrity_verification", verificationId);
|
||||
|
||||
// stop the copy until verification succeeds.
|
||||
mWaitForIntegrityVerificationToComplete = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the integrity verification timeout.
|
||||
*
|
||||
* @return verification timeout in milliseconds
|
||||
*/
|
||||
private long getIntegrityVerificationTimeout() {
|
||||
long timeout = Settings.Global.getLong(mPm.mContext.getContentResolver(),
|
||||
Settings.Global.APP_INTEGRITY_VERIFICATION_TIMEOUT,
|
||||
DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT);
|
||||
// The setting can be used to increase the timeout but not decrease it, since that is
|
||||
// equivalent to disabling the integrity component.
|
||||
return Math.max(timeout, DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not integrity verification has been enabled.
|
||||
*/
|
||||
private boolean isIntegrityVerificationEnabled() {
|
||||
// We are not exposing this as a user-configurable setting because we don't want to provide
|
||||
// an easy way to get around the integrity check.
|
||||
return DEFAULT_INTEGRITY_VERIFY_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a request to verifier(s) to verify the package if necessary.
|
||||
*/
|
||||
void sendPackageVerificationRequest(
|
||||
int verificationId,
|
||||
PackageInfoLite pkgLite,
|
||||
PackageVerificationState verificationState) {
|
||||
|
||||
// TODO: http://b/22976637
|
||||
// Apps installed for "all" users use the device owner to verify the app
|
||||
UserHandle verifierUser = getUser();
|
||||
if (verifierUser == UserHandle.ALL) {
|
||||
verifierUser = UserHandle.SYSTEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if we have any installed package verifiers. If we
|
||||
* do, then we'll defer to them to verify the packages.
|
||||
*/
|
||||
final int requiredUid = mPm.mRequiredVerifierPackage == null ? -1
|
||||
: mPm.getPackageUid(mPm.mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
|
||||
verifierUser.getIdentifier());
|
||||
verificationState.setRequiredVerifierUid(requiredUid);
|
||||
final int installerUid =
|
||||
mVerificationInfo == null ? -1 : mVerificationInfo.mInstallerUid;
|
||||
final boolean isVerificationEnabled = isVerificationEnabled(
|
||||
pkgLite, verifierUser.getIdentifier(), mInstallFlags, installerUid);
|
||||
final boolean isV4Signed =
|
||||
(mSigningDetails.getSignatureSchemeVersion() == SIGNING_BLOCK_V4);
|
||||
final boolean isIncrementalInstall =
|
||||
(mDataLoaderType == DataLoaderType.INCREMENTAL);
|
||||
// NOTE: We purposefully skip verification for only incremental installs when there's
|
||||
// a v4 signature block. Otherwise, proceed with verification as usual.
|
||||
if (!mOriginInfo.mExisting
|
||||
&& isVerificationEnabled
|
||||
&& (!isIncrementalInstall || !isV4Signed)) {
|
||||
final Intent verification = new Intent(
|
||||
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
|
||||
verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
|
||||
verification.setDataAndType(Uri.fromFile(new File(mOriginInfo.mResolvedPath)),
|
||||
PACKAGE_MIME_TYPE);
|
||||
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
// Query all live verifiers based on current user state
|
||||
final ParceledListSlice<ResolveInfo> receivers = mPm.queryIntentReceivers(verification,
|
||||
PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier());
|
||||
|
||||
if (DEBUG_VERIFY) {
|
||||
Slog.d(TAG, "Found " + receivers.getList().size() + " verifiers for intent "
|
||||
+ verification.toString() + " with " + pkgLite.verifiers.length
|
||||
+ " optional verifiers");
|
||||
}
|
||||
|
||||
verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
|
||||
|
||||
verification.putExtra(
|
||||
PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, mInstallFlags);
|
||||
|
||||
verification.putExtra(
|
||||
PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);
|
||||
|
||||
verification.putExtra(
|
||||
PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);
|
||||
|
||||
verification.putExtra(
|
||||
PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
|
||||
pkgLite.getLongVersionCode());
|
||||
|
||||
populateInstallerExtras(verification);
|
||||
|
||||
final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
|
||||
receivers.getList(), verificationState);
|
||||
|
||||
DeviceIdleInternal idleController =
|
||||
mPm.mInjector.getLocalService(DeviceIdleInternal.class);
|
||||
final long idleDuration = mPm.getVerificationTimeout();
|
||||
final BroadcastOptions options = BroadcastOptions.makeBasic();
|
||||
options.setTemporaryAppAllowlist(idleDuration,
|
||||
TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
|
||||
REASON_PACKAGE_VERIFIER, "");
|
||||
|
||||
/*
|
||||
* If any sufficient verifiers were listed in the package
|
||||
* manifest, attempt to ask them.
|
||||
*/
|
||||
if (sufficientVerifiers != null) {
|
||||
final int n = sufficientVerifiers.size();
|
||||
if (n == 0) {
|
||||
String errorMsg = "Additional verifiers required, but none installed.";
|
||||
Slog.i(TAG, errorMsg);
|
||||
setReturnCode(PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
|
||||
} else {
|
||||
for (int i = 0; i < n; i++) {
|
||||
final ComponentName verifierComponent = sufficientVerifiers.get(i);
|
||||
idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
|
||||
verifierComponent.getPackageName(), idleDuration,
|
||||
verifierUser.getIdentifier(), false,
|
||||
REASON_PACKAGE_VERIFIER, "package verifier");
|
||||
|
||||
final Intent sufficientIntent = new Intent(verification);
|
||||
sufficientIntent.setComponent(verifierComponent);
|
||||
mPm.mContext.sendBroadcastAsUser(sufficientIntent, verifierUser,
|
||||
/* receiverPermission= */ null,
|
||||
options.toBundle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mPm.mRequiredVerifierPackage != null) {
|
||||
final ComponentName requiredVerifierComponent = matchComponentForVerifier(
|
||||
mPm.mRequiredVerifierPackage, receivers.getList());
|
||||
/*
|
||||
* Send the intent to the required verification agent,
|
||||
* but only start the verification timeout after the
|
||||
* target BroadcastReceivers have run.
|
||||
*/
|
||||
verification.setComponent(requiredVerifierComponent);
|
||||
idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
|
||||
mPm.mRequiredVerifierPackage, idleDuration,
|
||||
verifierUser.getIdentifier(), false,
|
||||
REASON_PACKAGE_VERIFIER, "package verifier");
|
||||
mPm.mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
|
||||
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
|
||||
/* appOp= */ AppOpsManager.OP_NONE,
|
||||
/* options= */ options.toBundle(),
|
||||
new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final Message msg = mPm.mHandler
|
||||
.obtainMessage(CHECK_PENDING_VERIFICATION);
|
||||
msg.arg1 = verificationId;
|
||||
mPm.mHandler.sendMessageDelayed(msg, mPm.getVerificationTimeout());
|
||||
}
|
||||
}, null, 0, null, null);
|
||||
|
||||
Trace.asyncTraceBegin(
|
||||
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
|
||||
|
||||
/*
|
||||
* We don't want the copy to proceed until verification
|
||||
* succeeds.
|
||||
*/
|
||||
mWaitForVerificationToComplete = true;
|
||||
}
|
||||
} else {
|
||||
verificationState.setVerifierResponse(
|
||||
requiredUid, PackageManager.VERIFICATION_ALLOW);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<ComponentName> matchVerifiers(PackageInfoLite pkgInfo,
|
||||
List<ResolveInfo> receivers, final PackageVerificationState verificationState) {
|
||||
if (pkgInfo.verifiers.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int n = pkgInfo.verifiers.length;
|
||||
final List<ComponentName> sufficientVerifiers = new ArrayList<>(n + 1);
|
||||
for (int i = 0; i < n; i++) {
|
||||
final VerifierInfo verifierInfo = pkgInfo.verifiers[i];
|
||||
|
||||
final ComponentName comp = matchComponentForVerifier(verifierInfo.packageName,
|
||||
receivers);
|
||||
if (comp == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int verifierUid = getUidForVerifier(verifierInfo);
|
||||
if (verifierUid == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DEBUG_VERIFY) {
|
||||
Slog.d(TAG, "Added sufficient verifier " + verifierInfo.packageName
|
||||
+ " with the correct signature");
|
||||
}
|
||||
sufficientVerifiers.add(comp);
|
||||
verificationState.addSufficientVerifier(verifierUid);
|
||||
}
|
||||
|
||||
return sufficientVerifiers;
|
||||
}
|
||||
|
||||
private int getUidForVerifier(VerifierInfo verifierInfo) {
|
||||
synchronized (mPm.mLock) {
|
||||
final AndroidPackage pkg = mPm.mPackages.get(verifierInfo.packageName);
|
||||
if (pkg == null) {
|
||||
return -1;
|
||||
} else if (pkg.getSigningDetails().getSignatures().length != 1) {
|
||||
Slog.i(TAG, "Verifier package " + verifierInfo.packageName
|
||||
+ " has more than one signature; ignoring");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the public key of the package's signature does not match
|
||||
* our expected public key, then this is a different package and
|
||||
* we should skip.
|
||||
*/
|
||||
|
||||
final byte[] expectedPublicKey;
|
||||
try {
|
||||
final Signature verifierSig = pkg.getSigningDetails().getSignatures()[0];
|
||||
final PublicKey publicKey = verifierSig.getPublicKey();
|
||||
expectedPublicKey = publicKey.getEncoded();
|
||||
} catch (CertificateException e) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
|
||||
|
||||
if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
|
||||
Slog.i(TAG, "Verifier package " + verifierInfo.packageName
|
||||
+ " does not have the expected public key; ignoring");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return pkg.getUid();
|
||||
}
|
||||
}
|
||||
|
||||
private static ComponentName matchComponentForVerifier(String packageName,
|
||||
List<ResolveInfo> receivers) {
|
||||
ActivityInfo targetReceiver = null;
|
||||
|
||||
final int nr = receivers.size();
|
||||
for (int i = 0; i < nr; i++) {
|
||||
final ResolveInfo info = receivers.get(i);
|
||||
if (info.activityInfo == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (packageName.equals(info.activityInfo.packageName)) {
|
||||
targetReceiver = info.activityInfo;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetReceiver == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ComponentName(targetReceiver.packageName, targetReceiver.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether or not package verification has been enabled.
|
||||
*
|
||||
* @return true if verification should be performed
|
||||
*/
|
||||
private boolean isVerificationEnabled(
|
||||
PackageInfoLite pkgInfoLite, int userId, int installFlags, int installerUid) {
|
||||
if (!DEFAULT_VERIFY_ENABLE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if installing from ADB
|
||||
if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
|
||||
if (mPm.isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
|
||||
return true;
|
||||
}
|
||||
// Check if the developer wants to skip verification for ADB installs
|
||||
if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {
|
||||
synchronized (mPm.mLock) {
|
||||
if (mPm.mSettings.getPackageLPr(pkgInfoLite.packageName) == null) {
|
||||
// Always verify fresh install
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Only skip when apk is debuggable
|
||||
return !pkgInfoLite.debuggable;
|
||||
}
|
||||
return Settings.Global.getInt(mPm.mContext.getContentResolver(),
|
||||
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
|
||||
}
|
||||
|
||||
// only when not installed from ADB, skip verification for instant apps when
|
||||
// the installer and verifier are the same.
|
||||
if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
|
||||
if (mPm.mInstantAppInstallerActivity != null
|
||||
&& mPm.mInstantAppInstallerActivity.packageName.equals(
|
||||
mPm.mRequiredVerifierPackage)) {
|
||||
try {
|
||||
mPm.mInjector.getSystemService(AppOpsManager.class)
|
||||
.checkPackage(installerUid, mPm.mRequiredVerifierPackage);
|
||||
if (DEBUG_VERIFY) {
|
||||
Slog.i(TAG, "disable verification for instant app");
|
||||
}
|
||||
return false;
|
||||
} catch (SecurityException ignore) { }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void populateInstallerExtras(Intent intent) {
|
||||
intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
|
||||
mInstallSource.initiatingPackageName);
|
||||
|
||||
if (mVerificationInfo != null) {
|
||||
if (mVerificationInfo.mOriginatingUri != null) {
|
||||
intent.putExtra(Intent.EXTRA_ORIGINATING_URI,
|
||||
mVerificationInfo.mOriginatingUri);
|
||||
}
|
||||
if (mVerificationInfo.mReferrer != null) {
|
||||
intent.putExtra(Intent.EXTRA_REFERRER,
|
||||
mVerificationInfo.mReferrer);
|
||||
}
|
||||
if (mVerificationInfo.mOriginatingUid >= 0) {
|
||||
intent.putExtra(Intent.EXTRA_ORIGINATING_UID,
|
||||
mVerificationInfo.mOriginatingUid);
|
||||
}
|
||||
if (mVerificationInfo.mInstallerUid >= 0) {
|
||||
intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
|
||||
mVerificationInfo.mInstallerUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setReturnCode(int ret, String message) {
|
||||
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
|
||||
// Only update mRet if it was previously INSTALL_SUCCEEDED to
|
||||
// ensure we do not overwrite any previous failure results.
|
||||
mRet = ret;
|
||||
mErrorMessage = message;
|
||||
}
|
||||
}
|
||||
|
||||
void handleVerificationFinished() {
|
||||
mWaitForVerificationToComplete = false;
|
||||
handleReturnCode();
|
||||
}
|
||||
|
||||
void handleIntegrityVerificationFinished() {
|
||||
mWaitForIntegrityVerificationToComplete = false;
|
||||
handleReturnCode();
|
||||
}
|
||||
|
||||
|
||||
void handleRollbackEnabled() {
|
||||
// TODO(b/112431924): Consider halting the install if we
|
||||
// couldn't enable rollback.
|
||||
mWaitForEnableRollbackToComplete = false;
|
||||
handleReturnCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleReturnCode() {
|
||||
if (mWaitForVerificationToComplete || mWaitForIntegrityVerificationToComplete
|
||||
|| mWaitForEnableRollbackToComplete) {
|
||||
return;
|
||||
}
|
||||
sendVerificationCompleteNotification();
|
||||
}
|
||||
|
||||
private void sendVerificationCompleteNotification() {
|
||||
if (mParentVerificationParams != null) {
|
||||
mParentVerificationParams.trySendVerificationCompleteNotification(this, mRet);
|
||||
} else {
|
||||
try {
|
||||
mObserver.onPackageInstalled(null, mRet, mErrorMessage,
|
||||
new Bundle());
|
||||
} catch (RemoteException e) {
|
||||
Slog.i(TAG, "Observer no longer exists.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void verifyStage() {
|
||||
mPm.mHandler.post(this::startCopy);
|
||||
}
|
||||
|
||||
public void verifyStage(List<VerificationParams> children)
|
||||
throws PackageManagerException {
|
||||
final MultiPackageVerificationParams params =
|
||||
new MultiPackageVerificationParams(this, children);
|
||||
mPm.mHandler.post(params::startCopy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Container for a multi-package install which refers to all install sessions and args being
|
||||
* committed together.
|
||||
*/
|
||||
static final class MultiPackageVerificationParams extends HandlerParams {
|
||||
private final IPackageInstallObserver2 mObserver;
|
||||
private final List<VerificationParams> mChildParams;
|
||||
private final Map<VerificationParams, Integer> mVerificationState;
|
||||
|
||||
MultiPackageVerificationParams(VerificationParams parent, List<VerificationParams> children)
|
||||
throws PackageManagerException {
|
||||
super(parent.getUser());
|
||||
if (children.size() == 0) {
|
||||
throw new PackageManagerException("No child sessions found!");
|
||||
}
|
||||
mChildParams = children;
|
||||
// Provide every child with reference to this object as parent
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
final VerificationParams childParams = children.get(i);
|
||||
childParams.mParentVerificationParams = this;
|
||||
}
|
||||
mVerificationState = new ArrayMap<>(mChildParams.size());
|
||||
mObserver = parent.mObserver;
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleStartCopy() {
|
||||
for (VerificationParams params : mChildParams) {
|
||||
params.handleStartCopy();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleReturnCode() {
|
||||
for (VerificationParams params : mChildParams) {
|
||||
params.handleReturnCode();
|
||||
}
|
||||
}
|
||||
|
||||
void trySendVerificationCompleteNotification(VerificationParams child, int currentStatus) {
|
||||
mVerificationState.put(child, currentStatus);
|
||||
if (mVerificationState.size() != mChildParams.size()) {
|
||||
return;
|
||||
}
|
||||
int completeStatus = PackageManager.INSTALL_SUCCEEDED;
|
||||
String errorMsg = null;
|
||||
for (VerificationParams params : mVerificationState.keySet()) {
|
||||
int status = params.mRet;
|
||||
if (status == PackageManager.INSTALL_UNKNOWN) {
|
||||
return;
|
||||
} else if (status != PackageManager.INSTALL_SUCCEEDED) {
|
||||
completeStatus = status;
|
||||
errorMsg = params.mErrorMessage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
mObserver.onPackageInstalled(null, completeStatus,
|
||||
errorMsg, new Bundle());
|
||||
} catch (RemoteException e) {
|
||||
Slog.i(TAG, "Observer no longer exists.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,16 +101,15 @@ public class PackageManagerServiceTest {
|
||||
|
||||
PackageSenderImpl sender = new PackageSenderImpl();
|
||||
PackageSetting setting = null;
|
||||
PackageManagerService.PackageRemovedInfo pri =
|
||||
new PackageManagerService.PackageRemovedInfo(sender);
|
||||
PackageRemovedInfo pri = new PackageRemovedInfo(sender);
|
||||
|
||||
// Initial conditions: nothing there
|
||||
Assert.assertNull(pri.removedUsers);
|
||||
Assert.assertNull(pri.broadcastUsers);
|
||||
Assert.assertNull(pri.mRemovedUsers);
|
||||
Assert.assertNull(pri.mBroadcastUsers);
|
||||
|
||||
// populateUsers with nothing leaves nothing
|
||||
pri.populateUsers(null, setting);
|
||||
Assert.assertNull(pri.broadcastUsers);
|
||||
Assert.assertNull(pri.mBroadcastUsers);
|
||||
|
||||
// Create a real (non-null) PackageSetting and confirm that the removed
|
||||
// users are copied properly
|
||||
@@ -126,22 +125,22 @@ public class PackageManagerServiceTest {
|
||||
pri.populateUsers(new int[] {
|
||||
1, 2, 3, 4, 5
|
||||
}, setting);
|
||||
Assert.assertNotNull(pri.broadcastUsers);
|
||||
Assert.assertEquals(5, pri.broadcastUsers.length);
|
||||
Assert.assertNotNull(pri.instantUserIds);
|
||||
Assert.assertEquals(0, pri.instantUserIds.length);
|
||||
Assert.assertNotNull(pri.mBroadcastUsers);
|
||||
Assert.assertEquals(5, pri.mBroadcastUsers.length);
|
||||
Assert.assertNotNull(pri.mInstantUserIds);
|
||||
Assert.assertEquals(0, pri.mInstantUserIds.length);
|
||||
|
||||
// Exclude a user
|
||||
pri.broadcastUsers = null;
|
||||
pri.mBroadcastUsers = null;
|
||||
final int EXCLUDED_USER_ID = 4;
|
||||
setting.setInstantApp(true, EXCLUDED_USER_ID);
|
||||
pri.populateUsers(new int[] {
|
||||
1, 2, 3, EXCLUDED_USER_ID, 5
|
||||
}, setting);
|
||||
Assert.assertNotNull(pri.broadcastUsers);
|
||||
Assert.assertEquals(4, pri.broadcastUsers.length);
|
||||
Assert.assertNotNull(pri.instantUserIds);
|
||||
Assert.assertEquals(1, pri.instantUserIds.length);
|
||||
Assert.assertNotNull(pri.mBroadcastUsers);
|
||||
Assert.assertEquals(4, pri.mBroadcastUsers.length);
|
||||
Assert.assertNotNull(pri.mInstantUserIds);
|
||||
Assert.assertEquals(1, pri.mInstantUserIds.length);
|
||||
|
||||
// TODO: test that sendApplicationHiddenForUser() actually fills in
|
||||
// broadcastUsers
|
||||
|
||||
@@ -108,8 +108,8 @@ class ScanRequestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageManagerService.ScanRequest build() {
|
||||
return new PackageManagerService.ScanRequest(
|
||||
ScanRequest build() {
|
||||
return new ScanRequest(
|
||||
mPkg, mSharedUserSetting, mOldPkg, mPkgSetting, mDisabledPkgSetting,
|
||||
mOriginalPkgSetting, mRealPkgName, mParseFlags, mScanFlags, mIsPlatformPackage,
|
||||
mUser, mCpuAbiOverride);
|
||||
|
||||
@@ -129,16 +129,16 @@ public class ScanTests {
|
||||
|
||||
@Test
|
||||
public void newInstallSimpleAllNominal() throws Exception {
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.addScanFlag(PackageManagerService.SCAN_NEW_INSTALL)
|
||||
.addScanFlag(PackageManagerService.SCAN_AS_FULL_APP)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/);
|
||||
assertThat(scanResult.existingSettingCopied, is(false));
|
||||
assertThat(scanResult.mExistingSettingCopied, is(false));
|
||||
assertPathsNotDerived(scanResult);
|
||||
}
|
||||
|
||||
@@ -147,38 +147,38 @@ public class ScanTests {
|
||||
final int[] userIds = {0, 10, 11};
|
||||
when(mMockUserManager.getUserIds()).thenReturn(userIds);
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.setRealPkgName(null)
|
||||
.addScanFlag(PackageManagerService.SCAN_NEW_INSTALL)
|
||||
.addScanFlag(PackageManagerService.SCAN_AS_FULL_APP)
|
||||
.build();
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
for (int uid : userIds) {
|
||||
assertThat(scanResult.pkgSetting.readUserState(uid).installed, is(true));
|
||||
assertThat(scanResult.mPkgSetting.readUserState(uid).installed, is(true));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void installRealPackageName() throws Exception {
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.setRealPkgName("com.package.real")
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertThat(scanResult.pkgSetting.realName, is("com.package.real"));
|
||||
assertThat(scanResult.mPkgSetting.realName, is("com.package.real"));
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequestNoRealPkg =
|
||||
final ScanRequest scanRequestNoRealPkg =
|
||||
createBasicScanRequestBuilder(
|
||||
createBasicPackage(DUMMY_PACKAGE_NAME)
|
||||
.setRealPackage("com.package.real"))
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanResult scanResultNoReal = executeScan(scanRequestNoRealPkg);
|
||||
assertThat(scanResultNoReal.pkgSetting.realName, nullValue());
|
||||
final ScanResult scanResultNoReal = executeScan(scanRequestNoRealPkg);
|
||||
assertThat(scanResultNoReal.mPkgSetting.realName, nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -189,25 +189,25 @@ public class ScanTests {
|
||||
.setPrimaryCpuAbiString("primaryCpuAbi")
|
||||
.setSecondaryCpuAbiString("secondaryCpuAbi")
|
||||
.build();
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.addScanFlag(PackageManagerService.SCAN_AS_FULL_APP)
|
||||
.setPkgSetting(pkgSetting)
|
||||
.build();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertThat(scanResult.existingSettingCopied, is(true));
|
||||
assertThat(scanResult.mExistingSettingCopied, is(true));
|
||||
|
||||
// ensure we don't overwrite the existing pkgSetting, in case something post-scan fails
|
||||
assertNotSame(pkgSetting, scanResult.pkgSetting);
|
||||
assertNotSame(pkgSetting, scanResult.mPkgSetting);
|
||||
|
||||
assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/);
|
||||
|
||||
assertThat(scanResult.pkgSetting.primaryCpuAbiString, is("primaryCpuAbi"));
|
||||
assertThat(scanResult.pkgSetting.secondaryCpuAbiString, is("secondaryCpuAbi"));
|
||||
assertThat(scanResult.pkgSetting.cpuAbiOverrideString, nullValue());
|
||||
assertThat(scanResult.mPkgSetting.primaryCpuAbiString, is("primaryCpuAbi"));
|
||||
assertThat(scanResult.mPkgSetting.secondaryCpuAbiString, is("secondaryCpuAbi"));
|
||||
assertThat(scanResult.mPkgSetting.cpuAbiOverrideString, nullValue());
|
||||
|
||||
assertPathsNotDerived(scanResult);
|
||||
}
|
||||
@@ -221,13 +221,13 @@ public class ScanTests {
|
||||
.setInstantAppUserState(0, true)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.setPkgSetting(existingPkgSetting)
|
||||
.build();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, true /*isInstant*/);
|
||||
}
|
||||
@@ -244,24 +244,24 @@ public class ScanTests {
|
||||
.setBaseApkPath("/some/path.apk")
|
||||
.setSplitCodePaths(new String[] {"/some/other/path.apk"});
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest = new ScanRequestBuilder(pkg)
|
||||
final ScanRequest scanRequest = new ScanRequestBuilder(pkg)
|
||||
.setUser(UserHandle.of(0)).build();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getPackageName(), is("static.lib.pkg.123"));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getName(), is("static.lib"));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getLongVersion(), is(123L));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getType(), is(TYPE_STATIC));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getDeclaringPackage().getPackageName(),
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getPackageName(), is("static.lib.pkg.123"));
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getName(), is("static.lib"));
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getLongVersion(), is(123L));
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getType(), is(TYPE_STATIC));
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getDeclaringPackage().getPackageName(),
|
||||
is("static.lib.pkg"));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(),
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(),
|
||||
is(pkg.getLongVersionCode()));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getAllCodePaths(),
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getAllCodePaths(),
|
||||
hasItems("/some/path.apk", "/some/other/path.apk"));
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getDependencies(), nullValue());
|
||||
assertThat(scanResult.staticSharedLibraryInfo.getDependentPackages(), empty());
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getDependencies(), nullValue());
|
||||
assertThat(scanResult.mStaticSharedLibraryInfo.getDependentPackages(), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -276,13 +276,13 @@ public class ScanTests {
|
||||
.setBaseApkPath("/some/path.apk")
|
||||
.setSplitCodePaths(new String[] {"/some/other/path.apk"});
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
new ScanRequestBuilder(pkg).setUser(UserHandle.of(0)).build();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
final SharedLibraryInfo dynamicLib0 = scanResult.dynamicSharedLibraryInfos.get(0);
|
||||
final SharedLibraryInfo dynamicLib0 = scanResult.mDynamicSharedLibraryInfos.get(0);
|
||||
assertThat(dynamicLib0.getPackageName(), is("dynamic.lib.pkg"));
|
||||
assertThat(dynamicLib0.getName(), is("liba"));
|
||||
assertThat(dynamicLib0.getLongVersion(), is((long) VERSION_UNDEFINED));
|
||||
@@ -295,7 +295,7 @@ public class ScanTests {
|
||||
assertThat(dynamicLib0.getDependencies(), nullValue());
|
||||
assertThat(dynamicLib0.getDependentPackages(), empty());
|
||||
|
||||
final SharedLibraryInfo dynamicLib1 = scanResult.dynamicSharedLibraryInfos.get(1);
|
||||
final SharedLibraryInfo dynamicLib1 = scanResult.mDynamicSharedLibraryInfos.get(1);
|
||||
assertThat(dynamicLib1.getPackageName(), is("dynamic.lib.pkg"));
|
||||
assertThat(dynamicLib1.getName(), is("libb"));
|
||||
assertThat(dynamicLib1.getLongVersion(), is((long) VERSION_UNDEFINED));
|
||||
@@ -321,10 +321,10 @@ public class ScanTests {
|
||||
.hideAsParsed());
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(
|
||||
final ScanResult scanResult = executeScan(
|
||||
new ScanRequestBuilder(basicPackage).setPkgSetting(pkgSetting).build());
|
||||
|
||||
assertThat(scanResult.pkgSetting.volumeUuid, is(UUID_TWO.toString()));
|
||||
assertThat(scanResult.mPkgSetting.volumeUuid, is(UUID_TWO.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -337,7 +337,7 @@ public class ScanTests {
|
||||
.hideAsParsed());
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(new ScanRequestBuilder(
|
||||
final ScanResult scanResult = executeScan(new ScanRequestBuilder(
|
||||
basicPackage)
|
||||
.setPkgSetting(pkgSetting)
|
||||
.addScanFlag(SCAN_FIRST_BOOT_OR_UPGRADE)
|
||||
@@ -356,12 +356,12 @@ public class ScanTests {
|
||||
.hideAsParsed();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult result =
|
||||
final ScanResult result =
|
||||
executeScan(new ScanRequestBuilder(basicPackage)
|
||||
.setOriginalPkgSetting(originalPkgSetting)
|
||||
.build());
|
||||
|
||||
assertThat(result.request.parsedPackage.getPackageName(), is("original.package"));
|
||||
assertThat(result.mRequest.mParsedPackage.getPackageName(), is("original.package"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -373,14 +373,14 @@ public class ScanTests {
|
||||
.setInstantAppUserState(0, true)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.setPkgSetting(existingPkgSetting)
|
||||
.addScanFlag(SCAN_AS_FULL_APP)
|
||||
.build();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, false /*isInstant*/);
|
||||
}
|
||||
@@ -394,14 +394,14 @@ public class ScanTests {
|
||||
.setInstantAppUserState(0, false)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.setPkgSetting(existingPkgSetting)
|
||||
.addScanFlag(SCAN_AS_INSTANT_APP)
|
||||
.build();
|
||||
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertBasicPackageScanResult(scanResult, DUMMY_PACKAGE_NAME, true /*isInstant*/);
|
||||
}
|
||||
@@ -413,17 +413,17 @@ public class ScanTests {
|
||||
.setPkgFlags(ApplicationInfo.FLAG_SYSTEM)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(createBasicPackage(DUMMY_PACKAGE_NAME))
|
||||
.setPkgSetting(existingPkgSetting)
|
||||
.setDisabledPkgSetting(existingPkgSetting)
|
||||
.addScanFlag(SCAN_NEW_INSTALL)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.request.parsedPackage,
|
||||
scanResult.pkgSetting);
|
||||
int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.mRequest.mParsedPackage,
|
||||
scanResult.mPkgSetting);
|
||||
assertThat(appInfoFlags, hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP));
|
||||
}
|
||||
|
||||
@@ -432,14 +432,14 @@ public class ScanTests {
|
||||
final ParsingPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME)
|
||||
.addUsesPermission(new ParsedUsesPermission(Manifest.permission.FACTORY_TEST, 0));
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = PackageManagerService.scanPackageOnlyLI(
|
||||
final ScanResult scanResult = PackageManagerService.scanPackageOnlyLI(
|
||||
createBasicScanRequestBuilder(basicPackage).build(),
|
||||
mMockInjector,
|
||||
true /*isUnderFactoryTest*/,
|
||||
System.currentTimeMillis());
|
||||
|
||||
int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.request.parsedPackage,
|
||||
scanResult.request.pkgSetting);
|
||||
int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.mRequest.mParsedPackage,
|
||||
scanResult.mRequest.mPkgSetting);
|
||||
assertThat(appInfoFlags, hasFlag(ApplicationInfo.FLAG_FACTORY_TEST));
|
||||
}
|
||||
|
||||
@@ -449,13 +449,13 @@ public class ScanTests {
|
||||
.hideAsParsed())
|
||||
.setSystem(true);
|
||||
|
||||
final PackageManagerService.ScanRequest scanRequest =
|
||||
final ScanRequest scanRequest =
|
||||
createBasicScanRequestBuilder(pkg)
|
||||
.build();
|
||||
|
||||
final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
|
||||
final ScanResult scanResult = executeScan(scanRequest);
|
||||
|
||||
assertThat(scanResult.pkgSetting.installSource.isOrphaned, is(true));
|
||||
assertThat(scanResult.mPkgSetting.installSource.isOrphaned, is(true));
|
||||
}
|
||||
|
||||
private static Matcher<Integer> hasFlag(final int flag) {
|
||||
@@ -478,9 +478,9 @@ public class ScanTests {
|
||||
};
|
||||
}
|
||||
|
||||
private PackageManagerService.ScanResult executeScan(
|
||||
PackageManagerService.ScanRequest scanRequest) throws PackageManagerException {
|
||||
PackageManagerService.ScanResult result = PackageManagerService.scanPackageOnlyLI(
|
||||
private ScanResult executeScan(
|
||||
ScanRequest scanRequest) throws PackageManagerException {
|
||||
ScanResult result = PackageManagerService.scanPackageOnlyLI(
|
||||
scanRequest,
|
||||
mMockInjector,
|
||||
false /*isUnderFactoryTest*/,
|
||||
@@ -488,7 +488,7 @@ public class ScanTests {
|
||||
|
||||
// Need to call hideAsFinal to cache derived fields. This is normally done in PMS, but not
|
||||
// in this cut down flow used for the test.
|
||||
((ParsedPackage) result.pkgSetting.pkg).hideAsFinal();
|
||||
((ParsedPackage) result.mPkgSetting.pkg).hideAsFinal();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -529,10 +529,10 @@ public class ScanTests {
|
||||
}
|
||||
|
||||
private static void assertBasicPackageScanResult(
|
||||
PackageManagerService.ScanResult scanResult, String packageName, boolean isInstant) {
|
||||
assertThat(scanResult.success, is(true));
|
||||
ScanResult scanResult, String packageName, boolean isInstant) {
|
||||
assertThat(scanResult.mSuccess, is(true));
|
||||
|
||||
final PackageSetting pkgSetting = scanResult.pkgSetting;
|
||||
final PackageSetting pkgSetting = scanResult.mPkgSetting;
|
||||
assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting);
|
||||
|
||||
final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
|
||||
@@ -540,35 +540,35 @@ public class ScanTests {
|
||||
assertBasicApplicationInfo(scanResult, applicationInfo);
|
||||
}
|
||||
|
||||
private static void assertBasicPackageSetting(PackageManagerService.ScanResult scanResult,
|
||||
private static void assertBasicPackageSetting(ScanResult scanResult,
|
||||
String packageName, boolean isInstant, PackageSetting pkgSetting) {
|
||||
assertThat(pkgSetting.pkg.getPackageName(), is(packageName));
|
||||
assertThat(pkgSetting.getInstantApp(0), is(isInstant));
|
||||
assertThat(pkgSetting.usesStaticLibraries,
|
||||
arrayContaining("some.static.library", "some.other.static.library"));
|
||||
assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L}));
|
||||
assertThat(pkgSetting.pkg, is(scanResult.request.parsedPackage));
|
||||
assertThat(pkgSetting.pkg, is(scanResult.mRequest.mParsedPackage));
|
||||
assertThat(pkgSetting.getPath(), is(new File(createCodePath(packageName))));
|
||||
assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345)));
|
||||
}
|
||||
|
||||
private static void assertBasicApplicationInfo(PackageManagerService.ScanResult scanResult,
|
||||
private static void assertBasicApplicationInfo(ScanResult scanResult,
|
||||
ApplicationInfo applicationInfo) {
|
||||
assertThat(applicationInfo.processName,
|
||||
is(scanResult.request.parsedPackage.getPackageName()));
|
||||
is(scanResult.mRequest.mParsedPackage.getPackageName()));
|
||||
|
||||
final int uid = applicationInfo.uid;
|
||||
assertThat(UserHandle.getUserId(uid), is(UserHandle.USER_SYSTEM));
|
||||
|
||||
final String calculatedCredentialId = Environment.getDataUserCePackageDirectory(
|
||||
applicationInfo.volumeUuid, UserHandle.USER_SYSTEM,
|
||||
scanResult.request.parsedPackage.getPackageName()).getAbsolutePath();
|
||||
scanResult.mRequest.mParsedPackage.getPackageName()).getAbsolutePath();
|
||||
assertThat(applicationInfo.credentialProtectedDataDir, is(calculatedCredentialId));
|
||||
assertThat(applicationInfo.dataDir, is(applicationInfo.credentialProtectedDataDir));
|
||||
}
|
||||
|
||||
private static void assertAbiAndPathssDerived(PackageManagerService.ScanResult scanResult) {
|
||||
PackageSetting pkgSetting = scanResult.pkgSetting;
|
||||
private static void assertAbiAndPathssDerived(ScanResult scanResult) {
|
||||
PackageSetting pkgSetting = scanResult.mPkgSetting;
|
||||
final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
|
||||
pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0, pkgSetting);
|
||||
assertThat(applicationInfo.primaryCpuAbi, is("derivedPrimary"));
|
||||
@@ -581,8 +581,8 @@ public class ScanTests {
|
||||
assertThat(applicationInfo.secondaryNativeLibraryDir, is("derivedNativeDir2"));
|
||||
}
|
||||
|
||||
private static void assertPathsNotDerived(PackageManagerService.ScanResult scanResult) {
|
||||
PackageSetting pkgSetting = scanResult.pkgSetting;
|
||||
private static void assertPathsNotDerived(ScanResult scanResult) {
|
||||
PackageSetting pkgSetting = scanResult.mPkgSetting;
|
||||
final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
|
||||
pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0, pkgSetting);
|
||||
assertThat(applicationInfo.nativeLibraryRootDir, is("getRootDir"));
|
||||
|
||||
Reference in New Issue
Block a user