Fix discoverability timeout issues. (a) implement timeout logic (b) persist 'never timeout' after reboot (c) code cleanup

Change-Id: Ia7a8611d7212b9201994034d17da1d18e106107b
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 795a2e8..0ac4d3e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1479,5 +1479,11 @@
             <meta-data android:name="android.appwidget.provider" android:resource="@xml/appwidget_info" />
         </receiver>
 
+        <receiver android:name=".bluetooth.BluetoothDiscoverableTimeoutReceiver">
+            <intent-filter>
+                <action android:name="android.bluetooth.intent.DISCOVERABLE_TIMEOUT" />
+            </intent-filter>
+        </receiver>
+
     </application>
 </manifest>
diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
index babf1e2..4e43d98 100755
--- a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
+++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java
@@ -29,6 +29,12 @@
 
 import com.android.settings.R;
 
+/* Required to handle timeout notification when phone is suspended */
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.text.format.Time;
+import android.util.Log;
+
 /**
  * BluetoothDiscoverableEnabler is a helper to manage the "Discoverable"
  * checkbox. It sets/unsets discoverability and keeps track of how much time
@@ -36,6 +42,8 @@
  */
 final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClickListener {
 
+    private static final String TAG = "BluetoothDiscoverableEnabler";
+
     private static final String SYSTEM_PROPERTY_DISCOVERABLE_TIMEOUT =
             "debug.bt.discoverable_time";
 
@@ -43,6 +51,7 @@
     private static final int DISCOVERABLE_TIMEOUT_FIVE_MINUTES = 300;
     private static final int DISCOVERABLE_TIMEOUT_ONE_HOUR = 3600;
     static final int DISCOVERABLE_TIMEOUT_NEVER = 0;
+    private static final String INTENT_DISCOVERABLE_TIMEOUT = "android.bluetooth.intent.DISCOVERABLE_TIMEOUT";
 
     // Bluetooth advanced settings screen was replaced with action bar items.
     // Use the same preference key for discoverable timeout as the old ListPreference.
@@ -68,6 +77,8 @@
 
     private int mTimeoutSecs = -1;
 
+    private AlarmManager mAlarmManager = null;
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -95,6 +106,8 @@
         mDiscoveryPreference = discoveryPreference;
         mSharedPreferences = discoveryPreference.getSharedPreferences();
         discoveryPreference.setPersistent(false);
+
+        mAlarmManager = (AlarmManager) mContext.getSystemService (Context.ALARM_SERVICE);
     }
 
     public void resume() {
@@ -128,15 +141,18 @@
     private void setEnabled(boolean enable) {
         if (enable) {
             int timeout = getDiscoverableTimeout();
-            mLocalAdapter.setDiscoverableTimeout(timeout);
-
             long endTimestamp = System.currentTimeMillis() + timeout * 1000L;
             LocalBluetoothPreferences.persistDiscoverableEndTimestamp(mContext, endTimestamp);
 
             mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, timeout);
             updateCountdownSummary();
+
+            if (0 < timeout) {
+                setDiscoverableAlarm(endTimestamp);
+            }
         } else {
             mLocalAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+            cancelDiscoverableAlarm();
         }
     }
 
@@ -278,4 +294,34 @@
             mUiHandler.postDelayed(mUpdateCountdownSummaryRunnable, 1000);
         }
     }
+
+    private void setDiscoverableAlarm(long alarmTime) {
+        Log.d(TAG, "setDiscoverableAlarm(): alarmTime = " + alarmTime);
+
+        Intent intent = new Intent(INTENT_DISCOVERABLE_TIMEOUT);
+        intent.setClass(mContext, BluetoothDiscoverableTimeoutReceiver.class);
+        PendingIntent pending = PendingIntent.getBroadcast(
+            mContext, 0, intent, 0);
+        if (pending != null) {
+            // Cancel any previous alarms that do the same thing.
+            mAlarmManager.cancel(pending);
+        }
+        pending = PendingIntent.getBroadcast(
+            mContext, 0, intent, 0);
+
+        mAlarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime, pending);
+    }
+
+    private void cancelDiscoverableAlarm() {
+        Log.d(TAG, "cancelDiscoverableAlarm(): Enter");
+
+        Intent intent = new Intent(INTENT_DISCOVERABLE_TIMEOUT);
+        intent.setClass(mContext, BluetoothDiscoverableTimeoutReceiver.class);
+        PendingIntent pending = PendingIntent.getBroadcast(
+            mContext, 0, intent, PendingIntent.FLAG_NO_CREATE);
+        if (pending != null) {
+            // Cancel any previous alarms that do the same thing.
+            mAlarmManager.cancel(pending);
+        }
+    }
 }
diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableTimeoutReceiver.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
new file mode 100644
index 0000000..729498d
--- /dev/null
+++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableTimeoutReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2008 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 com.android.settings.bluetooth;
+
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.bluetooth.BluetoothAdapter;
+import android.util.Log;
+
+public class BluetoothDiscoverableTimeoutReceiver extends BroadcastReceiver {
+    private static final String TAG = "BluetoothDiscoverableTimeoutReceiver";
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        LocalBluetoothAdapter localBluetoothAdapter = LocalBluetoothAdapter.getInstance();
+
+         if(null != localBluetoothAdapter && localBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
+            Log.d(TAG, "Disable discoverable...");
+
+            localBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE);
+         } else {
+            Log.e(TAG, "localBluetoothAdapter is NULL!!");
+        }
+    }
+};
+