Grant permissions to headless system calendar/contacts sync adapters.

bug:21861781

Change-Id: I5f9905a23ba1b23e387adf2cea842172d34207b0
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index dbaba49..ea08956 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -39,6 +39,20 @@
     }
 
     /**
+     * Provider for package names.
+     */
+    public interface SyncAdapterPackagesProvider {
+
+        /**
+         * Gets the sync adapter packages for given authority and user.
+         * @param authority The authority.
+         * @param userId The user id.
+         * @return The package names.
+         */
+        public String[] getPackages(String authority, int userId);
+    }
+
+    /**
      * Sets the location provider packages provider.
      * @param provider The packages provider.
      */
@@ -69,6 +83,12 @@
     public abstract void setDialerAppPackagesProvider(PackagesProvider provider);
 
     /**
+     * Sets the sync adapter packages provider.
+     * @param provider The provider.
+     */
+    public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider);
+
+    /**
      * Requests granting of the default permissions to the current default SMS app.
      * @param packageName The default SMS package name.
      * @param userId The user for which to grant the permissions.
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 2c57833..c13401f 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -31,6 +31,7 @@
 import android.content.SyncRequest;
 import android.content.SyncStatusInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.database.IContentObserver;
 import android.database.sqlite.SQLiteException;
 import android.net.Uri;
@@ -46,6 +47,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseIntArray;
+import com.android.server.LocalServices;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -153,6 +155,18 @@
     /*package*/ ContentService(Context context, boolean factoryTest) {
         mContext = context;
         mFactoryTest = factoryTest;
+
+        // Let the package manager query for the sync adapters for a given authority
+        // as we grant default permissions to sync adapters for specifix authorities.
+        PackageManagerInternal packageManagerInternal = LocalServices.getService(
+                PackageManagerInternal.class);
+        packageManagerInternal.setSyncAdapterPackagesprovider(
+                new PackageManagerInternal.SyncAdapterPackagesProvider() {
+            @Override
+            public String[] getPackages(String authority, int userId) {
+                return getSyncAdapterPackagesForAuthorityAsUser(authority, userId);
+            }
+        });
     }
 
     public void systemReady() {
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index d71904e..cb7d932 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -23,6 +23,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal.PackagesProvider;
+import android.content.pm.PackageManagerInternal.SyncAdapterPackagesProvider;
 import android.content.pm.PackageParser;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
@@ -146,6 +147,7 @@
     private PackagesProvider mVoiceInteractionPackagesProvider;
     private PackagesProvider mSmsAppPackagesProvider;
     private PackagesProvider mDialerAppPackagesProvider;
+    private SyncAdapterPackagesProvider mSyncAdapterPackagesProvider;
 
     public DefaultPermissionGrantPolicy(PackageManagerService service) {
         mService = service;
@@ -171,6 +173,10 @@
         mDialerAppPackagesProvider = provider;
     }
 
+    public void setSyncAdapterPackagesProviderrLPw(SyncAdapterPackagesProvider provider) {
+        mSyncAdapterPackagesProvider = provider;
+    }
+
     public void grantDefaultPermissions(int userId) {
         grantPermissionsToSysComponentsAndPrivApps(userId);
         grantDefaultSystemHandlerPermissions(userId);
@@ -216,6 +222,7 @@
         final PackagesProvider voiceInteractionPackagesProvider;
         final PackagesProvider smsAppPackagesProvider;
         final PackagesProvider dialerAppPackagesProvider;
+        final SyncAdapterPackagesProvider syncAdapterPackagesProvider;
 
         synchronized (mService.mPackages) {
             imePackagesProvider = mImePackagesProvider;
@@ -223,6 +230,7 @@
             voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
             smsAppPackagesProvider = mSmsAppPackagesProvider;
             dialerAppPackagesProvider = mDialerAppPackagesProvider;
+            syncAdapterPackagesProvider = mSyncAdapterPackagesProvider;
         }
 
         String[] imePackageNames = (imePackagesProvider != null)
@@ -235,6 +243,10 @@
                 ? smsAppPackagesProvider.getPackages(userId) : null;
         String[] dialerAppPackageNames = (dialerAppPackagesProvider != null)
                 ? dialerAppPackagesProvider.getPackages(userId) : null;
+        String[] contactsSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
+                syncAdapterPackagesProvider.getPackages(ContactsContract.AUTHORITY, userId) : null;
+        String[] calendarSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
+                syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;
 
         synchronized (mService.mPackages) {
             // Installers
@@ -304,14 +316,14 @@
             PackageParser.Package mediaStorePackage = getDefaultProviderAuthorityPackageLPr(
                     MediaStore.AUTHORITY, userId);
             if (mediaStorePackage != null) {
-                grantRuntimePermissionsLPw(mediaStorePackage, STORAGE_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(mediaStorePackage, STORAGE_PERMISSIONS, true, userId);
             }
 
             // Downloads provider
             PackageParser.Package downloadsPackage = getDefaultProviderAuthorityPackageLPr(
                     "downloads", userId);
             if (downloadsPackage != null) {
-                grantRuntimePermissionsLPw(downloadsPackage, STORAGE_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(downloadsPackage, STORAGE_PERMISSIONS, true, userId);
             }
 
             // Downloads UI
@@ -320,7 +332,7 @@
                     downloadsUiIntent, userId);
             if (downloadsUiPackage != null
                     && doesPackageSupportRuntimePermissions(downloadsUiPackage)) {
-                grantRuntimePermissionsLPw(downloadsUiPackage, STORAGE_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(downloadsUiPackage, STORAGE_PERMISSIONS, true, userId);
             }
 
             // Storage provider
@@ -360,11 +372,24 @@
                     CalendarContract.AUTHORITY, userId);
             if (calendarProviderPackage != null) {
                 grantRuntimePermissionsLPw(calendarProviderPackage, CONTACTS_PERMISSIONS, userId);
-                grantRuntimePermissionsLPw(calendarProviderPackage, CALENDAR_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(calendarProviderPackage, CALENDAR_PERMISSIONS,
+                        true, userId);
                 grantRuntimePermissionsLPw(calendarProviderPackage, ACCOUNTS_PERMISSIONS, userId);
                 grantRuntimePermissionsLPw(calendarProviderPackage, STORAGE_PERMISSIONS, userId);
             }
 
+            // Calendar provider sync adapters
+            List<PackageParser.Package> calendarSyncAdapters =
+                    getHeadlessSyncAdapterPackagesLPr(calendarSyncAdapterPackages,
+                            userId);
+            final int calendarSyncAdapterCount = calendarSyncAdapters.size();
+            for (int i = 0; i < calendarSyncAdapterCount; i++) {
+                PackageParser.Package calendarSyncAdapter = calendarSyncAdapters.get(i);
+                if (doesPackageSupportRuntimePermissions(calendarSyncAdapter)) {
+                    grantRuntimePermissionsLPw(calendarSyncAdapter, CALENDAR_PERMISSIONS, userId);
+                }
+            }
+
             // Contacts
             Intent contactsIntent = new Intent(Intent.ACTION_MAIN);
             contactsIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
@@ -377,11 +402,24 @@
                 grantRuntimePermissionsLPw(contactsPackage, ACCOUNTS_PERMISSIONS, userId);
             }
 
+            // Contacts provider sync adapters
+            List<PackageParser.Package> contactsSyncAdapters =
+                    getHeadlessSyncAdapterPackagesLPr(contactsSyncAdapterPackages,
+                            userId);
+            final int contactsSyncAdapterCount = contactsSyncAdapters.size();
+            for (int i = 0; i < contactsSyncAdapterCount; i++) {
+                PackageParser.Package contactsSyncAdapter = contactsSyncAdapters.get(i);
+                if (doesPackageSupportRuntimePermissions(contactsSyncAdapter)) {
+                    grantRuntimePermissionsLPw(contactsSyncAdapter, CONTACTS_PERMISSIONS, userId);
+                }
+            }
+
             // Contacts provider
             PackageParser.Package contactsProviderPackage = getDefaultProviderAuthorityPackageLPr(
                     ContactsContract.AUTHORITY, userId);
             if (contactsProviderPackage != null) {
-                grantRuntimePermissionsLPw(contactsProviderPackage, CONTACTS_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(contactsProviderPackage, CONTACTS_PERMISSIONS,
+                        true, userId);
                 grantRuntimePermissionsLPw(contactsProviderPackage, ACCOUNTS_PERMISSIONS, userId);
                 grantRuntimePermissionsLPw(contactsProviderPackage, STORAGE_PERMISSIONS, userId);
             }
@@ -478,7 +516,8 @@
                         grantRuntimePermissionsLPw(locationPackage, MICROPHONE_PERMISSIONS, userId);
                         grantRuntimePermissionsLPw(locationPackage, PHONE_PERMISSIONS, userId);
                         grantRuntimePermissionsLPw(locationPackage, SMS_PERMISSIONS, userId);
-                        grantRuntimePermissionsLPw(locationPackage, LOCATION_PERMISSIONS, userId);
+                        grantRuntimePermissionsLPw(locationPackage, LOCATION_PERMISSIONS,
+                                true, userId);
                         grantRuntimePermissionsLPw(locationPackage, CAMERA_PERMISSIONS, userId);
                         grantRuntimePermissionsLPw(locationPackage, SENSORS_PERMISSIONS, userId);
                         grantRuntimePermissionsLPw(locationPackage, STORAGE_PERMISSIONS, userId);
@@ -603,6 +642,31 @@
         return null;
     }
 
+    private List<PackageParser.Package> getHeadlessSyncAdapterPackagesLPr(
+            String[] syncAdapterPackageNames, int userId) {
+        List<PackageParser.Package> syncAdapterPackages = new ArrayList<>();
+
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+
+        for (String syncAdapterPackageName : syncAdapterPackageNames) {
+            homeIntent.setPackage(syncAdapterPackageName);
+
+            List<ResolveInfo> homeActivities = mService.queryIntentActivities(homeIntent,
+                    homeIntent.resolveType(mService.mContext.getContentResolver()), 0, userId);
+            if (!homeActivities.isEmpty()) {
+                continue;
+            }
+
+            PackageParser.Package syncAdapterPackage = getSystemPackageLPr(syncAdapterPackageName);
+            if (syncAdapterPackage != null) {
+                syncAdapterPackages.add(syncAdapterPackage);
+            }
+        }
+
+        return syncAdapterPackages;
+    }
+
     private PackageParser.Package getDefaultProviderAuthorityPackageLPr(
             String authority, int userId) {
         ProviderInfo provider = mService.resolveContentProvider(authority, 0, userId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1385440..7d2cdbe 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -15970,6 +15970,13 @@
         }
 
         @Override
+        public void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider) {
+            synchronized (mPackages) {
+                mDefaultPermissionPolicy.setSyncAdapterPackagesProviderrLPw(provider);
+            }
+        }
+
+        @Override
         public void grantDefaultPermissionsToDefaultSmsApp(String packageName, int userId) {
             synchronized (mPackages) {
                 mDefaultPermissionPolicy.grantDefaultPermissionsToDefaultSmsAppLPr(