Create DPM APIs for cross profile callerId

Contact information in the managed profile is shown
in the incoming call UI unless blocked using this API.

TODO: Actually plumb this into the caller-id logic.

Bug: 16301261
Change-Id: If03adc907d9558baa0a45a1833b857206b7bf96a
diff --git a/api/current.txt b/api/current.txt
index abf7ea2..213834f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5327,6 +5327,7 @@
     method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
     method public boolean getBlockUninstall(android.content.ComponentName, java.lang.String);
     method public boolean getCameraDisabled(android.content.ComponentName);
+    method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
     method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
@@ -5366,6 +5367,7 @@
     method public int setApplicationsBlocked(android.content.ComponentName, android.content.Intent, boolean);
     method public void setBlockUninstall(android.content.ComponentName, java.lang.String, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
+    method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
     method public void setGlobalSetting(android.content.ComponentName, java.lang.String, java.lang.String);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setLockTaskPackages(java.lang.String[]) throws java.lang.SecurityException;
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 4e7dac0..d3aa950 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2270,6 +2270,45 @@
     }
 
     /**
+     * Called by a profile owner to set whether caller-Id information from the managed
+     * profile will be shown for incoming calls.
+     *
+     * <p>The calling device admin must be a profile owner. If it is not, a
+     * security exception will be thrown.
+     *
+     * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param disabled If true caller-Id information in the managed profile is not displayed.
+     */
+    public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) {
+        if (mService != null) {
+            try {
+                mService.setCrossProfileCallerIdDisabled(who, disabled);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Determine whether or not caller-Id information has been disabled.
+     *
+     * <p>The calling device admin must be a profile owner. If it is not, a
+     * security exception will be thrown.
+     *
+     * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+     */
+    public boolean getCrossProfileCallerIdDisabled(ComponentName who) {
+        if (mService != null) {
+            try {
+                return mService.getCrossProfileCallerIdDisabled(who);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by the profile owner so that some intents sent in the managed profile can also be
      * resolved in the parent, or vice versa.
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d36497e..46b8755 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -161,4 +161,8 @@
 
     void setBlockUninstall(in ComponentName admin, in String packageName, boolean blockUninstall);
     boolean getBlockUninstall(in ComponentName admin, in String packageName);
+
+    void setCrossProfileCallerIdDisabled(in ComponentName who, boolean disabled);
+    boolean getCrossProfileCallerIdDisabled(in ComponentName who);
+    boolean getCrossProfileCallerIdDisabledForUser(int userId);
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 92d3d95..f051fce 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -252,6 +252,7 @@
     static class ActiveAdmin {
         private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
         private static final String TAG_DISABLE_CAMERA = "disable-camera";
+        private static final String TAG_DISABLE_CALLER_ID = "disable-caller-id";
         private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
         private static final String TAG_ACCOUNT_TYPE = "account-type";
         private static final String TAG_ENCRYPTION_REQUESTED = "encryption-requested";
@@ -319,6 +320,7 @@
 
         boolean encryptionRequested = false;
         boolean disableCamera = false;
+        boolean disableCallerId = false;
         Set<String> accountTypesWithManagementDisabled = new HashSet<String>();
 
         // TODO: review implementation decisions with frameworks team
@@ -431,6 +433,11 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(disableCamera));
                 out.endTag(null, TAG_DISABLE_CAMERA);
             }
+            if (disableCallerId) {
+                out.startTag(null, TAG_DISABLE_CALLER_ID);
+                out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId));
+                out.endTag(null, TAG_DISABLE_CALLER_ID);
+            }
             if (disabledKeyguardFeatures != DEF_KEYGUARD_FEATURES_DISABLED) {
                 out.startTag(null, TAG_DISABLE_KEYGUARD_FEATURES);
                 out.attribute(null, ATTR_VALUE, Integer.toString(disabledKeyguardFeatures));
@@ -513,6 +520,9 @@
                 } else if (TAG_DISABLE_CAMERA.equals(tag)) {
                     disableCamera = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
+                    disableCallerId = Boolean.parseBoolean(
+                            parser.getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_DISABLE_KEYGUARD_FEATURES.equals(tag)) {
                     disabledKeyguardFeatures = Integer.parseInt(
                             parser.getAttributeValue(null, ATTR_VALUE));
@@ -589,6 +599,8 @@
                     pw.println(encryptionRequested);
             pw.print(prefix); pw.print("disableCamera=");
                     pw.println(disableCamera);
+            pw.print(prefix); pw.print("disableCallerId=");
+                    pw.println(disableCallerId);
             pw.print(prefix); pw.print("disabledKeyguardFeatures=");
                     pw.println(disabledKeyguardFeatures);
         }
@@ -3274,6 +3286,25 @@
         return null;
     }
 
+    // Returns the active profile owner for this user or null if the current user has no
+    // profile owner.
+    private ActiveAdmin getProfileOwnerAdmin(int userHandle) {
+        String profileOwnerPackage = getProfileOwner(userHandle);
+        if (profileOwnerPackage == null) {
+            return null;
+        }
+
+        DevicePolicyData policy = getUserData(userHandle);
+        final int n = policy.mAdminList.size();
+        for (int i = 0; i < n; i++) {
+            ActiveAdmin admin = policy.mAdminList.get(i);
+            if (profileOwnerPackage.equals(admin.info.getPackageName())) {
+                return admin;
+            }
+        }
+        return null;
+    }
+
     @Override
     public String getProfileOwnerName(int userHandle) {
         if (!mHasFeature) {
@@ -3312,6 +3343,12 @@
         }
     }
 
+    private void enforceSystemProcess(String message) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException(message);
+        }
+    }
+
     private void enforceNotManagedProfile(int userHandle, String message) {
         if(isManagedProfile(userHandle)) {
             throw new SecurityException("You can not " + message + " for a managed profile. ");
@@ -3933,6 +3970,50 @@
         return false;
     }
 
+    @Override
+    public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) {
+        if (!mHasFeature) {
+            return;
+        }
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (admin.disableCallerId != disabled) {
+                admin.disableCallerId = disabled;
+                saveSettingsLocked(UserHandle.getCallingUserId());
+            }
+        }
+    }
+
+    @Override
+    public boolean getCrossProfileCallerIdDisabled(ComponentName who) {
+        if (!mHasFeature) {
+            return false;
+        }
+
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            return admin.disableCallerId;
+        }
+    }
+
+    @Override
+    public boolean getCrossProfileCallerIdDisabledForUser(int userId) {
+        enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
+        synchronized (this) {
+            ActiveAdmin admin = getProfileOwnerAdmin(userId);
+            return (admin != null) ? admin.disableCallerId : false;
+        }
+    }
+
     /**
      * Sets which packages may enter lock task mode.
      *