Add Bluetooth Contacts Sharing policy in DevicePolicyManager

Bug: 19990979

Change-Id: Ide9adf66eec5721e50573c03956a1b63b7e8b18b
diff --git a/api/current.txt b/api/current.txt
index 9713b3c..0b4c9ff 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5601,6 +5601,7 @@
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
     method public boolean getAutoTimeRequired();
+    method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName);
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
     method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
@@ -5650,6 +5651,7 @@
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setAutoTimeRequired(android.content.ComponentName, boolean);
+    method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index 131b7f6..56fd30d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5697,6 +5697,7 @@
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
     method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
     method public boolean getAutoTimeRequired();
+    method public boolean getBluetoothContactSharingDisabled(android.content.ComponentName);
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public java.lang.String getCertInstallerPackage(android.content.ComponentName) throws java.lang.SecurityException;
     method public boolean getCrossProfileCallerIdDisabled(android.content.ComponentName);
@@ -5754,6 +5755,7 @@
     method public boolean setApplicationHidden(android.content.ComponentName, java.lang.String, boolean);
     method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setAutoTimeRequired(android.content.ComponentName, boolean);
+    method public void setBluetoothContactSharingDisabled(android.content.ComponentName, boolean);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setCertInstallerPackage(android.content.ComponentName, java.lang.String) throws java.lang.SecurityException;
     method public void setCrossProfileCallerIdDisabled(android.content.ComponentName, boolean);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 68f4707..346e560 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3214,6 +3214,73 @@
     }
 
     /**
+     * Called by a profile owner of a managed profile to set whether bluetooth
+     * devices can access enterprise contacts.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a
+     * security exception will be thrown.
+     * <p>
+     * This API works on managed profile only.
+     *
+     * @param who Which {@link DeviceAdminReceiver} this request is associated
+     *            with.
+     * @param disabled If true, bluetooth devices cannot access enterprise
+     *            contacts.
+     */
+    public void setBluetoothContactSharingDisabled(ComponentName who, boolean disabled) {
+        if (mService != null) {
+            try {
+                mService.setBluetoothContactSharingDisabled(who, disabled);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile owner of a managed profile to determine whether or
+     * not Bluetooth devices cannot access enterprise contacts.
+     * <p>
+     * The calling device admin must be a profile owner. If it is not, a
+     * security exception will be thrown.
+     * <p>
+     * This API works on managed profile only.
+     *
+     * @param who Which {@link DeviceAdminReceiver} this request is associated
+     *            with.
+     */
+    public boolean getBluetoothContactSharingDisabled(ComponentName who) {
+        if (mService != null) {
+            try {
+                return mService.getBluetoothContactSharingDisabled(who);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Determine whether or not Bluetooth devices cannot access contacts.
+     * <p>
+     * This API works on managed profile UserHandle only.
+     *
+     * @param userHandle The user for whom to check the caller-id permission
+     * @hide
+     */
+    public boolean getBluetoothContactSharingDisabled(UserHandle userHandle) {
+        if (mService != null) {
+            try {
+                return mService.getBluetoothContactSharingDisabledForUser(userHandle
+                        .getIdentifier());
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return true;
+    }
+
+    /**
      * Called by the profile owner of a managed profile so that some intents sent in the managed
      * profile can also be resolved in the parent, or vice versa.
      * Only activity intents are supported.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index c68311e..10923fb 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -191,6 +191,10 @@
     boolean getCrossProfileCallerIdDisabledForUser(int userId);
     void startManagedQuickContact(String lookupKey, long contactId, in Intent originalIntent);
 
+    void setBluetoothContactSharingDisabled(in ComponentName who, boolean disabled);
+    boolean getBluetoothContactSharingDisabled(in ComponentName who);
+    boolean getBluetoothContactSharingDisabledForUser(int userId);
+
     void setTrustAgentConfiguration(in ComponentName admin, in ComponentName agent,
             in PersistableBundle args);
     List<PersistableBundle> getTrustAgentConfiguration(in ComponentName admin,
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bb3085e..4b2f6d4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -347,6 +347,8 @@
         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_BLUETOOTH_CONTACT_SHARING
+                = "disable-bt-contacts-sharing";
         private static final String TAG_DISABLE_SCREEN_CAPTURE = "disable-screen-capture";
         private static final String TAG_DISABLE_ACCOUNT_MANAGEMENT = "disable-account-management";
         private static final String TAG_REQUIRE_AUTO_TIME = "require_auto_time";
@@ -428,6 +430,7 @@
         boolean encryptionRequested = false;
         boolean disableCamera = false;
         boolean disableCallerId = false;
+        boolean disableBluetoothContactSharing = true;
         boolean disableScreenCapture = false; // Can only be set by a device/profile owner.
         boolean requireAutoTime = false; // Can only be set by a device owner.
 
@@ -569,6 +572,12 @@
                 out.attribute(null, ATTR_VALUE, Boolean.toString(disableCallerId));
                 out.endTag(null, TAG_DISABLE_CALLER_ID);
             }
+            if (disableBluetoothContactSharing) {
+                out.startTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
+                out.attribute(null, ATTR_VALUE,
+                        Boolean.toString(disableBluetoothContactSharing));
+                out.endTag(null, TAG_DISABLE_BLUETOOTH_CONTACT_SHARING);
+            }
             if (disableScreenCapture) {
                 out.startTag(null, TAG_DISABLE_SCREEN_CAPTURE);
                 out.attribute(null, ATTR_VALUE, Boolean.toString(disableScreenCapture));
@@ -714,6 +723,9 @@
                 } else if (TAG_DISABLE_CALLER_ID.equals(tag)) {
                     disableCallerId = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_DISABLE_BLUETOOTH_CONTACT_SHARING.equals(tag)) {
+                    disableBluetoothContactSharing = Boolean.parseBoolean(parser
+                            .getAttributeValue(null, ATTR_VALUE));
                 } else if (TAG_DISABLE_SCREEN_CAPTURE.equals(tag)) {
                     disableScreenCapture = Boolean.parseBoolean(
                             parser.getAttributeValue(null, ATTR_VALUE));
@@ -904,6 +916,8 @@
                     pw.println(disableCamera);
             pw.print(prefix); pw.print("disableCallerId=");
                     pw.println(disableCallerId);
+            pw.print(prefix); pw.print("disableBluetoothContactSharing=");
+                    pw.println(disableBluetoothContactSharing);
             pw.print(prefix); pw.print("disableScreenCapture=");
                     pw.println(disableScreenCapture);
             pw.print(prefix); pw.print("requireAutoTime=");
@@ -5517,6 +5531,46 @@
         return -1;
     }
 
+    @Override
+    public void setBluetoothContactSharingDisabled(ComponentName who, boolean disabled) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (admin.disableBluetoothContactSharing != disabled) {
+                admin.disableBluetoothContactSharing = disabled;
+                saveSettingsLocked(UserHandle.getCallingUserId());
+            }
+        }
+    }
+
+    @Override
+    public boolean getBluetoothContactSharingDisabled(ComponentName who) {
+        if (!mHasFeature) {
+            return false;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        synchronized (this) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            return admin.disableBluetoothContactSharing;
+        }
+    }
+
+    @Override
+    public boolean getBluetoothContactSharingDisabledForUser(int userId) {
+        // TODO: Should there be a check to make sure this relationship is
+        // within a profile group?
+        // enforceSystemProcess("getCrossProfileCallerIdDisabled can only be called by system");
+        synchronized (this) {
+            ActiveAdmin admin = getProfileOwnerAdmin(userId);
+            return (admin != null) ? admin.disableBluetoothContactSharing : false;
+        }
+    }
+
     /**
      * Sets which packages may enter lock task mode.
      *