import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
+import static android.content.Intent.ACTION_MAIN;
+import static android.content.Intent.CATEGORY_DEFAULT;
+import static android.content.Intent.CATEGORY_HOME;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
// app's nature doesn't depend on the user, so we can just check
// its browser nature in any user and generalize.
if (packageIsBrowser(packageName, userId)) {
- mSettings.setDefaultBrowserPackageNameLPw(null, userId);
+ // If this browser is restored from user's backup, do not clear
+ // default-browser state for this user
+ final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+ if (pkgSetting.getInstallReason(userId)
+ != PackageManager.INSTALL_REASON_DEVICE_RESTORE) {
+ mSettings.setDefaultBrowserPackageNameLPw(null, userId);
+ }
}
// We may also need to apply pending (restored) runtime
| SCAN_AS_SYSTEM
| SCAN_AS_PRIVILEGED,
0);
+ if (!mPackages.containsKey("android")) {
+ throw new IllegalStateException(
+ "Failed to load frameworks package; check log for warnings");
+ }
// Collect privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
* Access may be limited based upon whether the calling or target applications
* are instant applications.
*
- * @see #canAccessInstantApps(int)
+ * @see #canViewInstantApps(int, int)
*/
private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid,
@Nullable ComponentName component, @ComponentType int componentType, int userId) {
}
/**
- * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, boolean, int)
+ * @see #filterAppAccessLPr(PackageSetting, int, ComponentName, int, int)
*/
private boolean filterAppAccessLPr(@Nullable PackageSetting ps, int callingUid, int userId) {
return filterAppAccessLPr(ps, callingUid, null, TYPE_UNKNOWN, userId);
@Override
public void deletePreloadsFileCache() {
- if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.SYSTEM_UID)) {
- throw new SecurityException("Only system or settings may call deletePreloadsFileCache");
- }
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CLEAR_APP_CACHE,
+ "deletePreloadsFileCache");
File dir = Environment.getDataPreloadsFileCacheDirectory();
Slog.i(TAG, "Deleting preloaded file cache " + dir);
FileUtils.deleteContents(dir);
return null;
}
+ private boolean isHomeIntent(Intent intent) {
+ return ACTION_MAIN.equals(intent.getAction())
+ && intent.hasCategory(CATEGORY_HOME)
+ && intent.hasCategory(CATEGORY_DEFAULT);
+ }
+
+ private boolean isDeviceProvisioned() {
+ return android.provider.Settings.Global.getInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.DEVICE_PROVISIONED, 0) == 1;
+ }
+
// TODO: handle preferred activities missing while user has amnesia
ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, int priority, boolean always,
Slog.v(TAG, " null");
}
}
+ final boolean excludeSetupWizardHomeActivity = isHomeIntent(intent)
+ && !isDeviceProvisioned();
if (ai == null) {
+ // Do not remove launcher's preferred activity during SetupWizard
+ // due to it may not install yet
+ if (excludeSetupWizardHomeActivity) {
+ continue;
+ }
+
// This previously registered preferred activity
// component is no longer known. Most likely an update
// to the app was installed and in the new version this
// was created, and is not a subset of the preferred set, we need to
// clear it and re-ask the user their preference, if we're looking for
// an "always" type entry.
- if (always && !pa.mPref.sameSet(query)) {
- if (pa.mPref.isSuperset(query)) {
- // some components of the set are no longer present in
- // the query, but the preferred activity can still be reused
- if (DEBUG_PREFERRED) {
- Slog.i(TAG, "Result set changed, but PreferredActivity is"
- + " still valid as only non-preferred components"
- + " were removed for " + intent + " type "
- + resolvedType);
+
+ if (always && !pa.mPref.sameSet(query, excludeSetupWizardHomeActivity)) {
+ if (pa.mPref.isSuperset(query, excludeSetupWizardHomeActivity)) {
+ if (!excludeSetupWizardHomeActivity) {
+ // some components of the set are no longer present in
+ // the query, but the preferred activity can still be reused
+ if (DEBUG_PREFERRED) {
+ Slog.i(TAG, "Result set changed, but PreferredActivity"
+ + " is still valid as only non-preferred"
+ + " components were removed for " + intent
+ + " type " + resolvedType);
+ }
+ // remove obsolete components and re-add the up-to-date
+ // filter
+ PreferredActivity freshPa = new PreferredActivity(pa,
+ pa.mPref.mMatch,
+ pa.mPref.discardObsoleteComponents(query),
+ pa.mPref.mComponent,
+ pa.mPref.mAlways);
+ pir.removeFilter(pa);
+ pir.addFilter(freshPa);
+ changed = true;
+ } else {
+ if (DEBUG_PREFERRED) {
+ Slog.i(TAG, "Do not remove preferred activity for launcher"
+ + " during SetupWizard");
+ }
}
- // remove obsolete components and re-add the up-to-date filter
- PreferredActivity freshPa = new PreferredActivity(pa,
- pa.mPref.mMatch,
- pa.mPref.discardObsoleteComponents(query),
- pa.mPref.mComponent,
- pa.mPref.mAlways);
- pir.removeFilter(pa);
- pir.addFilter(freshPa);
- changed = true;
} else {
Slog.i(TAG,
"Result set changed, dropping preferred activity for "
compareSignatures(
signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures,
pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) {
- throw new PackageManagerException(
- INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
- "Signature mismatch for shared user: " + pkgSetting.sharedUser);
+ // Treat mismatched signatures on system packages using a shared UID as
+ // fatal for the system overall, rather than just failing to install
+ // whichever package happened to be scanned later.
+ throw new IllegalStateException(
+ "Signature mismatch on system package " + pkg.packageName
+ + " for shared user " + pkgSetting.sharedUser);
}
signatureCheckPs.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails;
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
} catch (IllegalArgumentException e) {
-
// should never happen: certs matched when checking, but not when comparing
// old to new for sharedUser
- throw new PackageManagerException(INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
+ throw new RuntimeException(
"Signing certificates comparison made on incomparable signing details"
- + " but somehow passed verifySignatures!");
+ + " but somehow passed verifySignatures!", e);
}
}
final File file;
/**
- * Flag indicating that {@link #file} or {@link #cid} has already been
- * staged, meaning downstream users don't need to defensively copy the
- * contents.
+ * Flag indicating that {@link #file} has already been staged, meaning downstream users
+ * don't need to defensively copy the contents.
*/
final boolean staged;
/**
- * Flag indicating that {@link #file} or {@link #cid} is an already
- * installed app that is being moved.
+ * Flag indicating that {@link #file} is an already installed app that is being moved.
*/
final boolean existing;
final int uid = Binder.getCallingUid();
if (!isOrphaned(internalPackageName)
&& !isCallerAllowedToSilentlyUninstall(uid, internalPackageName)) {
- try {
- final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
- intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
- intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder());
- observer.onUserActionRequired(intent);
- } catch (RemoteException re) {
- }
+ mHandler.post(() -> {
+ try {
+ final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
+ intent.setData(Uri.fromParts(PACKAGE_SCHEME, packageName, null));
+ intent.putExtra(PackageInstaller.EXTRA_CALLBACK, observer.asBinder());
+ observer.onUserActionRequired(intent);
+ } catch (RemoteException re) {
+ }
+ });
return;
}
final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0;
- final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{ userId };
+ final int[] users = deleteAllUsers ? sUserManager.getUserIds() : new int[]{userId};
if (UserHandle.getUserId(uid) != userId || (deleteAllUsers && users.length > 1)) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
}
if (isUserRestricted(userId, UserManager.DISALLOW_UNINSTALL_APPS)) {
- try {
- observer.onPackageDeleted(packageName,
- PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
- } catch (RemoteException re) {
- }
+ mHandler.post(() -> {
+ try {
+ observer.onPackageDeleted(packageName,
+ PackageManager.DELETE_FAILED_USER_RESTRICTED, null);
+ } catch (RemoteException re) {
+ }
+ });
return;
}
if (!deleteAllUsers && getBlockUninstallForUser(internalPackageName, userId)) {
- try {
- observer.onPackageDeleted(packageName,
- PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
- } catch (RemoteException re) {
- }
+ mHandler.post(() -> {
+ try {
+ observer.onPackageDeleted(packageName,
+ PackageManager.DELETE_FAILED_OWNER_BLOCKED, null);
+ } catch (RemoteException re) {
+ }
+ });
return;
}
? "VERSION_CODE_HIGHEST" : versionCode));
}
// Queue up an async operation since the package deletion may take a little while.
- mHandler.post(new Runnable() {
- public void run() {
- mHandler.removeCallbacks(this);
- int returnCode;
- final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
- boolean doDeletePackage = true;
- if (ps != null) {
- final boolean targetIsInstantApp =
- ps.getInstantApp(UserHandle.getUserId(callingUid));
- doDeletePackage = !targetIsInstantApp
- || canViewInstantApps;
- }
- if (doDeletePackage) {
- if (!deleteAllUsers) {
+ mHandler.post(() -> {
+ int returnCode;
+ final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
+ boolean doDeletePackage = true;
+ if (ps != null) {
+ final boolean targetIsInstantApp =
+ ps.getInstantApp(UserHandle.getUserId(callingUid));
+ doDeletePackage = !targetIsInstantApp
+ || canViewInstantApps;
+ }
+ if (doDeletePackage) {
+ if (!deleteAllUsers) {
+ returnCode = deletePackageX(internalPackageName, versionCode,
+ userId, deleteFlags);
+ } else {
+ int[] blockUninstallUserIds = getBlockUninstallForUsers(
+ internalPackageName, users);
+ // If nobody is blocking uninstall, proceed with delete for all users
+ if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
returnCode = deletePackageX(internalPackageName, versionCode,
userId, deleteFlags);
} else {
- int[] blockUninstallUserIds = getBlockUninstallForUsers(
- internalPackageName, users);
- // If nobody is blocking uninstall, proceed with delete for all users
- if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
- returnCode = deletePackageX(internalPackageName, versionCode,
- userId, deleteFlags);
- } else {
- // Otherwise uninstall individually for users with blockUninstalls=false
- final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
- for (int userId : users) {
- if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
- returnCode = deletePackageX(internalPackageName, versionCode,
- userId, userFlags);
- if (returnCode != PackageManager.DELETE_SUCCEEDED) {
- Slog.w(TAG, "Package delete failed for user " + userId
- + ", returnCode " + returnCode);
- }
+ // Otherwise uninstall individually for users with blockUninstalls=false
+ final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
+ for (int userId1 : users) {
+ if (!ArrayUtils.contains(blockUninstallUserIds, userId1)) {
+ returnCode = deletePackageX(internalPackageName, versionCode,
+ userId1, userFlags);
+ if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+ Slog.w(TAG, "Package delete failed for user " + userId1
+ + ", returnCode " + returnCode);
}
}
- // The app has only been marked uninstalled for certain users.
- // We still need to report that delete was blocked
- returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
+ // The app has only been marked uninstalled for certain users.
+ // We still need to report that delete was blocked
+ returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
}
- } else {
- returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
}
- try {
- observer.onPackageDeleted(packageName, returnCode, null);
- } catch (RemoteException e) {
- Log.i(TAG, "Observer no longer exists.");
- } //end catch
- } //end run
+ } else {
+ returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
+ }
+ try {
+ observer.onPackageDeleted(packageName, returnCode, null);
+ } catch (RemoteException e) {
+ Log.i(TAG, "Observer no longer exists.");
+ } //end catch
});
}
public boolean isOrphaned(String packageName) {
// reader
synchronized (mPackages) {
+ if (!mPackages.containsKey(packageName)) {
+ return false;
+ }
return mSettings.isOrphaned(packageName);
}
}