Default permissions for carrier apps.

Grant permissions in the PHONE and LOCATION buckets to default carrier
apps as defined by the telephony stack. Provide a system API to grant
default permissions for carrier apps, as the set of apps may change
when a new SIM is inserted.

Since the phone process is separate from the system process, we need
to allow for binder calls to these APIs.

Also fix a log tag that is too long (android.util.Log drops messages
silently if the tag is > 23 characters).

Bug: 21696731
Change-Id: I98ca0c49c69f621f835ba57c1fd0505f2cec0d0d
diff --git a/Android.mk b/Android.mk
index e96a932..a02b326 100644
--- a/Android.mk
+++ b/Android.mk
@@ -142,6 +142,7 @@
 	core/java/android/content/pm/IPackageManager.aidl \
 	core/java/android/content/pm/IPackageMoveObserver.aidl \
 	core/java/android/content/pm/IPackageStatsObserver.aidl \
+	core/java/android/content/pm/IPackagesProvider.aidl \
 	core/java/android/content/pm/IOnPermissionsChangeListener.aidl \
 	core/java/android/database/IContentObserver.aidl \
 	core/java/android/hardware/ICameraService.aidl \
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 0c07bc3..dbbfce8 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -31,6 +31,7 @@
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IPackagesProvider;
 import android.content.pm.IOnPermissionsChangeListener;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.InstrumentationInfo;
@@ -299,18 +300,18 @@
      * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
      */
     int getComponentEnabledSetting(in ComponentName componentName, int userId);
-    
+
     /**
      * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
      */
     void setApplicationEnabledSetting(in String packageName, in int newState, int flags,
             int userId, String callingPackage);
-    
+
     /**
      * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
      */
     int getApplicationEnabledSetting(in String packageName, int userId);
-    
+
     /**
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
@@ -363,7 +364,7 @@
      */
      void freeStorage(in String volumeUuid, in long freeStorageSize,
              in IntentSender pi);
-     
+
     /**
      * Delete all the cache files in an applications cache directory
      * @param packageName The package name of the application whose cache
@@ -371,7 +372,7 @@
      * @param observer a callback used to notify when the deletion is finished.
      */
     void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer);
-    
+
     /**
      * Clear the user data directory of an application.
      * @param packageName The package name of the application whose cache
@@ -379,7 +380,7 @@
      * @param observer a callback used to notify when the operation is completed.
      */
     void clearApplicationUserData(in String packageName, IPackageDataObserver observer, int userId);
-    
+
    /**
      * Get package statistics including the code, data and cache size for
      * an already installed package
@@ -389,7 +390,7 @@
      * retrieval of information is complete.
      */
     void getPackageSizeInfo(in String packageName, int userHandle, IPackageStatsObserver observer);
-    
+
     /**
      * Get a list of shared libraries that are available on the
      * system.
@@ -403,7 +404,7 @@
     FeatureInfo[] getSystemAvailableFeatures();
 
     boolean hasSystemFeature(String name);
-    
+
     void enterSafeMode();
     boolean isSafeMode();
     void systemReady();
@@ -494,4 +495,7 @@
 
     void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
     void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+
+    void grantDefaultPermissions(int userId);
+    void setCarrierAppPackagesProvider(in IPackagesProvider provider);
 }
diff --git a/core/java/android/content/pm/IPackagesProvider.aidl b/core/java/android/content/pm/IPackagesProvider.aidl
new file mode 100644
index 0000000..7d76c88
--- /dev/null
+++ b/core/java/android/content/pm/IPackagesProvider.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+/** {@hide} */
+interface IPackagesProvider {
+    String[] getPackages(int userId);
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9ac1fdd..ea0c9d0 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1848,7 +1848,9 @@
          2. Pre-installed
          3. In the default state (enabled but not explicitly)
          And SubscriptionInfoUpdater undoes this and marks the app enabled when a SIM is inserted
-         that marks the app as carrier privileged. -->
+         that marks the app as carrier privileged. It also grants the app default permissions
+         for Phone and Location. As such, apps MUST only ever be added to this list if they
+         obtain user consent to access their location through other means. -->
     <string-array name="config_disabledUntilUsedPreinstalledCarrierApps" translatable="false" />
 
     <!-- The list of classes that should be added to the notification ranking pipline.
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index fe3103b..b168e92 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -45,7 +45,7 @@
  * have phone related permission by default.
  */
 final class DefaultPermissionGrantPolicy {
-    private static final String TAG = "DefaultPermissionGrantPolicy";
+    private static final String TAG = "DefaultPermGrantPolicy"; // must be <= 23 chars
     private static final boolean DEBUG = false;
 
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
@@ -133,6 +133,7 @@
     private PackagesProvider mImePackagesProvider;
     private PackagesProvider mLocationPackagesProvider;
     private PackagesProvider mVoiceInteractionPackagesProvider;
+    private PackagesProvider mCarrierAppPackagesProvider;
 
     public DefaultPermissionGrantPolicy(PackageManagerService service) {
         mService = service;
@@ -150,6 +151,10 @@
         mVoiceInteractionPackagesProvider = provider;
     }
 
+    public void setCarrierAppPackagesProviderLPw(PackagesProvider provider) {
+        mCarrierAppPackagesProvider = provider;
+    }
+
     public void grantDefaultPermissions(int userId) {
         grantPermissionsToSysComponentsAndPrivApps(userId);
         grantDefaultSystemHandlerPermissions(userId);
@@ -193,11 +198,13 @@
         final PackagesProvider imePackagesProvider;
         final PackagesProvider locationPackagesProvider;
         final PackagesProvider voiceInteractionPackagesProvider;
+        final PackagesProvider carrierAppPackagesProvider;
 
         synchronized (mService.mPackages) {
             imePackagesProvider = mImePackagesProvider;
             locationPackagesProvider = mLocationPackagesProvider;
             voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
+            carrierAppPackagesProvider = mCarrierAppPackagesProvider;
         }
 
         String[] imePackageNames = (imePackagesProvider != null)
@@ -206,6 +213,8 @@
                 ? voiceInteractionPackagesProvider.getPackages(userId) : null;
         String[] locationPackageNames = (locationPackagesProvider != null)
                 ? locationPackagesProvider.getPackages(userId) : null;
+        String[] carrierAppPackageNames = (carrierAppPackagesProvider != null)
+                ? carrierAppPackagesProvider.getPackages(userId) : null;
 
         synchronized (mService.mPackages) {
             // Installers
@@ -382,6 +391,18 @@
                     }
                 }
             }
+
+            // Carrier apps
+            if (carrierAppPackageNames != null) {
+                for (String packageName : carrierAppPackageNames) {
+                    PackageParser.Package carrierPackage = getSystemPackageLPr(packageName);
+                    if (carrierPackage != null
+                            && doesPackageSupportRuntimePermissions(carrierPackage)) {
+                        grantRuntimePermissionsLPw(carrierPackage, PHONE_PERMISSIONS, userId);
+                        grantRuntimePermissionsLPw(carrierPackage, LOCATION_PERMISSIONS, userId);
+                    }
+                }
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d7abad0..73c4962 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -100,6 +100,7 @@
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IPackagesProvider;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
@@ -253,14 +254,14 @@
 
 /**
  * Keep track of all those .apks everywhere.
- * 
+ *
  * This is very central to the platform's security; please run the unit
  * tests whenever making modifications here:
- * 
+ *
 mmm frameworks/base/tests/AndroidTests
 adb install -r -f out/target/product/passion/data/app/AndroidTests.apk
 adb shell am instrument -w -e class com.android.unit_tests.PackageManagerTests com.android.unit_tests/android.test.InstrumentationTestRunner
- * 
+ *
  * {@hide}
  */
 public class PackageManagerService extends IPackageManager.Stub {
@@ -508,7 +509,7 @@
     // Packages whose data we have transfered into another package, thus
     // should no longer exist.
     final ArraySet<String> mTransferedPackages = new ArraySet<String>();
-    
+
     // Broadcast actions that are only available to the system.
     final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>();
 
@@ -1072,7 +1073,7 @@
                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             }
         }
-        
+
         void doHandleMessage(Message msg) {
             switch (msg.what) {
                 case INIT_COPY: {
@@ -2485,7 +2486,7 @@
         }
         return out;
     }
-    
+
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
         String[] out = new String[names.length];
@@ -2555,7 +2556,7 @@
         pi.protectionLevel = bp.protectionLevel;
         return pi;
     }
-    
+
     @Override
     public PermissionInfo getPermissionInfo(String name, int flags) {
         // reader
@@ -3035,7 +3036,7 @@
         }
         return s1.equals(s2);
     }
-    
+
     static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
         if (pi1.icon != pi2.icon) return false;
         if (pi1.logo != pi2.logo) return false;
@@ -4155,7 +4156,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -4710,7 +4711,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -4761,7 +4762,7 @@
         ComponentName comp = intent.getComponent();
         if (comp == null) {
             if (intent.getSelector() != null) {
-                intent = intent.getSelector(); 
+                intent = intent.getSelector();
                 comp = intent.getComponent();
             }
         }
@@ -6188,7 +6189,7 @@
                                 + "): packages=" + suid.packages);
                 }
             }
-            
+
             // Check if we are renaming from an original package name.
             PackageSetting origPackage = null;
             String realName = null;
@@ -6208,7 +6209,7 @@
                         // it is not already done.
                         pkg.setPackageName(renamed);
                     }
-                    
+
                 } else {
                     for (int i=pkg.mOriginalPackages.size()-1; i>=0; i--) {
                         if ((origPackage = mSettings.peekPackageLPr(
@@ -6238,7 +6239,7 @@
                     }
                 }
             }
-            
+
             if (mTransferedPackages.contains(pkg.packageName)) {
                 Slog.w(TAG, "Package " + pkg.packageName
                         + " was transferred to another, but its .apk remains");
@@ -6263,24 +6264,24 @@
                 // looking up the package under its new name, so getPackageLP
                 // can take care of fiddling things correctly.
                 pkg.setPackageName(origPackage.name);
-                
+
                 // File a report about this.
                 String msg = "New package " + pkgSetting.realName
                         + " renamed to replace old package " + pkgSetting.name;
                 reportSettingsProblem(Log.WARN, msg);
-                
+
                 // Make a note of it.
                 mTransferedPackages.add(origPackage.name);
-                
+
                 // No longer need to retain this.
                 pkgSetting.origPackage = null;
             }
-            
+
             if (realName != null) {
                 // Make a note of it.
                 mTransferedPackages.add(pkg.packageName);
             }
-            
+
             if (mSettings.isDisabledSystemPackageLPr(pkg.packageName)) {
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
@@ -6396,7 +6397,7 @@
         }
 
         final String pkgName = pkg.packageName;
-        
+
         final long scanFileTime = scanFile.lastModified();
         final boolean forceDex = (scanFlags & SCAN_FORCE_DEX) != 0;
         pkg.applicationInfo.processName = fixProcessName(
@@ -8316,7 +8317,7 @@
                 PackageParser.ActivityIntentInfo info) {
             return packageName.equals(info.activity.owner.packageName);
         }
-        
+
         @Override
         protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
                 int match, int userId) {
@@ -8539,7 +8540,7 @@
                 PackageParser.ServiceIntentInfo info) {
             return packageName.equals(info.service.owner.packageName);
         }
-        
+
         @Override
         protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
                 int match, int userId) {
@@ -13943,7 +13944,7 @@
         boolean checkin = false;
 
         String packageName = null;
-        
+
         int opti = 0;
         while (opti < args.length) {
             String opt = args[opti];
@@ -15589,4 +15590,55 @@
             }
         }
     }
+
+    @Override
+    public void grantDefaultPermissions(final int userId) {
+        enforceSystemOrPhoneCaller("grantDefaultPermissions");
+        long token = Binder.clearCallingIdentity();
+        try {
+            // 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(userId);
+                }
+            });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    @Override
+    public void setCarrierAppPackagesProvider(final IPackagesProvider provider) {
+        enforceSystemOrPhoneCaller("setCarrierAppPackagesProvider");
+        long token = Binder.clearCallingIdentity();
+        try {
+            PackageManagerInternal.PackagesProvider wrapper =
+                    new PackageManagerInternal.PackagesProvider() {
+                @Override
+                public String[] getPackages(int userId) {
+                    try {
+                        return provider.getPackages(userId);
+                    } catch (RemoteException e) {
+                        return null;
+                    }
+                }
+            };
+            synchronized (mPackages) {
+                mDefaultPermissionPolicy.setCarrierAppPackagesProviderLPw(wrapper);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private static void enforceSystemOrPhoneCaller(String tag) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.PHONE_UID && callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "Cannot call " + tag + " from UID " + callingUid);
+        }
+    }
 }