Use modern install method in backup service
Test: adb backup -apk myApp -f backup ; adb restore backup Change-Id: I2bbcb0487ecc525a6dc8a2693b15ce624db275b0
This commit is contained in:
@@ -64,7 +64,6 @@ import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.LayerDrawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -1682,22 +1681,6 @@ public class ApplicationPackageManager extends PackageManager {
|
||||
return info.loadLabel(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installPackage(Uri packageURI,
|
||||
PackageInstallObserver observer, int flags, String installerPackageName) {
|
||||
if (!"file".equals(packageURI.getScheme())) {
|
||||
throw new UnsupportedOperationException("Only file:// URIs are supported");
|
||||
}
|
||||
|
||||
final String originPath = packageURI.getPath();
|
||||
try {
|
||||
mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
|
||||
mContext.getUserId());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int installExistingPackage(String packageName) throws NameNotFoundException {
|
||||
return installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN);
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.content.pm.ChangedPackages;
|
||||
import android.content.pm.InstantAppInfo;
|
||||
import android.content.pm.FeatureInfo;
|
||||
import android.content.pm.IDexModuleRegisterCallback;
|
||||
import android.content.pm.IPackageInstallObserver2;
|
||||
import android.content.pm.IPackageInstaller;
|
||||
import android.content.pm.IPackageDeleteObserver;
|
||||
import android.content.pm.IPackageDeleteObserver2;
|
||||
@@ -222,13 +221,6 @@ interface IPackageManager {
|
||||
ParceledListSlice queryInstrumentation(
|
||||
String targetPackage, int flags);
|
||||
|
||||
/** @deprecated Use PackageInstaller instead */
|
||||
void installPackageAsUser(in String originPath,
|
||||
in IPackageInstallObserver2 observer,
|
||||
int flags,
|
||||
in String installerPackageName,
|
||||
int userId);
|
||||
|
||||
void finishPackageInstall(int token, boolean didLaunch);
|
||||
|
||||
void setInstallerPackageName(in String targetPackage, in String installerPackageName);
|
||||
|
||||
@@ -324,7 +324,14 @@ public class PackageInstaller {
|
||||
*/
|
||||
public int createSession(@NonNull SessionParams params) throws IOException {
|
||||
try {
|
||||
return mInstaller.createSession(params, mInstallerPackageName, mUserId);
|
||||
final String installerPackage;
|
||||
if (params.installerPackageName == null) {
|
||||
installerPackage = mInstallerPackageName;
|
||||
} else {
|
||||
installerPackage = params.installerPackageName;
|
||||
}
|
||||
|
||||
return mInstaller.createSession(params, installerPackage, mUserId);
|
||||
} catch (RuntimeException e) {
|
||||
ExceptionUtils.maybeUnwrapIOException(e);
|
||||
throw e;
|
||||
@@ -1081,6 +1088,8 @@ public class PackageInstaller {
|
||||
public String volumeUuid;
|
||||
/** {@hide} */
|
||||
public String[] grantedRuntimePermissions;
|
||||
/** {@hide} */
|
||||
public String installerPackageName;
|
||||
|
||||
/**
|
||||
* Construct parameters for a new package install session.
|
||||
@@ -1109,6 +1118,7 @@ public class PackageInstaller {
|
||||
abiOverride = source.readString();
|
||||
volumeUuid = source.readString();
|
||||
grantedRuntimePermissions = source.readStringArray();
|
||||
installerPackageName = source.readString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1304,6 +1314,18 @@ public class PackageInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the installer package for the app.
|
||||
*
|
||||
* By default this is the app that created the {@link PackageInstaller} object.
|
||||
*
|
||||
* @param installerPackageName name of the installer package
|
||||
* {@hide}
|
||||
*/
|
||||
public void setInstallerPackageName(String installerPackageName) {
|
||||
this.installerPackageName = installerPackageName;
|
||||
}
|
||||
|
||||
/** {@hide} */
|
||||
public void dump(IndentingPrintWriter pw) {
|
||||
pw.printPair("mode", mode);
|
||||
@@ -1319,6 +1341,7 @@ public class PackageInstaller {
|
||||
pw.printPair("abiOverride", abiOverride);
|
||||
pw.printPair("volumeUuid", volumeUuid);
|
||||
pw.printPair("grantedRuntimePermissions", grantedRuntimePermissions);
|
||||
pw.printPair("installerPackageName", installerPackageName);
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@@ -1343,6 +1366,7 @@ public class PackageInstaller {
|
||||
dest.writeString(abiOverride);
|
||||
dest.writeString(volumeUuid);
|
||||
dest.writeStringArray(grantedRuntimePermissions);
|
||||
dest.writeString(installerPackageName);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<SessionParams>
|
||||
|
||||
@@ -47,7 +47,6 @@ import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -4717,17 +4716,6 @@ public abstract class PackageManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated replaced by {@link PackageInstaller}
|
||||
* @hide
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void installPackage(
|
||||
Uri packageURI,
|
||||
PackageInstallObserver observer,
|
||||
@InstallFlags int flags,
|
||||
String installerPackageName);
|
||||
|
||||
/**
|
||||
* If there is already an application with the given package name installed
|
||||
* on the system for other users, also install it for the calling user.
|
||||
|
||||
@@ -66,7 +66,6 @@ public class FullRestoreEngine extends RestoreEngine {
|
||||
// Task in charge of monitoring timeouts
|
||||
private final BackupRestoreTask mMonitorTask;
|
||||
|
||||
private final RestoreInstallObserver mInstallObserver = new RestoreInstallObserver();
|
||||
private final RestoreDeleteObserver mDeleteObserver = new RestoreDeleteObserver();
|
||||
|
||||
// Dedicated observer, if any
|
||||
@@ -249,13 +248,12 @@ public class FullRestoreEngine extends RestoreEngine {
|
||||
Slog.d(TAG, "APK file; installing");
|
||||
}
|
||||
// Try to install the app.
|
||||
String installerName = mPackageInstallers.get(pkg);
|
||||
String installerPackageName = mPackageInstallers.get(pkg);
|
||||
boolean isSuccessfullyInstalled = RestoreUtils.installApk(
|
||||
instream, mBackupManagerService.getPackageManager(),
|
||||
mInstallObserver, mDeleteObserver, mManifestSignatures,
|
||||
mPackagePolicies, info, installerName,
|
||||
bytesReadListener, mBackupManagerService.getDataDir()
|
||||
);
|
||||
instream, mBackupManagerService.getContext(),
|
||||
mDeleteObserver, mManifestSignatures,
|
||||
mPackagePolicies, info, installerPackageName,
|
||||
bytesReadListener);
|
||||
// good to go; promote to ACCEPT
|
||||
mPackagePolicies.put(pkg, isSuccessfullyInstalled
|
||||
? RestorePolicy.ACCEPT
|
||||
|
||||
@@ -88,7 +88,6 @@ public class PerformAdbRestoreTask implements Runnable {
|
||||
private final String mDecryptPassword;
|
||||
private final AtomicBoolean mLatchObject;
|
||||
private final PackageManagerBackupAgent mPackageManagerBackupAgent;
|
||||
private final RestoreInstallObserver mInstallObserver = new RestoreInstallObserver();
|
||||
private final RestoreDeleteObserver mDeleteObserver = new RestoreDeleteObserver();
|
||||
|
||||
private IFullBackupRestoreObserver mObserver;
|
||||
@@ -513,13 +512,11 @@ public class PerformAdbRestoreTask implements Runnable {
|
||||
Slog.d(TAG, "APK file; installing");
|
||||
}
|
||||
// Try to install the app.
|
||||
String installerName = mPackageInstallers.get(pkg);
|
||||
boolean isSuccessfullyInstalled = RestoreUtils.installApk(
|
||||
instream, mBackupManagerService.getPackageManager(),
|
||||
mInstallObserver, mDeleteObserver, mManifestSignatures,
|
||||
mPackagePolicies, info, installerName,
|
||||
bytesReadListener, mBackupManagerService.getDataDir()
|
||||
);
|
||||
String installerPackageName = mPackageInstallers.get(pkg);
|
||||
boolean isSuccessfullyInstalled = RestoreUtils.installApk(instream,
|
||||
mBackupManagerService.getContext(),
|
||||
mDeleteObserver, mManifestSignatures, mPackagePolicies,
|
||||
info, installerPackageName, bytesReadListener);
|
||||
// good to go; promote to ACCEPT
|
||||
mPackagePolicies.put(pkg, isSuccessfullyInstalled
|
||||
? RestorePolicy.ACCEPT
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.backup.restore;
|
||||
|
||||
import android.app.PackageInstallObserver;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Synchronous implementation of PackageInstallObserver.
|
||||
*
|
||||
* Allows the caller to synchronously wait for package install event.
|
||||
*/
|
||||
public class RestoreInstallObserver extends PackageInstallObserver {
|
||||
|
||||
@GuardedBy("mDone")
|
||||
private final AtomicBoolean mDone = new AtomicBoolean();
|
||||
|
||||
private String mPackageName;
|
||||
private int mResult;
|
||||
|
||||
public RestoreInstallObserver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the observer to prepare for another installation.
|
||||
*/
|
||||
public void reset() {
|
||||
synchronized (mDone) {
|
||||
mDone.set(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously waits for completion.
|
||||
*/
|
||||
public void waitForCompletion() {
|
||||
synchronized (mDone) {
|
||||
while (mDone.get() == false) {
|
||||
try {
|
||||
mDone.wait();
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns result code.
|
||||
*/
|
||||
public int getResult() {
|
||||
return mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns installed package name.
|
||||
*/
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPackageInstalled(String packageName, int returnCode,
|
||||
String msg, Bundle extras) {
|
||||
synchronized (mDone) {
|
||||
mResult = returnCode;
|
||||
mPackageName = packageName;
|
||||
mDone.set(true);
|
||||
mDone.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,23 +19,31 @@ package com.android.server.backup.utils;
|
||||
import static com.android.server.backup.RefactoredBackupManagerService.DEBUG;
|
||||
import static com.android.server.backup.RefactoredBackupManagerService.TAG;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.IIntentReceiver;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageInstaller.Session;
|
||||
import android.content.pm.PackageInstaller.SessionParams;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.Signature;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.server.backup.FileMetadata;
|
||||
import com.android.server.backup.restore.RestoreDeleteObserver;
|
||||
import com.android.server.backup.restore.RestoreInstallObserver;
|
||||
import com.android.server.backup.restore.RestorePolicy;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
@@ -47,62 +55,66 @@ public class RestoreUtils {
|
||||
* Reads apk contents from input stream and installs the apk.
|
||||
*
|
||||
* @param instream - input stream to read apk data from.
|
||||
* @param packageManager - {@link PackageManager} instance.
|
||||
* @param installObserver - {@link RestoreInstallObserver} instance.
|
||||
* @param context - installing context
|
||||
* @param deleteObserver - {@link RestoreDeleteObserver} instance.
|
||||
* @param manifestSignatures - manifest signatures.
|
||||
* @param packagePolicies - package policies.
|
||||
* @param info - backup file info.
|
||||
* @param installerPackage - installer package.
|
||||
* @param installerPackageName - package name of installer.
|
||||
* @param bytesReadListener - listener to be called for counting bytes read.
|
||||
* @param dataDir - directory where to create apk file.
|
||||
* @return true if apk was successfully read and installed and false otherwise.
|
||||
*/
|
||||
// TODO: Refactor to get rid of unneeded params.
|
||||
public static boolean installApk(InputStream instream, PackageManager packageManager,
|
||||
RestoreInstallObserver installObserver, RestoreDeleteObserver deleteObserver,
|
||||
public static boolean installApk(InputStream instream, Context context,
|
||||
RestoreDeleteObserver deleteObserver,
|
||||
HashMap<String, Signature[]> manifestSignatures,
|
||||
HashMap<String, RestorePolicy> packagePolicies,
|
||||
FileMetadata info,
|
||||
String installerPackage, BytesReadListener bytesReadListener,
|
||||
File dataDir) {
|
||||
String installerPackageName, BytesReadListener bytesReadListener) {
|
||||
boolean okay = true;
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Installing from backup: " + info.packageName);
|
||||
}
|
||||
|
||||
// The file content is an .apk file. Copy it out to a staging location and
|
||||
// attempt to install it.
|
||||
File apkFile = new File(dataDir, info.packageName);
|
||||
try {
|
||||
FileOutputStream apkStream = new FileOutputStream(apkFile);
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
long size = info.size;
|
||||
while (size > 0) {
|
||||
long toRead = (buffer.length < size) ? buffer.length : size;
|
||||
int didRead = instream.read(buffer, 0, (int) toRead);
|
||||
if (didRead >= 0) {
|
||||
bytesReadListener.onBytesRead(didRead);
|
||||
LocalIntentReceiver receiver = new LocalIntentReceiver();
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
PackageInstaller installer = packageManager.getPackageInstaller();
|
||||
|
||||
SessionParams params = new SessionParams(SessionParams.MODE_FULL_INSTALL);
|
||||
params.setInstallerPackageName(installerPackageName);
|
||||
int sessionId = installer.createSession(params);
|
||||
try {
|
||||
try (Session session = installer.openSession(sessionId)) {
|
||||
try (OutputStream apkStream = session.openWrite(info.packageName, 0,
|
||||
info.size)) {
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
long size = info.size;
|
||||
while (size > 0) {
|
||||
long toRead = (buffer.length < size) ? buffer.length : size;
|
||||
int didRead = instream.read(buffer, 0, (int) toRead);
|
||||
if (didRead >= 0) {
|
||||
bytesReadListener.onBytesRead(didRead);
|
||||
}
|
||||
apkStream.write(buffer, 0, didRead);
|
||||
size -= didRead;
|
||||
}
|
||||
}
|
||||
|
||||
session.commit(receiver.getIntentSender());
|
||||
}
|
||||
apkStream.write(buffer, 0, didRead);
|
||||
size -= didRead;
|
||||
} catch (Exception t) {
|
||||
installer.abandonSession(sessionId);
|
||||
|
||||
throw t;
|
||||
}
|
||||
apkStream.close();
|
||||
|
||||
// make sure the installer can read it
|
||||
apkFile.setReadable(true, false);
|
||||
Intent result = receiver.getResult();
|
||||
int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
|
||||
PackageInstaller.STATUS_FAILURE);
|
||||
|
||||
// Now install it
|
||||
Uri packageUri = Uri.fromFile(apkFile);
|
||||
installObserver.reset();
|
||||
// TODO: PackageManager.installPackage() is deprecated, refactor.
|
||||
packageManager.installPackage(packageUri, installObserver,
|
||||
PackageManager.INSTALL_REPLACE_EXISTING | PackageManager.INSTALL_FROM_ADB,
|
||||
installerPackage);
|
||||
installObserver.waitForCompletion();
|
||||
|
||||
if (installObserver.getResult() != PackageManager.INSTALL_SUCCEEDED) {
|
||||
if (status != PackageInstaller.STATUS_SUCCESS) {
|
||||
// The only time we continue to accept install of data even if the
|
||||
// apk install failed is if we had already determined that we could
|
||||
// accept the data regardless.
|
||||
@@ -112,10 +124,12 @@ public class RestoreUtils {
|
||||
} else {
|
||||
// Okay, the install succeeded. Make sure it was the right app.
|
||||
boolean uninstall = false;
|
||||
if (!installObserver.getPackageName().equals(info.packageName)) {
|
||||
final String installedPackageName = result.getStringExtra(
|
||||
PackageInstaller.EXTRA_PACKAGE_NAME);
|
||||
if (!installedPackageName.equals(info.packageName)) {
|
||||
Slog.w(TAG, "Restore stream claimed to include apk for "
|
||||
+ info.packageName + " but apk was really "
|
||||
+ installObserver.getPackageName());
|
||||
+ installedPackageName);
|
||||
// delete the package we just put in place; it might be fraudulent
|
||||
okay = false;
|
||||
uninstall = true;
|
||||
@@ -161,7 +175,7 @@ public class RestoreUtils {
|
||||
if (uninstall) {
|
||||
deleteObserver.reset();
|
||||
packageManager.deletePackage(
|
||||
installObserver.getPackageName(),
|
||||
installedPackageName,
|
||||
deleteObserver, 0);
|
||||
deleteObserver.waitForCompletion();
|
||||
}
|
||||
@@ -169,10 +183,44 @@ public class RestoreUtils {
|
||||
} catch (IOException e) {
|
||||
Slog.e(TAG, "Unable to transcribe restored apk for install");
|
||||
okay = false;
|
||||
} finally {
|
||||
apkFile.delete();
|
||||
}
|
||||
|
||||
return okay;
|
||||
}
|
||||
|
||||
private static class LocalIntentReceiver {
|
||||
private final Object mLock = new Object();
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private Intent mResult = null;
|
||||
|
||||
private IIntentSender.Stub mLocalSender = new IIntentSender.Stub() {
|
||||
@Override
|
||||
public void send(int code, Intent intent, String resolvedType, IBinder whitelistToken,
|
||||
IIntentReceiver finishedReceiver, String requiredPermission, Bundle options) {
|
||||
synchronized (mLock) {
|
||||
mResult = intent;
|
||||
mLock.notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public IntentSender getIntentSender() {
|
||||
return new IntentSender((IIntentSender) mLocalSender);
|
||||
}
|
||||
|
||||
public Intent getResult() {
|
||||
synchronized (mLock) {
|
||||
while (mResult == null) {
|
||||
try {
|
||||
mLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
return mResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +415,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
|
||||
params.installFlags |= PackageManager.INSTALL_FROM_ADB;
|
||||
|
||||
} else {
|
||||
mAppOps.checkPackage(callingUid, installerPackageName);
|
||||
// Only apps with INSTALL_PACKAGES are allowed to set an installer that is not the
|
||||
// caller.
|
||||
if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
mAppOps.checkPackage(callingUid, installerPackageName);
|
||||
}
|
||||
|
||||
params.installFlags &= ~PackageManager.INSTALL_FROM_ADB;
|
||||
params.installFlags &= ~PackageManager.INSTALL_ALL_USERS;
|
||||
|
||||
@@ -346,13 +346,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
|| (isSelfUpdatePermissionGranted
|
||||
&& mPm.getPackageUid(mPackageName, 0, userId) == mInstallerUid);
|
||||
final boolean isInstallerRoot = (mInstallerUid == Process.ROOT_UID);
|
||||
final boolean isInstallerSystem = (mInstallerUid == Process.SYSTEM_UID);
|
||||
final boolean forcePermissionPrompt =
|
||||
(params.installFlags & PackageManager.INSTALL_FORCE_PERMISSION_PROMPT) != 0;
|
||||
|
||||
// Device owners and affiliated profile owners are allowed to silently install packages, so
|
||||
// the permission check is waived if the installer is the device owner.
|
||||
return forcePermissionPrompt || !(isPermissionGranted || isInstallerRoot
|
||||
|| isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked());
|
||||
|| isInstallerSystem || isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked());
|
||||
}
|
||||
|
||||
public PackageInstallerSession(PackageInstallerService.InternalCallback callback,
|
||||
|
||||
@@ -13141,80 +13141,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
|
||||
int installFlags, String installerPackageName, int userId) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
|
||||
true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser");
|
||||
|
||||
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
|
||||
try {
|
||||
if (observer != null) {
|
||||
observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
|
||||
installFlags |= PackageManager.INSTALL_FROM_ADB;
|
||||
|
||||
} else {
|
||||
// Caller holds INSTALL_PACKAGES permission, so we're less strict
|
||||
// about installerPackageName.
|
||||
|
||||
installFlags &= ~PackageManager.INSTALL_FROM_ADB;
|
||||
installFlags &= ~PackageManager.INSTALL_ALL_USERS;
|
||||
}
|
||||
|
||||
UserHandle user;
|
||||
if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
|
||||
user = UserHandle.ALL;
|
||||
} else {
|
||||
user = new UserHandle(userId);
|
||||
}
|
||||
|
||||
// Only system components can circumvent runtime permissions when installing.
|
||||
if ((installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
|
||||
&& mContext.checkCallingOrSelfPermission(Manifest.permission
|
||||
.INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
|
||||
throw new SecurityException("You need the "
|
||||
+ "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
|
||||
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
|
||||
}
|
||||
|
||||
if ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
|
||||
|| (installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"New installs into ASEC containers no longer supported");
|
||||
}
|
||||
|
||||
final File originFile = new File(originPath);
|
||||
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
|
||||
|
||||
final Message msg = mHandler.obtainMessage(INIT_COPY);
|
||||
final VerificationInfo verificationInfo = new VerificationInfo(
|
||||
null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
|
||||
final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
|
||||
installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
|
||||
null /*packageAbiOverride*/, null /*grantedPermissions*/,
|
||||
null /*certificates*/, PackageManager.INSTALL_REASON_UNKNOWN);
|
||||
params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
|
||||
msg.obj = params;
|
||||
|
||||
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installAsUser",
|
||||
System.identityHashCode(msg.obj));
|
||||
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
|
||||
System.identityHashCode(msg.obj));
|
||||
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ensure that the install reason matches what we know about the package installer (e.g. whether
|
||||
* it is acting on behalf on an enterprise or the user).
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.android.server.backup.testutils;
|
||||
|
||||
import android.app.PackageInstallObserver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@@ -32,7 +31,6 @@ import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.os.storage.VolumeInfo;
|
||||
@@ -621,12 +619,6 @@ public class PackageManagerStub extends PackageManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installPackage(Uri packageURI, PackageInstallObserver observer, int flags,
|
||||
String installerPackageName) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int installExistingPackage(String packageName)
|
||||
throws NameNotFoundException {
|
||||
|
||||
@@ -1086,15 +1086,6 @@ public class MockPackageManager extends PackageManager {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
public void installPackage(Uri packageURI, PackageInstallObserver observer,
|
||||
int flags, String installerPackageName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
|
||||
@@ -71,18 +71,6 @@ public class PmPermissionsTests extends AndroidTestCase {
|
||||
private class TestInstallObserver extends PackageInstallObserver {
|
||||
}
|
||||
|
||||
@SmallTest
|
||||
public void testInstallPackage() {
|
||||
TestInstallObserver observer = new TestInstallObserver();
|
||||
try {
|
||||
mPm.installPackage(null, observer, 0, null);
|
||||
fail("PackageManager.installPackage" +
|
||||
"did not throw SecurityException as expected");
|
||||
} catch (SecurityException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This test verifies that PackageManger.freeStorage
|
||||
* enforces permission android.permission.CLEAR_APP_CACHE
|
||||
|
||||
Reference in New Issue
Block a user