[pm] extract InstallParams from PackageManagerService class

Extract InstallParams and related logic from PackageManagerService. This
is not a structural refactor, but just re-organizing code into separate files.

This aligns with the goal to separate installation logic out from
PackageManagerService.

Due to shared code paths between addForInit and regular installation,
there are still methods that are in PackageManagerService that are
called by InstallParams. The next step is to address those methods.

Once we can clearly see which codes require PackageManagerService locks,
we can encapsulate those into new PackageManagerInternal interfaces.

+ also removed some unused code

BYPASS_INCLUSIVE_LANGUAGE_REASON=need to change some public APIs first

BUG: 194319951
Test: builds and presubmit
Change-Id: Ibf5a914f463b784857a3ca6774b2a7709c93ebd4
This commit is contained in:
Songchun Fan
2021-07-26 13:38:47 -07:00
parent 044380ac11
commit 296502a3c3
32 changed files with 5214 additions and 4622 deletions

View 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;
}
}

View File

@@ -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;
}
}

View 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;
}
}

View 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();
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View 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;
}
}

File diff suppressed because it is too large Load Diff

View 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;
}
}

View 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;
}
}

View 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();
}
}

View 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;
}
}
}

View 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);
}
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View 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);
}
}
}
}

View 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);
}

View File

@@ -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

View 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;
}
}

View 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;
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View 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;
}
}

View 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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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.");
}
}
}
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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"));