Fragmentize BluetoothSettings.

Add UserLeaveHintListener.java, so that the settings won't use
its implementation around Activity#onUserLeaveHint().

Also fragmentize bluetooth tethering screen.

Change-Id: Id06ae3161fbdb5854ddb7a257f464fb16ea9b089
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0a73131..405acaa 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -168,9 +168,10 @@
             </intent-filter>
         </activity>
 
-        <activity android:name=".bluetooth.BluetoothSettings"
+        <activity-alias android:name=".bluetooth.BluetoothSettings"
                   android:label="@string/bluetooth_settings_title"
                   android:clearTaskOnLaunch="true"
+                  android:targetActivity="Settings"
                   >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -183,7 +184,7 @@
                 <action android:name="android.bluetooth.devicepicker.action.LAUNCH" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
-        </activity>
+        </activity-alias>
 
         <activity-alias android:name=".TetherSettings"
             android:clearTaskOnLaunch="true"
diff --git a/proguard.flags b/proguard.flags
index 9427b09..0e1b428 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -3,4 +3,4 @@
 -keep class com.android.settings.*Picker
 -keep class com.android.settings.*Settings
 -keep class com.android.settings.wifi.*Settings
--keep class com.android.settings.deviceinfo.*
\ No newline at end of file
+-keep class com.android.settings.deviceinfo.*
diff --git a/res/xml/tether_prefs.xml b/res/xml/tether_prefs.xml
index ac93a86..d475a14 100644
--- a/res/xml/tether_prefs.xml
+++ b/res/xml/tether_prefs.xml
@@ -38,14 +38,13 @@
         android:title="@string/bluetooth_tether_checkbox_text"
         android:persistent="false" />
 
+    <!-- BluetoothSettings will have extra argument to know this request is
+         for tethering, not for BT setting in general. -->
     <PreferenceScreen
+        android:fragment="com.android.settings.bluetooth.BluetoothSettings"
         android:key="bluetooth_tether_settings"
         android:title="@string/bluetooth_tether_settings_text"
         android:summary="@string/bluetooth_tether_settings_subtext" >
-        <intent
-            android:action="com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER"
-            android:targetPackage="com.android.settings"
-            android:targetClass="com.android.settings.bluetooth.BluetoothSettings" />
     </PreferenceScreen>
 
     <PreferenceScreen
diff --git a/res/xml/wireless_settings.xml b/res/xml/wireless_settings.xml
index 3c61424..8e05e60 100644
--- a/res/xml/wireless_settings.xml
+++ b/res/xml/wireless_settings.xml
@@ -45,13 +45,10 @@
         android:persistent="false" />
 
     <PreferenceScreen
+        android:fragment="com.android.settings.bluetooth.BluetoothSettings"
         android:key="bt_settings"
         android:title="@string/bluetooth_settings_title"
         android:summary="@string/bluetooth_settings_summary">
-        <intent
-            android:action="android.intent.action.MAIN"
-            android:targetPackage="com.android.settings"
-            android:targetClass="com.android.settings.bluetooth.BluetoothSettings" />
     </PreferenceScreen>
 
     <PreferenceScreen
diff --git a/src/com/android/settings/SettingsPreferenceFragment.java b/src/com/android/settings/SettingsPreferenceFragment.java
index 90ceb03..935c72a 100644
--- a/src/com/android/settings/SettingsPreferenceFragment.java
+++ b/src/com/android/settings/SettingsPreferenceFragment.java
@@ -175,6 +175,10 @@
         return mNextButton;
     }
 
+    public void finish() {
+        getActivity().onBackPressed();
+    }
+
     /**
      * Sets up Button Bar possibly required in the Fragment. Probably available only in
      * phones.
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index 272a3d4..87726c1 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -16,6 +16,7 @@
 
 package com.android.settings;
 
+import com.android.settings.bluetooth.BluetoothSettings;
 import com.android.settings.wifi.WifiApEnabler;
 
 import android.app.Activity;
@@ -34,6 +35,7 @@
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
 import android.preference.PreferenceScreen;
+import android.util.Log;
 import android.webkit.WebView;
 
 import java.io.InputStream;
@@ -385,7 +387,7 @@
     }
 
     @Override
-    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+    public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
         if (preference == mUsbTether) {
             boolean newState = mUsbTether.isChecked();
 
@@ -457,11 +459,15 @@
                     mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext);
                 }
             }
+        } else if (preference == mBluetoothSettings) {
+            preference.getExtras().putString(BluetoothSettings.ACTION,
+                    BluetoothSettings.ACTION_LAUNCH_TETHER_PICKER);
         } else if (preference == mTetherHelp) {
             showDialog(DIALOG_TETHER_HELP);
+            return true;
         }
 
-        return super.onPreferenceTreeClick(preferenceScreen, preference);
+        return super.onPreferenceTreeClick(screen, preference);
     }
 
     private String findIface(String[] ifaces, String[] regexes) {
diff --git a/src/com/android/settings/UserLeaveHintListener.java b/src/com/android/settings/UserLeaveHintListener.java
new file mode 100644
index 0000000..c5c2a7a
--- /dev/null
+++ b/src/com/android/settings/UserLeaveHintListener.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2010 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;
+
+/**
+ * Interface enabling fragments to listen to Activity#onUserLeaveHint().
+ */
+public interface UserLeaveHintListener {
+    public void onUserLeaveHint();
+}
\ No newline at end of file
diff --git a/src/com/android/settings/bluetooth/BluetoothSettings.java b/src/com/android/settings/bluetooth/BluetoothSettings.java
index bb3cbc7..88d1e83 100644
--- a/src/com/android/settings/bluetooth/BluetoothSettings.java
+++ b/src/com/android/settings/bluetooth/BluetoothSettings.java
@@ -18,8 +18,11 @@
 
 import com.android.settings.ProgressCategory;
 import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.UserLeaveHintListener;
 import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
 
+import android.app.Activity;
 import android.app.AlertDialog;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothClass;
@@ -27,28 +30,22 @@
 import android.bluetooth.BluetoothDevicePicker;
 import android.bluetooth.BluetoothPan;
 import android.bluetooth.BluetoothUuid;
-import android.bluetooth.IBluetooth;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
-import android.os.IBinder;
 import android.os.ParcelUuid;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.preference.CheckBoxPreference;
 import android.preference.Preference;
-import android.preference.PreferenceActivity;
 import android.preference.PreferenceScreen;
-import android.server.BluetoothService;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
 import android.view.MenuItem;
 import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
 import android.widget.AdapterView.AdapterContextMenuInfo;
 
 import java.util.List;
@@ -58,8 +55,8 @@
  * BluetoothSettings is the Settings screen for Bluetooth configuration and
  * connection management.
  */
-public class BluetoothSettings extends PreferenceActivity
-        implements LocalBluetoothManager.Callback {
+public class BluetoothSettings extends SettingsPreferenceFragment
+        implements LocalBluetoothManager.Callback, UserLeaveHintListener {
 
     private static final String TAG = "BluetoothSettings";
 
@@ -73,6 +70,7 @@
     private static final int SCREEN_TYPE_DEVICEPICKER = 1;
     private static final int SCREEN_TYPE_TETHERING = 2;
 
+    public static final String ACTION = "bluetooth_action";
     public static final String ACTION_LAUNCH_TETHER_PICKER =
         "com.android.settings.bluetooth.action.LAUNCH_TETHER_PICKER";
 
@@ -123,11 +121,19 @@
     };
 
     @Override
-    protected void onCreate(Bundle savedInstanceState) {
+    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+    }
 
-        mLocalManager = LocalBluetoothManager.getInstance(this);
-        if (mLocalManager == null) finish();
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        // We delay calling super.onActivityCreated(). See WifiSettings.java for more info.
+
+        final Activity activity = getActivity();
+        mLocalManager = LocalBluetoothManager.getInstance(activity);
+        if (mLocalManager == null) {
+            finish();
+        }
 
         // Note:
         // If an application wish to show the BT device list, it can send an
@@ -139,8 +145,13 @@
         // -DEVICE_PICKER_NEED_AUTH: to show if bonding procedure needed.
 
         mFilterType = BluetoothDevicePicker.FILTER_TYPE_ALL;
-        Intent intent = getIntent();
-        String action = intent.getAction();
+        final Intent intent = activity.getIntent();
+
+        // This additional argument comes from PreferenceScreen (See TetherSettings.java).
+        String action = getArguments().getString(ACTION);
+        if (TextUtils.isEmpty(action)) {
+            action = intent.getAction();
+        }
 
         if (action.equals(BluetoothDevicePicker.ACTION_LAUNCH)) {
             mScreenType = SCREEN_TYPE_DEVICEPICKER;
@@ -150,23 +161,23 @@
             mLaunchPackage = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_PACKAGE);
             mLaunchClass = intent.getStringExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS);
 
-            setTitle(getString(R.string.device_picker));
+            activity.setTitle(activity.getString(R.string.device_picker));
             addPreferencesFromResource(R.xml.device_picker);
         } else if (action.equals(ACTION_LAUNCH_TETHER_PICKER)){
             mScreenType = SCREEN_TYPE_TETHERING;
             mFilterType = BluetoothDevicePicker.FILTER_TYPE_PANU;
 
-            setTitle(getString(R.string.device_picker));
+            activity.setTitle(activity.getString(R.string.device_picker));
             addPreferencesFromResource(R.xml.device_picker);
         } else {
             addPreferencesFromResource(R.xml.bluetooth_settings);
 
             mEnabler = new BluetoothEnabler(
-                    this,
+                    activity,
                     (CheckBoxPreference) findPreference(KEY_BT_CHECKBOX));
 
             mDiscoverableEnabler = new BluetoothDiscoverableEnabler(
-                    this,
+                    activity,
                     (CheckBoxPreference) findPreference(KEY_BT_DISCOVERABLE));
 
             mNamePreference = (BluetoothNamePreference) findPreference(KEY_BT_NAME);
@@ -177,10 +188,12 @@
         mDeviceList = (ProgressCategory) findPreference(KEY_BT_DEVICE_LIST);
 
         registerForContextMenu(getListView());
+
+        super.onActivityCreated(savedInstanceState);
     }
 
     @Override
-    protected void onResume() {
+    public void onResume() {
         super.onResume();
 
         // Repopulate (which isn't too bad since it's cached in the settings
@@ -203,18 +216,17 @@
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
         intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
-        registerReceiver(mReceiver, intentFilter);
-        mLocalManager.setForegroundActivity(this);
+        getActivity().registerReceiver(mReceiver, intentFilter);
+        mLocalManager.setForegroundActivity(getActivity());
     }
 
     @Override
-    protected void onPause() {
+    public void onPause() {
         super.onPause();
-
         mLocalManager.setForegroundActivity(null);
         mDevicePreferenceMap.clear();
         mDeviceList.removeAll();
-        unregisterReceiver(mReceiver);
+        getActivity().unregisterReceiver(mReceiver);
 
         mLocalManager.unregisterCallback(this);
         if (mScreenType == SCREEN_TYPE_SETTINGS) {
@@ -225,8 +237,7 @@
     }
 
     @Override
-    protected void onUserLeaveHint() {
-        super.onUserLeaveHint();
+    public void onUserLeaveHint() {
         mLocalManager.stopScanning();
     }
 
@@ -390,10 +401,10 @@
         BluetoothDevicePreference preference;
         if (mScreenType == SCREEN_TYPE_TETHERING) {
             preference = new BluetoothDevicePreference(
-                    this, cachedDevice, CachedBluetoothDevice.PAN_PROFILE);
+                    getActivity(), cachedDevice, CachedBluetoothDevice.PAN_PROFILE);
         } else {
             preference = new BluetoothDevicePreference(
-                    this, cachedDevice, CachedBluetoothDevice.OTHER_PROFILES);
+                    getActivity(), cachedDevice, CachedBluetoothDevice.OTHER_PROFILES);
         }
         mDeviceList.addPreference(preference);
         mDevicePreferenceMap.put(cachedDevice, preference);
@@ -421,22 +432,23 @@
     }
 
     private void onPanDevicePicked() {
+        final Activity activity = getActivity();
         final LocalBluetoothProfileManager profileManager =
             LocalBluetoothProfileManager.getProfileManager(mLocalManager, Profile.PAN);
         int status = profileManager.getConnectionStatus(mSelectedDevice);
         if (SettingsBtStatus.isConnectionStatusConnected(status)) {
             String name = mSelectedDevice.getName();
             if (TextUtils.isEmpty(name)) {
-                name = getString(R.string.bluetooth_device);
+                name = activity.getString(R.string.bluetooth_device);
             }
-            String message = getString(R.string.bluetooth_untether_blank, name);
+            String message = activity.getString(R.string.bluetooth_untether_blank, name);
             DialogInterface.OnClickListener disconnectListener =
                 new DialogInterface.OnClickListener() {
                 public void onClick(DialogInterface dialog, int which) {
                     profileManager.disconnect(mSelectedDevice);
                 }
             };
-            new AlertDialog.Builder(this)
+            new AlertDialog.Builder(activity)
                 .setTitle(name)
                 .setMessage(message)
                 .setPositiveButton(android.R.string.ok, disconnectListener)
@@ -445,10 +457,10 @@
                 .show();
         } else if (status == SettingsBtStatus.CONNECTION_STATUS_DISCONNECTED) {
             if (profileManager.getConnectedDevices().size() >= BluetoothPan.MAX_CONNECTIONS) {
-                new AlertDialog.Builder(this)
+                new AlertDialog.Builder(activity)
                     .setIcon(android.R.drawable.ic_dialog_alert)
                     .setTitle(R.string.bluetooth_error_title)
-                    .setMessage(getString(R.string.bluetooth_tethering_overflow_error,
+                    .setMessage(activity.getString(R.string.bluetooth_tethering_overflow_error,
                             BluetoothPan.MAX_CONNECTIONS))
                     .setNegativeButton(android.R.string.ok, null)
                     .create()
@@ -466,6 +478,6 @@
                 mLaunchPackage != null && mLaunchClass != null) {
             intent.setClassName(mLaunchPackage, mLaunchClass);
         }
-        sendBroadcast(intent);
+        getActivity().sendBroadcast(intent);
     }
 }