Merge changes Iad51cd85,I6414d28c
* changes: Minor refactorings and cleanups. Simplifying callback calls in PackageInstallerSession.
This commit is contained in:
@@ -26,7 +26,6 @@ import android.app.AppOpsManager;
|
|||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PackageDeleteObserver;
|
import android.app.PackageDeleteObserver;
|
||||||
import android.app.PackageInstallObserver;
|
|
||||||
import android.app.admin.DevicePolicyEventLogger;
|
import android.app.admin.DevicePolicyEventLogger;
|
||||||
import android.app.admin.DevicePolicyManagerInternal;
|
import android.app.admin.DevicePolicyManagerInternal;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -994,74 +993,57 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class PackageInstallObserverAdapter extends PackageInstallObserver {
|
static void sendOnUserActionRequired(Context context, IntentSender target, int sessionId,
|
||||||
private final Context mContext;
|
Intent intent) {
|
||||||
private final IntentSender mTarget;
|
final Intent fillIn = new Intent();
|
||||||
private final int mSessionId;
|
fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
|
||||||
private final boolean mShowNotification;
|
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
|
||||||
private final int mUserId;
|
PackageInstaller.STATUS_PENDING_USER_ACTION);
|
||||||
|
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
|
||||||
public PackageInstallObserverAdapter(Context context, IntentSender target, int sessionId,
|
try {
|
||||||
boolean showNotification, int userId) {
|
target.sendIntent(context, 0, fillIn, null, null);
|
||||||
mContext = context;
|
} catch (SendIntentException ignored) {
|
||||||
mTarget = target;
|
|
||||||
mSessionId = sessionId;
|
|
||||||
mShowNotification = showNotification;
|
|
||||||
mUserId = userId;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
static void sendOnPackageInstalled(Context context, IntentSender target, int sessionId,
|
||||||
public void onUserActionRequired(Intent intent) {
|
boolean showNotification, int userId, String basePackageName, int returnCode,
|
||||||
final Intent fillIn = new Intent();
|
String msg, Bundle extras) {
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
|
if (PackageManager.INSTALL_SUCCEEDED == returnCode && showNotification) {
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
|
boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
|
||||||
PackageInstaller.STATUS_PENDING_USER_ACTION);
|
Notification notification = buildSuccessNotification(context,
|
||||||
fillIn.putExtra(Intent.EXTRA_INTENT, intent);
|
context.getResources()
|
||||||
try {
|
.getString(update ? R.string.package_updated_device_owner :
|
||||||
mTarget.sendIntent(mContext, 0, fillIn, null, null);
|
R.string.package_installed_device_owner),
|
||||||
} catch (SendIntentException ignored) {
|
basePackageName,
|
||||||
|
userId);
|
||||||
|
if (notification != null) {
|
||||||
|
NotificationManager notificationManager = (NotificationManager)
|
||||||
|
context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.notify(basePackageName,
|
||||||
|
SystemMessage.NOTE_PACKAGE_STATE,
|
||||||
|
notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
final Intent fillIn = new Intent();
|
||||||
@Override
|
fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
|
||||||
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
|
fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
|
||||||
Bundle extras) {
|
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
|
||||||
if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) {
|
PackageManager.installStatusToPublicStatus(returnCode));
|
||||||
boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING);
|
fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
|
||||||
Notification notification = buildSuccessNotification(mContext,
|
PackageManager.installStatusToString(returnCode, msg));
|
||||||
mContext.getResources()
|
fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
|
||||||
.getString(update ? R.string.package_updated_device_owner :
|
if (extras != null) {
|
||||||
R.string.package_installed_device_owner),
|
final String existing = extras.getString(
|
||||||
basePackageName,
|
PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
|
||||||
mUserId);
|
if (!TextUtils.isEmpty(existing)) {
|
||||||
if (notification != null) {
|
fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
|
||||||
NotificationManager notificationManager = (NotificationManager)
|
|
||||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
notificationManager.notify(basePackageName,
|
|
||||||
SystemMessage.NOTE_PACKAGE_STATE,
|
|
||||||
notification);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final Intent fillIn = new Intent();
|
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName);
|
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
|
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
|
|
||||||
PackageManager.installStatusToPublicStatus(returnCode));
|
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE,
|
|
||||||
PackageManager.installStatusToString(returnCode, msg));
|
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_LEGACY_STATUS, returnCode);
|
|
||||||
if (extras != null) {
|
|
||||||
final String existing = extras.getString(
|
|
||||||
PackageManager.EXTRA_FAILURE_EXISTING_PACKAGE);
|
|
||||||
if (!TextUtils.isEmpty(existing)) {
|
|
||||||
fillIn.putExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME, existing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
mTarget.sendIntent(mContext, 0, fillIn, null, null);
|
|
||||||
} catch (SendIntentException ignored) {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
target.sendIntent(context, 0, fillIn, null, null);
|
||||||
|
} catch (SendIntentException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package com.android.server.pm;
|
|||||||
|
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
|
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
|
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
|
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||||
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
|
import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
|
||||||
@@ -79,7 +78,6 @@ import android.os.Message;
|
|||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.ParcelableException;
|
import android.os.ParcelableException;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
|
||||||
import android.os.RevocableFileDescriptor;
|
import android.os.RevocableFileDescriptor;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
@@ -107,7 +105,6 @@ import com.android.internal.util.IndentingPrintWriter;
|
|||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
import com.android.server.pm.Installer.InstallerException;
|
import com.android.server.pm.Installer.InstallerException;
|
||||||
import com.android.server.pm.PackageInstallerService.PackageInstallObserverAdapter;
|
|
||||||
import com.android.server.pm.dex.DexManager;
|
import com.android.server.pm.dex.DexManager;
|
||||||
import com.android.server.security.VerityUtils;
|
import com.android.server.security.VerityUtils;
|
||||||
|
|
||||||
@@ -131,7 +128,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||||
private static final String TAG = "PackageInstallerSession";
|
private static final String TAG = "PackageInstallerSession";
|
||||||
private static final boolean LOGD = true;
|
private static final boolean LOGD = true;
|
||||||
private static final String REMOVE_SPLIT_MARKER_EXTENSION = ".removed";
|
private static final String REMOVE_MARKER_EXTENSION = ".removed";
|
||||||
|
|
||||||
private static final int MSG_COMMIT = 1;
|
private static final int MSG_COMMIT = 1;
|
||||||
private static final int MSG_ON_PACKAGE_INSTALLED = 2;
|
private static final int MSG_ON_PACKAGE_INSTALLED = 2;
|
||||||
@@ -257,7 +254,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
private final ArrayList<FileBridge> mBridges = new ArrayList<>();
|
private final ArrayList<FileBridge> mBridges = new ArrayList<>();
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private IPackageInstallObserver2 mRemoteObserver;
|
private IntentSender mRemoteStatusReceiver;
|
||||||
|
|
||||||
/** Fields derived from commit parsing */
|
/** Fields derived from commit parsing */
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@@ -293,9 +290,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private File mResolvedBaseFile;
|
private File mResolvedBaseFile;
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
private File mResolvedStageDir;
|
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private final List<File> mResolvedStagedFiles = new ArrayList<>();
|
private final List<File> mResolvedStagedFiles = new ArrayList<>();
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
@@ -315,7 +309,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
// Installers can't stage directories, so it's fine to ignore
|
// Installers can't stage directories, so it's fine to ignore
|
||||||
// entries like "lost+found".
|
// entries like "lost+found".
|
||||||
if (file.isDirectory()) return false;
|
if (file.isDirectory()) return false;
|
||||||
if (file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
|
if (file.getName().endsWith(REMOVE_MARKER_EXTENSION)) return false;
|
||||||
if (DexMetadataHelper.isDexMetadataFile(file)) return false;
|
if (DexMetadataHelper.isDexMetadataFile(file)) return false;
|
||||||
if (VerityUtils.isFsveritySignatureFile(file)) return false;
|
if (VerityUtils.isFsveritySignatureFile(file)) return false;
|
||||||
return true;
|
return true;
|
||||||
@@ -325,7 +319,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
@Override
|
@Override
|
||||||
public boolean accept(File file) {
|
public boolean accept(File file) {
|
||||||
if (file.isDirectory()) return false;
|
if (file.isDirectory()) return false;
|
||||||
if (!file.getName().endsWith(REMOVE_SPLIT_MARKER_EXTENSION)) return false;
|
if (!file.getName().endsWith(REMOVE_MARKER_EXTENSION)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -342,14 +336,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
final String packageName = (String) args.arg1;
|
final String packageName = (String) args.arg1;
|
||||||
final String message = (String) args.arg2;
|
final String message = (String) args.arg2;
|
||||||
final Bundle extras = (Bundle) args.arg3;
|
final Bundle extras = (Bundle) args.arg3;
|
||||||
final IPackageInstallObserver2 observer = (IPackageInstallObserver2) args.arg4;
|
final IntentSender statusReceiver = (IntentSender) args.arg4;
|
||||||
final int returnCode = args.argi1;
|
final int returnCode = args.argi1;
|
||||||
args.recycle();
|
args.recycle();
|
||||||
|
|
||||||
try {
|
PackageInstallerService.sendOnPackageInstalled(mContext,
|
||||||
observer.onPackageInstalled(packageName, returnCode, message, extras);
|
statusReceiver, sessionId,
|
||||||
} catch (RemoteException ignored) {
|
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId,
|
||||||
}
|
packageName, returnCode, message, extras);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -559,23 +553,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve the actual location where staged data should be written. This
|
|
||||||
* might point at an ASEC mount point, which is why we delay path resolution
|
|
||||||
* until someone actively works with the session.
|
|
||||||
*/
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
private File resolveStageDirLocked() throws IOException {
|
|
||||||
if (mResolvedStageDir == null) {
|
|
||||||
if (stageDir != null) {
|
|
||||||
mResolvedStageDir = stageDir;
|
|
||||||
} else {
|
|
||||||
throw new IOException("Missing stageDir");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mResolvedStageDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setClientProgress(float progress) {
|
public void setClientProgress(float progress) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
@@ -615,14 +592,32 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
assertCallerIsOwnerOrRootLocked();
|
assertCallerIsOwnerOrRootLocked();
|
||||||
assertPreparedAndNotCommittedOrDestroyedLocked("getNames");
|
assertPreparedAndNotCommittedOrDestroyedLocked("getNames");
|
||||||
|
|
||||||
try {
|
return getNamesLocked();
|
||||||
return resolveStageDirLocked().list();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw ExceptionUtils.wrap(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private String[] getNamesLocked() {
|
||||||
|
return stageDir.list();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File[] filterFiles(File parent, String[] names, FileFilter filter) {
|
||||||
|
return Arrays.stream(names).map(name -> new File(parent, name)).filter(
|
||||||
|
file -> filter.accept(file)).toArray(File[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private File[] getAddedFilesLocked() {
|
||||||
|
String[] names = getNamesLocked();
|
||||||
|
return filterFiles(stageDir, names, sAddedFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private File[] getRemovedFilesLocked() {
|
||||||
|
String[] names = getNamesLocked();
|
||||||
|
return filterFiles(stageDir, names, sRemovedFilter);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeSplit(String splitName) {
|
public void removeSplit(String splitName) {
|
||||||
if (TextUtils.isEmpty(params.appPackageName)) {
|
if (TextUtils.isEmpty(params.appPackageName)) {
|
||||||
@@ -641,13 +636,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getRemoveMarkerName(String name) {
|
||||||
|
final String markerName = name + REMOVE_MARKER_EXTENSION;
|
||||||
|
if (!FileUtils.isValidExtFilename(markerName)) {
|
||||||
|
throw new IllegalArgumentException("Invalid marker: " + markerName);
|
||||||
|
}
|
||||||
|
return markerName;
|
||||||
|
}
|
||||||
|
|
||||||
private void createRemoveSplitMarkerLocked(String splitName) throws IOException {
|
private void createRemoveSplitMarkerLocked(String splitName) throws IOException {
|
||||||
try {
|
try {
|
||||||
final String markerName = splitName + REMOVE_SPLIT_MARKER_EXTENSION;
|
final File target = new File(stageDir, getRemoveMarkerName(splitName));
|
||||||
if (!FileUtils.isValidExtFilename(markerName)) {
|
|
||||||
throw new IllegalArgumentException("Invalid marker: " + markerName);
|
|
||||||
}
|
|
||||||
final File target = new File(resolveStageDirLocked(), markerName);
|
|
||||||
target.createNewFile();
|
target.createNewFile();
|
||||||
Os.chmod(target.getAbsolutePath(), 0 /*mode*/);
|
Os.chmod(target.getAbsolutePath(), 0 /*mode*/);
|
||||||
} catch (ErrnoException e) {
|
} catch (ErrnoException e) {
|
||||||
@@ -681,7 +680,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
// will block any attempted install transitions.
|
// will block any attempted install transitions.
|
||||||
final RevocableFileDescriptor fd;
|
final RevocableFileDescriptor fd;
|
||||||
final FileBridge bridge;
|
final FileBridge bridge;
|
||||||
final File stageDir;
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
assertCallerIsOwnerOrRootLocked();
|
assertCallerIsOwnerOrRootLocked();
|
||||||
assertPreparedAndNotSealedLocked("openWrite");
|
assertPreparedAndNotSealedLocked("openWrite");
|
||||||
@@ -695,8 +693,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
bridge = new FileBridge();
|
bridge = new FileBridge();
|
||||||
mBridges.add(bridge);
|
mBridges.add(bridge);
|
||||||
}
|
}
|
||||||
|
|
||||||
stageDir = resolveStageDirLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -802,7 +798,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
if (!FileUtils.isValidExtFilename(name)) {
|
if (!FileUtils.isValidExtFilename(name)) {
|
||||||
throw new IllegalArgumentException("Invalid name: " + name);
|
throw new IllegalArgumentException("Invalid name: " + name);
|
||||||
}
|
}
|
||||||
final File target = new File(resolveStageDirLocked(), name);
|
final File target = new File(stageDir, name);
|
||||||
final FileDescriptor targetFd = Os.open(target.getAbsolutePath(), O_RDONLY, 0);
|
final FileDescriptor targetFd = Os.open(target.getAbsolutePath(), O_RDONLY, 0);
|
||||||
return new ParcelFileDescriptor(targetFd);
|
return new ParcelFileDescriptor(targetFd);
|
||||||
} catch (ErrnoException e) {
|
} catch (ErrnoException e) {
|
||||||
@@ -948,7 +944,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
* This method may be called multiple times to update the status receiver validate caller
|
* This method may be called multiple times to update the status receiver validate caller
|
||||||
* permissions.
|
* permissions.
|
||||||
*/
|
*/
|
||||||
public boolean markAsCommitted(
|
private boolean markAsCommitted(
|
||||||
@NonNull IntentSender statusReceiver, boolean forTransfer) {
|
@NonNull IntentSender statusReceiver, boolean forTransfer) {
|
||||||
Preconditions.checkNotNull(statusReceiver);
|
Preconditions.checkNotNull(statusReceiver);
|
||||||
|
|
||||||
@@ -959,10 +955,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
assertCallerIsOwnerOrRootLocked();
|
assertCallerIsOwnerOrRootLocked();
|
||||||
assertPreparedAndNotDestroyedLocked("commit");
|
assertPreparedAndNotDestroyedLocked("commit");
|
||||||
|
|
||||||
final PackageInstallObserverAdapter adapter = new PackageInstallObserverAdapter(
|
mRemoteStatusReceiver = statusReceiver;
|
||||||
mContext, statusReceiver, sessionId,
|
|
||||||
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId);
|
|
||||||
mRemoteObserver = adapter.getBinder();
|
|
||||||
|
|
||||||
if (forTransfer) {
|
if (forTransfer) {
|
||||||
mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
|
mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, null);
|
||||||
@@ -986,12 +979,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
if (!mSealed) {
|
if (!mSealed) {
|
||||||
try {
|
try {
|
||||||
sealAndValidateLocked(childSessions);
|
sealAndValidateLocked(childSessions);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalArgumentException(e);
|
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
// Do now throw an exception here to stay compatible with O and older
|
|
||||||
destroyInternal();
|
|
||||||
dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1091,52 +1079,59 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
*/
|
*/
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private void sealAndValidateLocked(List<PackageInstallerSession> childSessions)
|
private void sealAndValidateLocked(List<PackageInstallerSession> childSessions)
|
||||||
throws PackageManagerException, IOException {
|
throws PackageManagerException {
|
||||||
assertNoWriteFileTransfersOpenLocked();
|
try {
|
||||||
assertPreparedAndNotDestroyedLocked("sealing of session");
|
assertNoWriteFileTransfersOpenLocked();
|
||||||
|
assertPreparedAndNotDestroyedLocked("sealing of session");
|
||||||
|
|
||||||
mSealed = true;
|
mSealed = true;
|
||||||
|
|
||||||
if (childSessions != null) {
|
if (childSessions != null) {
|
||||||
assertMultiPackageConsistencyLocked(childSessions);
|
assertMultiPackageConsistencyLocked(childSessions);
|
||||||
}
|
|
||||||
|
|
||||||
if (params.isStaged) {
|
|
||||||
final PackageInstallerSession activeSession = mStagingManager.getActiveSession();
|
|
||||||
final boolean anotherSessionAlreadyInProgress =
|
|
||||||
activeSession != null && sessionId != activeSession.sessionId
|
|
||||||
&& mParentSessionId != activeSession.sessionId;
|
|
||||||
if (anotherSessionAlreadyInProgress) {
|
|
||||||
throw new PackageManagerException(
|
|
||||||
PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
|
|
||||||
"There is already in-progress committed staged session "
|
|
||||||
+ activeSession.sessionId, null);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read transfers from the original owner stay open, but as the session's data
|
if (params.isStaged) {
|
||||||
// cannot be modified anymore, there is no leak of information. For staged sessions,
|
final PackageInstallerSession activeSession = mStagingManager.getActiveSession();
|
||||||
// further validation is performed by the staging manager.
|
final boolean anotherSessionAlreadyInProgress =
|
||||||
if (!params.isMultiPackage) {
|
activeSession != null && sessionId != activeSession.sessionId
|
||||||
final PackageInfo pkgInfo = mPm.getPackageInfo(
|
&& mParentSessionId != activeSession.sessionId;
|
||||||
params.appPackageName, PackageManager.GET_SIGNATURES
|
if (anotherSessionAlreadyInProgress) {
|
||||||
| PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
|
throw new PackageManagerException(
|
||||||
|
PackageManager.INSTALL_FAILED_OTHER_STAGED_SESSION_IN_PROGRESS,
|
||||||
resolveStageDirLocked();
|
"There is already in-progress committed staged session "
|
||||||
|
+ activeSession.sessionId, null);
|
||||||
try {
|
|
||||||
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
|
|
||||||
validateApexInstallLocked();
|
|
||||||
} else {
|
|
||||||
validateApkInstallLocked(pkgInfo);
|
|
||||||
}
|
}
|
||||||
} catch (PackageManagerException e) {
|
|
||||||
throw e;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
// Convert all exceptions into package manager exceptions as only those are handled
|
|
||||||
// in the code above
|
|
||||||
throw new PackageManagerException(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read transfers from the original owner stay open, but as the session's data
|
||||||
|
// cannot be modified anymore, there is no leak of information. For staged sessions,
|
||||||
|
// further validation is performed by the staging manager.
|
||||||
|
if (!params.isMultiPackage) {
|
||||||
|
final PackageInfo pkgInfo = mPm.getPackageInfo(
|
||||||
|
params.appPackageName, PackageManager.GET_SIGNATURES
|
||||||
|
| PackageManager.MATCH_STATIC_SHARED_LIBRARIES /*flags*/, userId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
|
||||||
|
validateApexInstallLocked();
|
||||||
|
} else {
|
||||||
|
validateApkInstallLocked(pkgInfo);
|
||||||
|
}
|
||||||
|
} catch (PackageManagerException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// Convert all exceptions into package manager exceptions as only those are
|
||||||
|
// handled in the code above.
|
||||||
|
throw new PackageManagerException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PackageManagerException e) {
|
||||||
|
// Session is sealed but could not be verified, we need to destroy it.
|
||||||
|
destroyInternal();
|
||||||
|
// Dispatch message to remove session from PackageInstallerService
|
||||||
|
dispatchSessionFinished(
|
||||||
|
e.error, ExceptionUtils.getCompleteMessage(e), null);
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1159,15 +1154,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
try {
|
try {
|
||||||
sealAndValidateLocked(childSessions);
|
sealAndValidateLocked(childSessions);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
Slog.e(TAG, "Package not valid", e);
|
Slog.e(TAG, "Package not valid", e);
|
||||||
// Session is sealed but could not be verified, we need to destroy it.
|
|
||||||
destroyInternal();
|
|
||||||
// Dispatch message to remove session from PackageInstallerService
|
|
||||||
dispatchSessionFinished(
|
|
||||||
e.error, ExceptionUtils.getCompleteMessage(e), null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1208,13 +1196,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
sealAndValidateLocked(childSessions);
|
sealAndValidateLocked(childSessions);
|
||||||
} catch (IOException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
// Session is sealed but could not be verified, we need to destroy it
|
|
||||||
destroyInternal();
|
|
||||||
dispatchSessionFinished(e.error, ExceptionUtils.getCompleteMessage(e), null);
|
|
||||||
|
|
||||||
throw new IllegalArgumentException("Package is not valid", e);
|
throw new IllegalArgumentException("Package is not valid", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1299,11 +1281,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!success) {
|
if (!success) {
|
||||||
try {
|
PackageInstallerService.sendOnPackageInstalled(mContext,
|
||||||
mRemoteObserver.onPackageInstalled(
|
mRemoteStatusReceiver, sessionId,
|
||||||
null, failure.error, failure.getLocalizedMessage(), null);
|
isInstallerDeviceOwnerOrAffiliatedProfileOwnerLocked(), userId, null,
|
||||||
} catch (RemoteException ignored) {
|
failure.error, failure.getLocalizedMessage(), null);
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mPm.installStage(activeChildSessions);
|
mPm.installStage(activeChildSessions);
|
||||||
@@ -1347,10 +1328,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
|
final Intent intent = new Intent(PackageInstaller.ACTION_CONFIRM_INSTALL);
|
||||||
intent.setPackage(mPm.getPackageInstallerPackageName());
|
intent.setPackage(mPm.getPackageInstallerPackageName());
|
||||||
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
|
intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId);
|
||||||
try {
|
|
||||||
mRemoteObserver.onUserActionRequired(intent);
|
PackageInstallerService.sendOnUserActionRequired(mContext,
|
||||||
} catch (RemoteException ignored) {
|
mRemoteStatusReceiver, sessionId, intent);
|
||||||
}
|
|
||||||
|
|
||||||
// Commit was keeping session marked as active until now; release
|
// Commit was keeping session marked as active until now; release
|
||||||
// that extra refcount so session appears idle.
|
// that extra refcount so session appears idle.
|
||||||
@@ -1363,7 +1343,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
|
if (params.mode == SessionParams.MODE_INHERIT_EXISTING) {
|
||||||
try {
|
try {
|
||||||
final List<File> fromFiles = mResolvedInheritedFiles;
|
final List<File> fromFiles = mResolvedInheritedFiles;
|
||||||
final File toDir = resolveStageDirLocked();
|
final File toDir = stageDir;
|
||||||
|
|
||||||
if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
|
if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
|
||||||
if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
|
if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
|
||||||
@@ -1413,8 +1393,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
computeProgressLocked(true);
|
computeProgressLocked(true);
|
||||||
|
|
||||||
// Unpack native libraries
|
// Unpack native libraries
|
||||||
extractNativeLibraries(mResolvedStageDir, params.abiOverride,
|
extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
|
||||||
mayInheritNativeLibs());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've reached point of no return; call into PMS to install the stage.
|
// We've reached point of no return; call into PMS to install the stage.
|
||||||
@@ -1475,7 +1454,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private void validateApexInstallLocked()
|
private void validateApexInstallLocked()
|
||||||
throws PackageManagerException {
|
throws PackageManagerException {
|
||||||
final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
|
final File[] addedFiles = getAddedFilesLocked();
|
||||||
if (ArrayUtils.isEmpty(addedFiles)) {
|
if (ArrayUtils.isEmpty(addedFiles)) {
|
||||||
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
|
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
|
||||||
}
|
}
|
||||||
@@ -1485,13 +1464,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
"Too many files for apex install");
|
"Too many files for apex install");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
resolveStageDirLocked();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
|
|
||||||
"Failed to resolve stage location", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
File addedFile = addedFiles[0]; // there is only one file
|
File addedFile = addedFiles[0]; // there is only one file
|
||||||
|
|
||||||
// Ensure file name has proper suffix
|
// Ensure file name has proper suffix
|
||||||
@@ -1504,7 +1476,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
"Invalid filename: " + targetName);
|
"Invalid filename: " + targetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
final File targetFile = new File(mResolvedStageDir, targetName);
|
final File targetFile = new File(stageDir, targetName);
|
||||||
resolveAndStageFile(addedFile, targetFile);
|
resolveAndStageFile(addedFile, targetFile);
|
||||||
|
|
||||||
mResolvedBaseFile = targetFile;
|
mResolvedBaseFile = targetFile;
|
||||||
@@ -1545,25 +1517,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
&& params.mode == SessionParams.MODE_INHERIT_EXISTING
|
&& params.mode == SessionParams.MODE_INHERIT_EXISTING
|
||||||
&& VerityUtils.hasFsverity(pkgInfo.applicationInfo.getBaseCodePath());
|
&& VerityUtils.hasFsverity(pkgInfo.applicationInfo.getBaseCodePath());
|
||||||
|
|
||||||
try {
|
final File[] removedFiles = getRemovedFilesLocked();
|
||||||
resolveStageDirLocked();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR,
|
|
||||||
"Failed to resolve stage location", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
final File[] removedFiles = mResolvedStageDir.listFiles(sRemovedFilter);
|
|
||||||
final List<String> removeSplitList = new ArrayList<>();
|
final List<String> removeSplitList = new ArrayList<>();
|
||||||
if (!ArrayUtils.isEmpty(removedFiles)) {
|
if (!ArrayUtils.isEmpty(removedFiles)) {
|
||||||
for (File removedFile : removedFiles) {
|
for (File removedFile : removedFiles) {
|
||||||
final String fileName = removedFile.getName();
|
final String fileName = removedFile.getName();
|
||||||
final String splitName = fileName.substring(
|
final String splitName = fileName.substring(
|
||||||
0, fileName.length() - REMOVE_SPLIT_MARKER_EXTENSION.length());
|
0, fileName.length() - REMOVE_MARKER_EXTENSION.length());
|
||||||
removeSplitList.add(splitName);
|
removeSplitList.add(splitName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final File[] addedFiles = mResolvedStageDir.listFiles(sAddedFilter);
|
final File[] addedFiles = getAddedFilesLocked();
|
||||||
if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
|
if (ArrayUtils.isEmpty(addedFiles) && removeSplitList.size() == 0) {
|
||||||
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
|
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, "No packages staged");
|
||||||
}
|
}
|
||||||
@@ -1607,7 +1572,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
"Invalid filename: " + targetName);
|
"Invalid filename: " + targetName);
|
||||||
}
|
}
|
||||||
|
|
||||||
final File targetFile = new File(mResolvedStageDir, targetName);
|
final File targetFile = new File(stageDir, targetName);
|
||||||
resolveAndStageFile(addedFile, targetFile);
|
resolveAndStageFile(addedFile, targetFile);
|
||||||
|
|
||||||
// Base is coming from session
|
// Base is coming from session
|
||||||
@@ -1622,7 +1587,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
|
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
|
||||||
"Invalid filename: " + dexMetadataFile);
|
"Invalid filename: " + dexMetadataFile);
|
||||||
}
|
}
|
||||||
final File targetDexMetadataFile = new File(mResolvedStageDir,
|
final File targetDexMetadataFile = new File(stageDir,
|
||||||
DexMetadataHelper.buildDexMetadataPathForApk(targetName));
|
DexMetadataHelper.buildDexMetadataPathForApk(targetName));
|
||||||
resolveAndStageFile(dexMetadataFile, targetDexMetadataFile);
|
resolveAndStageFile(dexMetadataFile, targetDexMetadataFile);
|
||||||
}
|
}
|
||||||
@@ -2182,17 +2147,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
|
private void dispatchSessionFinished(int returnCode, String msg, Bundle extras) {
|
||||||
final IPackageInstallObserver2 observer;
|
final IntentSender statusReceiver;
|
||||||
final String packageName;
|
final String packageName;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
mFinalStatus = returnCode;
|
mFinalStatus = returnCode;
|
||||||
mFinalMessage = msg;
|
mFinalMessage = msg;
|
||||||
|
|
||||||
observer = mRemoteObserver;
|
statusReceiver = mRemoteStatusReceiver;
|
||||||
packageName = mPackageName;
|
packageName = mPackageName;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (observer != null) {
|
if (statusReceiver != null) {
|
||||||
// Execute observer.onPackageInstalled on different tread as we don't want callers
|
// Execute observer.onPackageInstalled on different tread as we don't want callers
|
||||||
// inside the system server have to worry about catching the callbacks while they are
|
// inside the system server have to worry about catching the callbacks while they are
|
||||||
// calling into the session
|
// calling into the session
|
||||||
@@ -2200,7 +2165,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
|||||||
args.arg1 = packageName;
|
args.arg1 = packageName;
|
||||||
args.arg2 = msg;
|
args.arg2 = msg;
|
||||||
args.arg3 = extras;
|
args.arg3 = extras;
|
||||||
args.arg4 = observer;
|
args.arg4 = statusReceiver;
|
||||||
args.argi1 = returnCode;
|
args.argi1 = returnCode;
|
||||||
|
|
||||||
mHandler.obtainMessage(MSG_ON_PACKAGE_INSTALLED, args).sendToTarget();
|
mHandler.obtainMessage(MSG_ON_PACKAGE_INSTALLED, args).sendToTarget();
|
||||||
|
|||||||
Reference in New Issue
Block a user