Only grant runtime permissions to special components.
Now runtime permissions are granted only to components that are
part of the system or perform special system operations. For
exmple, the shell UID gets its runtime permissions granted by
default and the default phone app gets the phone permissions
granted by default.
bug:21764803
Change-Id: If8b8cadbd1980ffe7a6fc15bbb5f54a425f6e8f9
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 9fb6f4d..6feb860 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -962,6 +962,13 @@
/**
* @hide
*/
+ public boolean isPrivilegedApp() {
+ return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
+ }
+
+ /**
+ * @hide
+ */
public boolean isUpdatedSystemApp() {
return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
new file mode 100644
index 0000000..7599bd6
--- /dev/null
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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 android.content.pm;
+
+import android.annotation.NonNull;
+
+/**
+ * Package manager local system service interface.
+ *
+ * @hide Only for use within the system server.
+ */
+public abstract class PackageManagerInternal {
+
+ /**
+ * Provider for package names.
+ */
+ public interface PackagesProvider {
+
+ /**
+ * Gets the packages for a given user.
+ * @param userId The user id.
+ * @return The package names.
+ */
+ public String[] getPackages(int userId);
+ }
+
+ /**
+ * Sets the location provider packages provider.
+ * @param provider The packages provider.
+ */
+ public abstract void setLocationPackagesProvider(PackagesProvider provider);
+
+ /**
+ * Sets the input method packages provider.
+ * @param provider The packages provider.
+ */
+ public abstract void setImePackagesProvider(PackagesProvider provider);
+
+ /**
+ * Sets the voice interaction packages provider.
+ * @param provider The packages provider.
+ */
+ public abstract void setVoiceInteractionPackagesProvider(PackagesProvider provider);
+}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 287e0c5..faf71ee 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -4508,6 +4508,13 @@
/**
* @hide
*/
+ public boolean isPrivilegedApp() {
+ return applicationInfo.isPrivilegedApp();
+ }
+
+ /**
+ * @hide
+ */
public boolean isUpdatedSystemApp() {
return applicationInfo.isUpdatedSystemApp();
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index a5d536e..9a9a4ae 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
import android.annotation.NonNull;
+import android.content.pm.PackageManagerInternal;
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -31,6 +32,7 @@
import com.android.internal.view.IInputMethodManager;
import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
+import com.android.server.pm.UserManagerService;
import com.android.server.statusbar.StatusBarManagerService;
import com.android.server.wm.WindowManagerService;
@@ -859,6 +861,38 @@
// mSettings should be created before buildInputMethodListLocked
mSettings = new InputMethodSettings(
mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
+
+ // Let the package manager query which are the default imes
+ // as they get certain permissions granted by default.
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ packageManagerInternal.setImePackagesProvider(
+ new PackageManagerInternal.PackagesProvider() {
+ @Override
+ public String[] getPackages(int userId) {
+ synchronized (mMethodMap) {
+ final int currentUserId = mSettings.getCurrentUserId();
+ // TODO: We are switching the current user id in the settings
+ // object to query it and then revert the user id. Ideally, we
+ // should call a API in settings with the user id as an argument.
+ mSettings.setCurrentUserId(userId);
+ List<InputMethodInfo> imes = mSettings
+ .getEnabledInputMethodListLocked();
+ String[] packageNames = null;
+ if (imes != null) {
+ final int imeCount = imes.size();
+ packageNames = new String[imeCount];
+ for (int i = 0; i < imeCount; i++) {
+ InputMethodInfo ime = imes.get(i);
+ packageNames[i] = ime.getPackageName();
+ }
+ }
+ mSettings.setCurrentUserId(currentUserId);
+ return packageNames;
+ }
+ }
+ });
+
updateCurrentProfileIds();
mFileManager = new InputMethodFileManager(mMethodMap, userId);
synchronized (mMethodMap) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index c76fc1c..c98f33e 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.content.pm.PackageManagerInternal;
import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
@@ -218,6 +219,19 @@
mContext = context;
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
+ // Let the package manager query which are the default location
+ // providers as they get certain permissions granted by default.
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ packageManagerInternal.setLocationPackagesProvider(
+ new PackageManagerInternal.PackagesProvider() {
+ @Override
+ public String[] getPackages(int userId) {
+ return mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_locationProviderPackageNames);
+ }
+ });
+
if (D) Log.d(TAG, "Constructed");
// most startup is deferred until systemReady()
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
new file mode 100644
index 0000000..fe3103b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -0,0 +1,521 @@
+/*
+ * Copyright (C) 2015 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.Manifest;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal.PackagesProvider;
+import android.content.pm.PackageParser;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Build;
+import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.util.ArraySet;
+import android.util.Log;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import static android.os.Process.FIRST_APPLICATION_UID;
+
+/**
+ * This class is the policy for granting runtime permissions to
+ * platform components and default handlers in the system such
+ * that the device is usable out-of-the-box. For example, the
+ * shell UID is a part of the system and the Phone app should
+ * have phone related permission by default.
+ */
+final class DefaultPermissionGrantPolicy {
+ private static final String TAG = "DefaultPermissionGrantPolicy";
+ private static final boolean DEBUG = false;
+
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
+ private static final Set<String> PHONE_PERMISSIONS = new ArraySet<>();
+ static {
+ PHONE_PERMISSIONS.add(Manifest.permission.READ_PHONE_STATE);
+ PHONE_PERMISSIONS.add(Manifest.permission.CALL_PHONE);
+ PHONE_PERMISSIONS.add( Manifest.permission.READ_CALL_LOG);
+ PHONE_PERMISSIONS.add(Manifest.permission.WRITE_CALL_LOG);
+ PHONE_PERMISSIONS.add(Manifest.permission.ADD_VOICEMAIL);
+ PHONE_PERMISSIONS.add(Manifest.permission.USE_SIP);
+ PHONE_PERMISSIONS.add(Manifest.permission.PROCESS_OUTGOING_CALLS);
+ }
+
+ private static final Set<String> CONTACTS_PERMISSIONS = new ArraySet<>();
+ static {
+ CONTACTS_PERMISSIONS.add(Manifest.permission.READ_CONTACTS);
+ CONTACTS_PERMISSIONS.add(Manifest.permission.WRITE_CONTACTS);
+ }
+
+ private static final Set<String> LOCATION_PERMISSIONS = new ArraySet<>();
+ static {
+ LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
+ LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
+ }
+
+ private static final Set<String> CALENDAR_PERMISSIONS = new ArraySet<>();
+ static {
+ CALENDAR_PERMISSIONS.add(Manifest.permission.READ_CALENDAR);
+ CALENDAR_PERMISSIONS.add(Manifest.permission.WRITE_CALENDAR);
+ }
+
+ private static final Set<String> SMS_PERMISSIONS = new ArraySet<>();
+ static {
+ SMS_PERMISSIONS.add(Manifest.permission.SEND_SMS);
+ SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_SMS);
+ SMS_PERMISSIONS.add(Manifest.permission.READ_SMS);
+ SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_WAP_PUSH);
+ SMS_PERMISSIONS.add(Manifest.permission.RECEIVE_MMS);
+ SMS_PERMISSIONS.add(Manifest.permission.READ_CELL_BROADCASTS);
+ }
+
+ private static final Set<String> MICROPHONE_PERMISSIONS = new ArraySet<>();
+ static {
+ MICROPHONE_PERMISSIONS.add(Manifest.permission.RECORD_AUDIO);
+ }
+
+ private static final Set<String> CAMERA_PERMISSIONS = new ArraySet<>();
+ static {
+ CAMERA_PERMISSIONS.add(Manifest.permission.CAMERA);
+ }
+
+ private static final Set<String> SENSORS_PERMISSIONS = new ArraySet<>();
+ static {
+ SENSORS_PERMISSIONS.add(Manifest.permission.BODY_SENSORS);
+ }
+
+ private static final Set<String> STORAGE_PERMISSIONS = new ArraySet<>();
+ static {
+// STORAGE_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ STORAGE_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+ private static final Set<String> SETTINGS_PERMISSIONS = new ArraySet<>();
+ static {
+ SETTINGS_PERMISSIONS.add(Manifest.permission.WRITE_SETTINGS);
+ }
+
+ private static final Set<String> INSTALLER_PERMISSIONS = new ArraySet<>();
+ static {
+ INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS);
+ INSTALLER_PERMISSIONS.add(Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+ INSTALLER_PERMISSIONS.add(Manifest.permission.CLEAR_APP_USER_DATA);
+ INSTALLER_PERMISSIONS.add(Manifest.permission.KILL_UID);
+ }
+
+ private static final Set<String> VERIFIER_PERMISSIONS = new ArraySet<>();
+ static {
+ INSTALLER_PERMISSIONS.add(Manifest.permission.GRANT_REVOKE_PERMISSIONS);
+ }
+
+ private final PackageManagerService mService;
+
+ private PackagesProvider mImePackagesProvider;
+ private PackagesProvider mLocationPackagesProvider;
+ private PackagesProvider mVoiceInteractionPackagesProvider;
+
+ public DefaultPermissionGrantPolicy(PackageManagerService service) {
+ mService = service;
+ }
+
+ public void setImePackagesProviderLPr(PackagesProvider provider) {
+ mImePackagesProvider = provider;
+ }
+
+ public void setLocationPackagesProviderLPw(PackagesProvider provider) {
+ mLocationPackagesProvider = provider;
+ }
+
+ public void setVoiceInteractionPackagesProviderLPw(PackagesProvider provider) {
+ mVoiceInteractionPackagesProvider = provider;
+ }
+
+ public void grantDefaultPermissions(int userId) {
+ grantPermissionsToSysComponentsAndPrivApps(userId);
+ grantDefaultSystemHandlerPermissions(userId);
+ }
+
+ private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
+ Log.i(TAG, "Granting permissions to platform components");
+
+ synchronized (mService.mPackages) {
+ for (PackageParser.Package pkg : mService.mPackages.values()) {
+ if (!isSysComponentOrPersistentPrivApp(pkg)
+ || !doesPackageSupportRuntimePermissions(pkg)) {
+ continue;
+ }
+ final int permissionCount = pkg.requestedPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ String permission = pkg.requestedPermissions.get(i);
+ BasePermission bp = mService.mSettings.mPermissions.get(permission);
+ if (bp != null && bp.isRuntime()) {
+ final int flags = mService.getPermissionFlags(permission,
+ pkg.packageName, userId);
+ if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) == 0) {
+ mService.grantRuntimePermission(pkg.packageName, permission, userId);
+ mService.updatePermissionFlags(permission, pkg.packageName,
+ PackageManager.MASK_PERMISSION_FLAGS,
+ PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, userId);
+ if (DEBUG) {
+ Log.i(TAG, "Granted " + permission + " to system component "
+ + pkg.packageName);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void grantDefaultSystemHandlerPermissions(int userId) {
+ Log.i(TAG, "Granting permissions to default platform handlers");
+
+ final PackagesProvider imePackagesProvider;
+ final PackagesProvider locationPackagesProvider;
+ final PackagesProvider voiceInteractionPackagesProvider;
+
+ synchronized (mService.mPackages) {
+ imePackagesProvider = mImePackagesProvider;
+ locationPackagesProvider = mLocationPackagesProvider;
+ voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
+ }
+
+ String[] imePackageNames = (imePackagesProvider != null)
+ ? imePackagesProvider.getPackages(userId) : null;
+ String[] voiceInteractPackageNames = (voiceInteractionPackagesProvider != null)
+ ? voiceInteractionPackagesProvider.getPackages(userId) : null;
+ String[] locationPackageNames = (locationPackagesProvider != null)
+ ? locationPackagesProvider.getPackages(userId) : null;
+
+ synchronized (mService.mPackages) {
+ // Installers
+ Intent installerIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
+ installerIntent.addCategory(Intent.CATEGORY_DEFAULT);
+ installerIntent.setDataAndType(Uri.fromFile(new File("foo.apk")),
+ PACKAGE_MIME_TYPE);
+ List<PackageParser.Package> installerPackages =
+ getPrivilegedHandlerActivityPackagesLPr(installerIntent, userId);
+ final int installerCount = installerPackages.size();
+ for (int i = 0; i < installerCount; i++) {
+ PackageParser.Package installPackage = installerPackages.get(i);
+ grantInstallPermissionsLPw(installPackage, INSTALLER_PERMISSIONS, userId);
+ }
+
+ // Verifiers
+ Intent verifierIntent = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verifierIntent.setType(PACKAGE_MIME_TYPE);
+ List<PackageParser.Package> verifierPackages =
+ getPrivilegedHandlerReceiverPackagesLPr(verifierIntent, userId);
+ final int verifierCount = verifierPackages.size();
+ for (int i = 0; i < verifierCount; i++) {
+ PackageParser.Package verifierPackage = verifierPackages.get(i);
+ grantInstallPermissionsLPw(verifierPackage, VERIFIER_PERMISSIONS, userId);
+ }
+
+ // SetupWizard
+ Intent setupIntent = new Intent(Intent.ACTION_MAIN);
+ setupIntent.addCategory(Intent.CATEGORY_HOME);
+ PackageParser.Package setupPackage = getDefaultSystemHandlerActvityPackageLPr(
+ setupIntent, userId);
+ if (setupPackage != null
+ && doesPackageSupportRuntimePermissions(setupPackage)) {
+ grantRuntimePermissionsLPw(setupPackage, PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(setupPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(setupPackage, SETTINGS_PERMISSIONS, userId);
+ }
+
+ // Phone
+ Intent dialerIntent = new Intent(Intent.ACTION_DIAL);
+ PackageParser.Package dialerPackage = getDefaultSystemHandlerActvityPackageLPr(
+ dialerIntent, userId);
+ if (dialerPackage != null
+ && doesPackageSupportRuntimePermissions(dialerPackage)) {
+ grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId);
+ }
+
+ // Camera
+ Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ PackageParser.Package cameraPackage = getDefaultSystemHandlerActvityPackageLPr(
+ cameraIntent, userId);
+ if (cameraPackage != null
+ && doesPackageSupportRuntimePermissions(cameraPackage)) {
+ grantRuntimePermissionsLPw(cameraPackage, CAMERA_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(cameraPackage, MICROPHONE_PERMISSIONS, userId);
+ }
+
+ // Messaging
+ Intent messagingIntent = new Intent(Intent.ACTION_MAIN);
+ messagingIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);
+ PackageParser.Package messagingPackage = getDefaultSystemHandlerActvityPackageLPr(
+ messagingIntent, userId);
+ if (messagingPackage != null
+ && doesPackageSupportRuntimePermissions(messagingPackage)) {
+ grantRuntimePermissionsLPw(messagingPackage, PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(messagingPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(messagingPackage, SMS_PERMISSIONS, userId);
+ }
+
+ // Calendar
+ Intent calendarIntent = new Intent(Intent.ACTION_MAIN);
+ calendarIntent.addCategory(Intent.CATEGORY_APP_CALENDAR);
+ PackageParser.Package calendarPackage = getDefaultSystemHandlerActvityPackageLPr(
+ calendarIntent, userId);
+ if (calendarPackage != null
+ && doesPackageSupportRuntimePermissions(calendarPackage)) {
+ grantRuntimePermissionsLPw(calendarPackage, CALENDAR_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(calendarPackage, CONTACTS_PERMISSIONS, userId);
+ }
+
+ // Contacts
+ Intent contactsIntent = new Intent(Intent.ACTION_MAIN);
+ contactsIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
+ PackageParser.Package contactsPackage = getDefaultSystemHandlerActvityPackageLPr(
+ contactsIntent, userId);
+ if (contactsPackage != null
+ && doesPackageSupportRuntimePermissions(contactsPackage)) {
+ grantRuntimePermissionsLPw(contactsPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(contactsPackage, PHONE_PERMISSIONS, userId);
+ }
+
+ // Maps
+ Intent mapsIntent = new Intent(Intent.ACTION_MAIN);
+ mapsIntent.addCategory(Intent.CATEGORY_APP_MAPS);
+ PackageParser.Package mapsPackage = getDefaultSystemHandlerActvityPackageLPr(
+ mapsIntent, userId);
+ if (mapsPackage != null
+ && doesPackageSupportRuntimePermissions(mapsPackage)) {
+ grantRuntimePermissionsLPw(mapsPackage, LOCATION_PERMISSIONS, userId);
+ }
+
+ // Email
+ Intent emailIntent = new Intent(Intent.ACTION_MAIN);
+ emailIntent.addCategory(Intent.CATEGORY_APP_EMAIL);
+ PackageParser.Package emailPackage = getDefaultSystemHandlerActvityPackageLPr(
+ emailIntent, userId);
+ if (emailPackage != null
+ && doesPackageSupportRuntimePermissions(emailPackage)) {
+ grantRuntimePermissionsLPw(emailPackage, CONTACTS_PERMISSIONS, userId);
+ }
+
+ // Browser
+ Intent browserIntent = new Intent(Intent.ACTION_MAIN);
+ browserIntent.addCategory(Intent.CATEGORY_APP_BROWSER);
+ PackageParser.Package browserPackage = getDefaultSystemHandlerActvityPackageLPr(
+ browserIntent, userId);
+ if (browserPackage != null
+ && doesPackageSupportRuntimePermissions(browserPackage)) {
+ grantRuntimePermissionsLPw(browserPackage, LOCATION_PERMISSIONS, userId);
+ }
+
+ // IME
+ if (imePackageNames != null) {
+ for (String imePackageName : imePackageNames) {
+ PackageParser.Package imePackage = getSystemPackageLPr(imePackageName);
+ if (imePackage != null
+ && doesPackageSupportRuntimePermissions(imePackage)) {
+ grantRuntimePermissionsLPw(imePackage, CONTACTS_PERMISSIONS, userId);
+ }
+ }
+ }
+
+ // Voice interaction
+ if (voiceInteractPackageNames != null) {
+ for (String voiceInteractPackageName : voiceInteractPackageNames) {
+ PackageParser.Package voiceInteractPackage = getSystemPackageLPr(
+ voiceInteractPackageName);
+ if (voiceInteractPackage != null
+ && doesPackageSupportRuntimePermissions(voiceInteractPackage)) {
+ grantRuntimePermissionsLPw(voiceInteractPackage,
+ CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(voiceInteractPackage,
+ CALENDAR_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(voiceInteractPackage,
+ MICROPHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(voiceInteractPackage,
+ PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(voiceInteractPackage,
+ SMS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(voiceInteractPackage,
+ LOCATION_PERMISSIONS, userId);
+ }
+ }
+ }
+
+ // Location
+ if (locationPackageNames != null) {
+ for (String packageName : locationPackageNames) {
+ PackageParser.Package locationPackage = getSystemPackageLPr(packageName);
+ if (locationPackage != null
+ && doesPackageSupportRuntimePermissions(locationPackage)) {
+ grantRuntimePermissionsLPw(locationPackage, CONTACTS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, CALENDAR_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, MICROPHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, PHONE_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, SMS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, LOCATION_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, CAMERA_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, SENSORS_PERMISSIONS, userId);
+ grantRuntimePermissionsLPw(locationPackage, STORAGE_PERMISSIONS, userId);
+ }
+ }
+ }
+ }
+ }
+
+ private List<PackageParser.Package> getPrivilegedHandlerReceiverPackagesLPr(
+ Intent intent, int userId) {
+ List<ResolveInfo> handlers = mService.queryIntentReceivers(
+ intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()),
+ 0, userId);
+ return getPrivilegedPackages(handlers);
+ }
+
+ private List<PackageParser.Package> getPrivilegedHandlerActivityPackagesLPr(
+ Intent intent, int userId) {
+ List<ResolveInfo> handlers = mService.queryIntentActivities(
+ intent, intent.resolveTypeIfNeeded(mService.mContext.getContentResolver()),
+ 0, userId);
+ return getPrivilegedPackages(handlers);
+ }
+
+ private List<PackageParser.Package> getPrivilegedPackages(List<ResolveInfo> resolveInfos) {
+ List<PackageParser.Package> handlerPackages = new ArrayList<>();
+ final int handlerCount = resolveInfos.size();
+ for (int i = 0; i < handlerCount; i++) {
+ ResolveInfo handler = resolveInfos.get(i);
+ PackageParser.Package handlerPackage = getPrivilegedPackageLPr(
+ handler.activityInfo.packageName);
+ if (handlerPackage != null) {
+ handlerPackages.add(handlerPackage);
+ }
+ }
+ return handlerPackages;
+ }
+
+ private PackageParser.Package getDefaultSystemHandlerActvityPackageLPr(
+ Intent intent, int userId) {
+ List<ResolveInfo> handlers = mService.queryIntentActivities(intent, null, 0, userId);
+ final int handlerCount = handlers.size();
+ for (int i = 0; i < handlerCount; i++) {
+ ResolveInfo handler = handlers.get(i);
+ // TODO: This is a temporary hack to figure out the setup app.
+ PackageParser.Package handlerPackage = getSystemPackageLPr(
+ handler.activityInfo.packageName);
+ if (handlerPackage != null) {
+ return handlerPackage;
+ }
+ }
+ return null;
+ }
+
+ private PackageParser.Package getSystemPackageLPr(String packageName) {
+ PackageParser.Package pkg = mService.mPackages.get(packageName);
+ if (pkg != null && pkg.isSystemApp()) {
+ return !isSysComponentOrPersistentPrivApp(pkg) ? pkg : null;
+ }
+ return null;
+ }
+
+ private PackageParser.Package getPrivilegedPackageLPr(String packageName) {
+ PackageParser.Package pkg = mService.mPackages.get(packageName);
+ if (pkg != null && pkg.applicationInfo.isPrivilegedApp()) {
+ return !isSysComponentOrPersistentPrivApp(pkg) ? pkg : null;
+ }
+ return null;
+ }
+
+ private void grantRuntimePermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
+ int userId) {
+ List<String> requestedPermissions = pkg.requestedPermissions;
+
+ if (pkg.isUpdatedSystemApp()) {
+ PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
+ if (sysPs != null) {
+ requestedPermissions = sysPs.pkg.requestedPermissions;
+ }
+ }
+
+ final int permissionCount = requestedPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ String permission = requestedPermissions.get(i);
+ if (permissions.contains(permission)) {
+ final int flags = mService.getPermissionFlags(permission, pkg.packageName, userId);
+
+ // If any flags are set to the permission, then it is either set in
+ // its current state by the system or device/profile owner or the user.
+ // In all these cases we do not want to clobber the current state.
+ if (flags == 0) {
+ mService.grantRuntimePermission(pkg.packageName, permission, userId);
+ if (DEBUG) {
+ Log.i(TAG, "Granted " + permission + " to default handler "
+ + pkg.packageName);
+ }
+ }
+ }
+ }
+ }
+
+ private void grantInstallPermissionsLPw(PackageParser.Package pkg, Set<String> permissions,
+ int userId) {
+ List<String> requestedPermissions = pkg.requestedPermissions;
+
+ if (pkg.isUpdatedSystemApp()) {
+ PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
+ if (sysPs != null) {
+ requestedPermissions = sysPs.pkg.requestedPermissions;
+ }
+ }
+
+ final int permissionCount = requestedPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ String permission = requestedPermissions.get(i);
+ if (permissions.contains(permission)) {
+ final int flags = mService.getPermissionFlags(permission, pkg.packageName, userId);
+
+ // If any flags are set to the permission, then it is either set in
+ // its current state by the system or device/profile owner or the user.
+ // In all these cases we do not want to clobber the current state.
+ if (flags == 0) {
+ mService.grantInstallPermissionLPw(permission, pkg);
+ if (DEBUG) {
+ Log.i(TAG, "Granted install " + permission + " to " + pkg.packageName);
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean isSysComponentOrPersistentPrivApp(PackageParser.Package pkg) {
+ return UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID
+ || ((pkg.applicationInfo.privateFlags
+ & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0
+ && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0);
+ }
+
+ private static boolean doesPackageSupportRuntimePermissions(PackageParser.Package pkg) {
+ return pkg.applicationInfo.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5b7dd70..91aec60 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -55,7 +55,6 @@
import static android.content.pm.PackageManager.MOVE_FAILED_OPERATION_PENDING;
import static android.content.pm.PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
import static android.content.pm.PackageParser.isApkFile;
-import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static android.system.OsConstants.O_CREAT;
@@ -111,6 +110,7 @@
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.ActivityIntentInfo;
import android.content.pm.PackageParser.PackageLite;
@@ -281,6 +281,8 @@
private static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
+ static final boolean CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE = Build.IS_DEBUGGABLE;
+
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
private static final int NFC_UID = Process.NFC_UID;
@@ -551,6 +553,9 @@
final SparseArray<IntentFilterVerificationState> mIntentFilterVerificationStates
= new SparseArray<IntentFilterVerificationState>();
+ final DefaultPermissionGrantPolicy mDefaultPermissionPolicy =
+ new DefaultPermissionGrantPolicy(this);
+
private interface IntentFilterVerifier<T extends IntentFilter> {
boolean addOneIntentFilterVerification(int verifierId, int userId, int verificationId,
T filter, String packageName);
@@ -2194,6 +2199,9 @@
// are all flushed. Not really needed, but keeps things nice and
// tidy.
Runtime.getRuntime().gc();
+
+ // Expose private service for system components to use.
+ LocalServices.addService(PackageManagerInternal.class, new PackageManagerInternalImpl());
}
@Override
@@ -3150,7 +3158,7 @@
}
@Override
- public void grantRuntimePermission(String packageName, String name, int userId) {
+ public void grantRuntimePermission(String packageName, String name, final int userId) {
if (!sUserManager.exists(userId)) {
Log.e(TAG, "No such user:" + userId);
return;
@@ -3163,7 +3171,6 @@
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"grantRuntimePermission");
- boolean gidsChanged = false;
final SettingBase sb;
synchronized (mPackages) {
@@ -3199,7 +3206,12 @@
}
case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
- gidsChanged = true;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
+ }
+ });
} break;
}
@@ -3208,10 +3220,6 @@
// Not critical if that is lost - app has to request again.
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
}
-
- if (gidsChanged) {
- killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
- }
}
@Override
@@ -3318,15 +3326,14 @@
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"updatePermissionFlags");
- // Only the system can change policy flags.
+ // Only the system can change policy and system fixed flags.
if (getCallingUid() != Process.SYSTEM_UID) {
flagMask &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
flagValues &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
- }
- // Only the package manager can change system flags.
- flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
- flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+ flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+ flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
+ }
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
@@ -3404,6 +3411,21 @@
return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
}
+ void grantInstallPermissionLPw(String permission, PackageParser.Package pkg) {
+ BasePermission bp = mSettings.mPermissions.get(permission);
+ if (bp == null) {
+ throw new SecurityException("Missing " + permission + " permission");
+ }
+
+ SettingBase sb = (SettingBase) pkg.mExtras;
+ PermissionsState permissionsState = sb.getPermissionsState();
+
+ if (permissionsState.grantInstallPermission(bp) !=
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ scheduleWriteSettingsLocked();
+ }
+ }
+
@Override
public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
mContext.enforceCallingOrSelfPermission(
@@ -7748,7 +7770,6 @@
final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
- int[] upgradeUserIds = EMPTY_INT_ARRAY;
int[] changedRuntimePermissionUserIds = EMPTY_INT_ARRAY;
boolean changedInstallPermission = false;
@@ -7805,32 +7826,11 @@
if (pkg.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL_LEGACY;
- } else if (ps.isSystem()) {
- final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds();
- if (origPermissions.hasInstallPermission(bp.name)) {
- // If a system app had an install permission, then the app was
- // upgraded and we grant the permissions as runtime to all users.
- grant = GRANT_UPGRADE;
- upgradeUserIds = currentUserIds;
- } else if (!Arrays.equals(updatedUserIds, currentUserIds)) {
- // If users changed since the last permissions update for a
- // system app, we grant the permission as runtime to the new users.
- grant = GRANT_UPGRADE;
- upgradeUserIds = currentUserIds;
- for (int userId : updatedUserIds) {
- upgradeUserIds = ArrayUtils.removeInt(upgradeUserIds, userId);
- }
- } else {
- // Otherwise, we grant the permission as runtime if the app
- // already had it, i.e. we preserve runtime permissions.
- grant = GRANT_RUNTIME;
- }
} else if (origPermissions.hasInstallPermission(bp.name)) {
// For legacy apps that became modern, install becomes runtime.
grant = GRANT_UPGRADE;
- upgradeUserIds = currentUserIds;
- } else if (replace) {
- // For upgraded modern apps keep runtime permissions unchanged.
+ } else {
+ // For modern apps keep runtime permissions unchanged.
grant = GRANT_RUNTIME;
}
} break;
@@ -7865,7 +7865,7 @@
switch (grant) {
case GRANT_INSTALL: {
// Revoke this as runtime permission to handle the case of
- // a runtime permssion being downgraded to an install one.
+ // a runtime permission being downgraded to an install one.
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (origPermissions.getRuntimePermissionState(
bp.name, userId) != null) {
@@ -7896,26 +7896,20 @@
case GRANT_RUNTIME: {
// Grant previously granted runtime permissions.
for (int userId : UserManagerService.getInstance().getUserIds()) {
+ PermissionState permissionState = origPermissions
+ .getRuntimePermissionState(bp.name, userId);
+ final int flags = permissionState != null
+ ? permissionState.getFlags() : 0;
if (origPermissions.hasRuntimePermission(bp.name, userId)) {
- PermissionState permissionState = origPermissions
- .getRuntimePermissionState(bp.name, userId);
- final int flags = permissionState.getFlags();
if (permissionsState.grantRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_FAILURE) {
// If we cannot put the permission as it was, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
- } else {
- // System components not only get the permissions but
- // they are also fixed, so nothing can change that.
- final int newFlags = !isSystemComponentOrPersistentPrivApp(pkg)
- ? flags
- : flags | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
- // Propagate the permission flags.
- permissionsState.updatePermissionFlags(bp, userId,
- newFlags, newFlags);
}
}
+ // Propagate the permission flags.
+ permissionsState.updatePermissionFlags(bp, userId, flags, flags);
}
} break;
@@ -7925,25 +7919,23 @@
.getInstallPermissionState(bp.name);
final int flags = permissionState != null ? permissionState.getFlags() : 0;
- origPermissions.revokeInstallPermission(bp);
- // We will be transferring the permission flags, so clear them.
- origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS, 0);
+ if (origPermissions.revokeInstallPermission(bp)
+ != PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ // We will be transferring the permission flags, so clear them.
+ origPermissions.updatePermissionFlags(bp, UserHandle.USER_ALL,
+ PackageManager.MASK_PERMISSION_FLAGS, 0);
+ changedInstallPermission = true;
+ }
// If the permission is not to be promoted to runtime we ignore it and
// also its other flags as they are not applicable to install permissions.
if ((flags & PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRADE) == 0) {
- for (int userId : upgradeUserIds) {
+ for (int userId : currentUserIds) {
if (permissionsState.grantRuntimePermission(bp, userId) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
- // System components not only get the permissions but
- // they are also fixed so nothing can change that.
- final int newFlags = !isSystemComponentOrPersistentPrivApp(pkg)
- ? flags
- : flags | PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
// Transfer the permission flags.
permissionsState.updatePermissionFlags(bp, userId,
- newFlags, newFlags);
+ flags, flags);
// If we granted the permission, we have to write.
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
@@ -7995,8 +7987,6 @@
ps.installPermissionsFixed = true;
}
- ps.setPermissionsUpdatedForUserIds(currentUserIds);
-
// Persist the runtime permissions state for users with changes.
for (int userId : changedRuntimePermissionUserIds) {
mSettings.writeRuntimePermissionsForUserLPr(userId, true);
@@ -11875,13 +11865,6 @@
}
}
- private boolean isSystemComponentOrPersistentPrivApp(PackageParser.Package pkg) {
- return UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID
- || ((pkg.applicationInfo.privateFlags
- & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0
- && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0);
- }
-
private static boolean isMultiArch(PackageSetting ps) {
return (ps.pkgFlags & ApplicationInfo.FLAG_MULTIARCH) != 0;
}
@@ -13674,6 +13657,14 @@
}
sUserManager.systemReady();
+ // If we upgraded grant all default permissions before kicking off.
+ if (isFirstBoot()) {
+ updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
+ for (int userId : UserManagerService.getInstance().getUserIds()) {
+ mDefaultPermissionPolicy.grantDefaultPermissions(userId);
+ }
+ }
+
// Kick off any messages waiting for system ready
if (mPostSystemReadyMessages != null) {
for (Message msg : mPostSystemReadyMessages) {
@@ -15061,9 +15052,16 @@
}
}
- void newUserCreatedLILPw(int userHandle) {
- // Adding a user requires updating runtime permissions for system apps.
- updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
+ void newUserCreatedLILPw(final int userHandle) {
+ // We cannot grant the default permissions with a lock held as
+ // we query providers from other components for default handlers
+ // such as enabled IMEs, etc.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mDefaultPermissionPolicy.grantDefaultPermissions(userHandle);
+ }
+ });
}
@Override
@@ -15415,4 +15413,27 @@
}
}
}
+
+ private class PackageManagerInternalImpl extends PackageManagerInternal {
+ @Override
+ public void setLocationPackagesProvider(PackagesProvider provider) {
+ synchronized (mPackages) {
+ mDefaultPermissionPolicy.setLocationPackagesProviderLPw(provider);
+ }
+ }
+
+ @Override
+ public void setImePackagesProvider(PackagesProvider provider) {
+ synchronized (mPackages) {
+ mDefaultPermissionPolicy.setImePackagesProviderLPr(provider);
+ }
+ }
+
+ @Override
+ public void setVoiceInteractionPackagesProvider(PackagesProvider provider) {
+ synchronized (mPackages) {
+ mDefaultPermissionPolicy.setVoiceInteractionPackagesProviderLPw(provider);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index f62c00c..6f46f69 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -24,7 +24,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageUserState;
import android.os.storage.VolumeInfo;
-import android.text.TextUtils;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -223,7 +222,6 @@
* Make a shallow copy of this package settings.
*/
public void copyFrom(PackageSettingBase base) {
- setPermissionsUpdatedForUserIds(base.getPermissionsUpdatedForUserIds());
mPermissionsState.copyFrom(base.mPermissionsState);
primaryCpuAbiString = base.primaryCpuAbiString;
secondaryCpuAbiString = base.secondaryCpuAbiString;
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index c35258a..5cf92a9 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -18,16 +18,11 @@
import android.content.pm.ApplicationInfo;
-import java.util.Arrays;
-
abstract class SettingBase {
- private static final int[] USERS_NONE = new int[0];
-
int pkgFlags;
int pkgPrivateFlags;
protected final PermissionsState mPermissionsState;
- private int[] mPermissionsUpdatedForUserIds = USERS_NONE;
SettingBase(int pkgFlags, int pkgPrivateFlags) {
setFlags(pkgFlags);
@@ -39,29 +34,12 @@
pkgFlags = base.pkgFlags;
pkgPrivateFlags = base.pkgPrivateFlags;
mPermissionsState = new PermissionsState(base.mPermissionsState);
- setPermissionsUpdatedForUserIds(base.mPermissionsUpdatedForUserIds);
}
public PermissionsState getPermissionsState() {
return mPermissionsState;
}
- public int[] getPermissionsUpdatedForUserIds() {
- return mPermissionsUpdatedForUserIds;
- }
-
- public void setPermissionsUpdatedForUserIds(int[] userIds) {
- if (Arrays.equals(mPermissionsUpdatedForUserIds, userIds)) {
- return;
- }
-
- if (userIds == USERS_NONE) {
- mPermissionsUpdatedForUserIds = userIds;
- } else {
- mPermissionsUpdatedForUserIds = Arrays.copyOf(userIds, userIds.length);
- }
- }
-
void setFlags(int pkgFlags) {
this.pkgFlags = pkgFlags
& (ApplicationInfo.FLAG_SYSTEM
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index cd50946..c43bd60 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1139,17 +1139,6 @@
return new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME);
}
- boolean isFirstRuntimePermissionsBoot() {
- return !getUserRuntimePermissionsFile(UserHandle.USER_OWNER).exists();
- }
-
- void deleteRuntimePermissionsFiles() {
- for (int userId : UserManagerService.getInstance().getUserIds()) {
- File file = getUserRuntimePermissionsFile(userId);
- file.delete();
- }
- }
-
private File getUserPackagesStateBackupFile(int userId) {
return new File(Environment.getUserSystemDirectory(userId),
"package-restrictions-backup.xml");
@@ -2466,6 +2455,22 @@
} catch (NumberFormatException e) {
}
mFingerprint = parser.getAttributeValue(null, "fingerprint");
+
+ // If the build is setup to drop runtime permissions
+ // on update drop the files before loading them.
+ if (PackageManagerService.CLEAR_RUNTIME_PERMISSIONS_ON_UPGRADE) {
+ if (!Build.FINGERPRINT.equals(mFingerprint)) {
+ if (users == null) {
+ mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
+ UserHandle.USER_OWNER);
+ } else {
+ for (UserInfo user : users) {
+ mRuntimePermissionsPersistence.deleteUserRuntimePermissionsFile(
+ user.id);
+ }
+ }
+ }
+ }
} else if (tagName.equals("database-version")) {
mInternalDatabaseVersion = mExternalDatabaseVersion = 0;
try {
@@ -2554,15 +2559,21 @@
} else {
if (users == null) {
readPackageRestrictionsLPr(0);
- mRuntimePermissionsPersistence.readStateForUserSyncLPr(UserHandle.USER_OWNER);
} else {
for (UserInfo user : users) {
readPackageRestrictionsLPr(user.id);
- mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
}
}
}
+ if (users == null) {
+ mRuntimePermissionsPersistence.readStateForUserSyncLPr(UserHandle.USER_OWNER);
+ } else {
+ for (UserInfo user : users) {
+ mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
+ }
+ }
+
/*
* Make sure all the updated system packages have their shared users
* associated with them.
@@ -3056,18 +3067,6 @@
}
}
- // We keep track for which users we granted permissions to be able
- // to grant runtime permissions to system apps for newly appeared
- // users or newly appeared system apps. If we supported runtime
- // permissions during the previous boot, then we already granted
- // permissions for all device users. In such a case we set the users
- // for which we granted permissions to avoid clobbering of runtime
- // permissions we granted to system apps but the user revoked later.
- if (!isFirstRuntimePermissionsBoot()) {
- final int[] userIds = UserManagerService.getInstance().getUserIds();
- ps.setPermissionsUpdatedForUserIds(userIds);
- }
-
mDisabledSysPackages.put(name, ps);
}
@@ -3364,18 +3363,6 @@
XmlUtils.skipCurrentTag(parser);
}
}
-
- // We keep track for which users we granted permissions to be able
- // to grant runtime permissions to system apps for newly appeared
- // users or newly appeared system apps. If we supported runtime
- // permissions during the previous boot, then we already granted
- // permissions for all device users. In such a case we set the users
- // for which we granted permissions to avoid clobbering of runtime
- // permissions we granted to system apps but the user revoked later.
- if (!isFirstRuntimePermissionsBoot()) {
- final int[] userIds = UserManagerService.getInstance().getUserIds();
- packageSetting.setPermissionsUpdatedForUserIds(userIds);
- }
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -3493,18 +3480,6 @@
XmlUtils.skipCurrentTag(parser);
}
}
-
- // We keep track for which users we granted permissions to be able
- // to grant runtime permissions to system apps for newly appeared
- // users or newly appeared system apps. If we supported runtime
- // permissions during the previous boot, then we already granted
- // permissions for all device users. In such a case we set the users
- // for which we granted permissions to avoid clobbering of runtime
- // permissions we granted to system apps but the user revoked later.
- if (!isFirstRuntimePermissionsBoot()) {
- final int[] userIds = UserManagerService.getInstance().getUserIds();
- su.setPermissionsUpdatedForUserIds(userIds);
- }
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -4397,6 +4372,10 @@
}
}
+ public void deleteUserRuntimePermissionsFile(int userId) {
+ getUserRuntimePermissionsFile(userId).delete();
+ }
+
public void readStateForUserSyncLPr(int userId) {
File permissionsFile = getUserRuntimePermissionsFile(userId);
if (!permissionsFile.exists()) {
@@ -4489,22 +4468,12 @@
? Integer.parseInt(flagsStr, 16) : 0;
if (granted) {
- if (permissionsState.grantRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
- } else {
- permissionsState.updatePermissionFlags(bp, userId,
+ permissionsState.grantRuntimePermission(bp, userId);
+ permissionsState.updatePermissionFlags(bp, userId,
PackageManager.MASK_PERMISSION_FLAGS, flags);
-
- }
} else {
- if (permissionsState.revokeRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
- } else {
- permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS, flags);
- }
+ permissionsState.updatePermissionFlags(bp, userId,
+ PackageManager.MASK_PERMISSION_FLAGS, flags);
}
} break;
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index fafe44a..b68abab 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -26,6 +26,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
@@ -57,6 +58,7 @@
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.UiThread;
@@ -83,6 +85,21 @@
mDbHelper = new DatabaseHelper(context);
mSoundTriggerHelper = new SoundTriggerHelper(context);
mServiceStub = new VoiceInteractionManagerServiceStub();
+
+ PackageManagerInternal packageManagerInternal = LocalServices.getService(
+ PackageManagerInternal.class);
+ packageManagerInternal.setVoiceInteractionPackagesProvider(
+ new PackageManagerInternal.PackagesProvider() {
+ @Override
+ public String[] getPackages(int userId) {
+ mServiceStub.initForUser(userId);
+ ComponentName interactor = mServiceStub.getCurInteractor(userId);
+ if (interactor != null) {
+ return new String[] {interactor.getPackageName()};
+ }
+ return null;
+ }
+ });
}
@Override