Monitor disabled profile setting and enable/disable profiles on change.

Bug: 25900899
Change-Id: Id98ae58ada8eecd33a2c86970d9d20ae061680be
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index a12ea9e..5e60ee4 100644
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -188,6 +188,8 @@
     private PowerManager.WakeLock mWakeLock;
     private String mWakeLockName;
 
+    private ProfileObserver mProfileObserver;
+
     public AdapterService() {
         super();
         if (TRACE_REF) {
@@ -404,9 +406,8 @@
 
         mSdpManager = SdpManager.init(this);
         registerReceiver(mAlarmBroadcastReceiver, new IntentFilter(ACTION_ALARM_WAKEUP));
-
-
-
+        mProfileObserver = new ProfileObserver(getApplicationContext(), this, new Handler());
+        mProfileObserver.start();
     }
 
     @Override
@@ -422,6 +423,7 @@
 
     public void onDestroy() {
         debugLog("onDestroy()");
+        mProfileObserver.stop();
     }
 
     void BleOnProcessStart() {
diff --git a/src/com/android/bluetooth/btservice/Config.java b/src/com/android/bluetooth/btservice/Config.java
index 4301cd9..d176d78 100644
--- a/src/com/android/bluetooth/btservice/Config.java
+++ b/src/com/android/bluetooth/btservice/Config.java
@@ -17,10 +17,15 @@
 package com.android.bluetooth.btservice;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
+import android.bluetooth.BluetoothProfile;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.SystemProperties;
+import android.provider.Settings;
 import android.util.Log;
 
 import com.android.bluetooth.R;
@@ -84,10 +89,11 @@
         if (resources == null) {
             return;
         }
+
         ArrayList<Class> profiles = new ArrayList<Class>(PROFILE_SERVICES.length);
         for (int i=0; i < PROFILE_SERVICES_FLAG.length; i++) {
             boolean supported = resources.getBoolean(PROFILE_SERVICES_FLAG[i]);
-            if (supported) {
+            if (supported && !isProfileDisabled(ctx, PROFILE_SERVICES[i])) {
                 Log.d(TAG, "Adding " + PROFILE_SERVICES[i].getSimpleName());
                 profiles.add(PROFILE_SERVICES[i]);
             }
@@ -100,4 +106,44 @@
     static Class[]  getSupportedProfiles() {
         return SUPPORTED_PROFILES;
     }
+
+    private static boolean isProfileDisabled(Context context, Class profile) {
+        int profileIndex = -1;
+
+        if (profile == HeadsetService.class) {
+            profileIndex = BluetoothProfile.HEADSET;
+        } else if (profile == A2dpService.class) {
+            profileIndex = BluetoothProfile.A2DP;
+        } else if (profile == A2dpSinkService.class) {
+            profileIndex = BluetoothProfile.A2DP_SINK;
+        } else if (profile == HidService.class) {
+            profileIndex = BluetoothProfile.HID;
+        } else if (profile == HealthService.class) {
+            profileIndex = BluetoothProfile.HDP;
+        } else if (profile == PanService.class) {
+            profileIndex = BluetoothProfile.PAN;
+        } else if (profile == GattService.class) {
+            profileIndex = BluetoothProfile.GATT;
+        } else if (profile == BluetoothMapService.class) {
+            profileIndex = BluetoothProfile.MAP;
+        } else if (profile == HeadsetClientService.class) {
+            profileIndex = BluetoothProfile.HEADSET_CLIENT;
+        } else if (profile == AvrcpControllerService.class) {
+            profileIndex = BluetoothProfile.AVRCP_CONTROLLER;
+        } else if (profile == SapService.class) {
+            profileIndex = BluetoothProfile.SAP;
+        }
+
+        if (profileIndex == -1) {
+            Log.d(TAG, "Could not find profile bit mask");
+            return false;
+        }
+
+        final ContentResolver resolver = context.getContentResolver();
+        final long disabledProfilesBitMask = Settings.Global.getLong(resolver,
+                Settings.Global.BLUETOOTH_DISABLED_PROFILES, 0);
+        long profileBit = 1 << profileIndex;
+
+        return (disabledProfilesBitMask & profileBit) != 0;
+    }
 }
diff --git a/src/com/android/bluetooth/btservice/ProfileObserver.java b/src/com/android/bluetooth/btservice/ProfileObserver.java
new file mode 100644
index 0000000..cccd96a
--- /dev/null
+++ b/src/com/android/bluetooth/btservice/ProfileObserver.java
@@ -0,0 +1,69 @@
+package com.android.bluetooth.btservice;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+
+/**
+ * This helper class monitors the state of the enabled profiles and will update and restart
+ * the adapter when necessary.
+ */
+public class ProfileObserver extends ContentObserver {
+    private Context mContext;
+    private AdapterService mService;
+    private AdapterStateObserver mStateObserver;
+
+    public ProfileObserver(Context context, AdapterService service, Handler handler) {
+        super(handler);
+        mContext = context;
+        mService = service;
+        mStateObserver = new AdapterStateObserver(this);
+    }
+
+    public void start() {
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.BLUETOOTH_DISABLED_PROFILES), false,
+                this);
+    }
+
+    private void onBluetoothOff() {
+        mContext.unregisterReceiver(mStateObserver);
+        Config.init(mContext);
+        mService.enable();
+    }
+
+    public void stop() {
+        mContext.getContentResolver().unregisterContentObserver(this);
+    }
+
+    @Override
+    public void onChange(boolean selfChange) {
+        if (mService.isEnabled()) {
+            mContext.registerReceiver(mStateObserver,
+                    new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
+            mService.disable();
+        }
+    }
+
+    private static class AdapterStateObserver extends BroadcastReceiver {
+        private ProfileObserver mProfileObserver;
+
+        public AdapterStateObserver(ProfileObserver observer) {
+            mProfileObserver = observer;
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())
+                    && intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1)
+                    == BluetoothAdapter.STATE_OFF) {
+                mProfileObserver.onBluetoothOff();
+            }
+        }
+    }
+}