Introduce BluetoothAdapter.getDefaultAdapter().

This is the main entry point to the Bluetooth APIs, and returns the default
local Bluetooth adapter.

It replaces context.getSystemService(Context.BLUETOOTH_SERVICE). This was
never in a public SDK release.

DrNo: eastham
Bug: 2158765
Joke: Why can't you play cards in the jungle? Because there's too many cheetas!
Change-Id: Ieed8be009ee5aba621cb69090ee8c8a9c19c840d
diff --git a/api/current.xml b/api/current.xml
index 0bca84b..f4d81c7 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -25550,6 +25550,17 @@
  visibility="public"
 >
 </method>
+<method name="getDefaultAdapter"
+ return="android.bluetooth.BluetoothAdapter"
+ abstract="false"
+ native="false"
+ synchronized="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getName"
  return="java.lang.String"
  abstract="false"
@@ -31505,17 +31516,6 @@
  visibility="public"
 >
 </field>
-<field name="BLUETOOTH_SERVICE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;bluetooth&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="CLIPBOARD_SERVICE"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 8ba7c01..f48f150 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -22,8 +22,6 @@
 
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.IBluetooth;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -182,8 +180,6 @@
     private StatusBarManager mStatusBarManager = null;
     private TelephonyManager mTelephonyManager = null;
     private ClipboardManager mClipboardManager = null;
-    private boolean mIsBluetoothAdapterCached = false;
-    private BluetoothAdapter mBluetoothAdapter;
     private boolean mRestricted;
     private AccountManager mAccountManager; // protected by mSync
 
@@ -883,8 +879,6 @@
             return getSearchManager();
         } else if (SENSOR_SERVICE.equals(name)) {
             return getSensorManager();
-        } else if (BLUETOOTH_SERVICE.equals(name)) {
-            return getBluetoothAdapter();
         } else if (VIBRATOR_SERVICE.equals(name)) {
             return getVibrator();
         } else if (STATUS_BAR_SERVICE.equals(name)) {
@@ -1034,18 +1028,6 @@
         return mSearchManager;
     }
 
-    private synchronized BluetoothAdapter getBluetoothAdapter() {
-        if (!mIsBluetoothAdapterCached) {
-            mIsBluetoothAdapterCached = true;
-            IBinder b = ServiceManager.getService(BLUETOOTH_SERVICE);
-            if (b != null) {
-                IBluetooth service = IBluetooth.Stub.asInterface(b);
-                mBluetoothAdapter = new BluetoothAdapter(service);
-            }
-        }
-        return mBluetoothAdapter;
-    }
-
     private SensorManager getSensorManager() {
         synchronized (mSync) {
             if (mSensorManager == null) {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8ce911d..cc35b7d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -20,9 +20,11 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.util.Log;
 
 import java.io.IOException;
@@ -36,10 +38,8 @@
 /**
  * Represents the local Bluetooth adapter.
  *
- * <p>Use {@link android.content.Context#getSystemService} with {@link
- * android.content.Context#BLUETOOTH_SERVICE} to get the default local
- * Bluetooth adapter. On most Android devices there is only one local
- * Bluetotoh adapter.
+ * <p>Use {@link #getDefaultAdapter} to get the default local Bluetooth
+ * adapter.
  *
  * <p>Use the {@link BluetoothDevice} class for operations on remote Bluetooth
  * devices.
@@ -257,12 +257,40 @@
      */
     public static final String EXTRA_LOCAL_NAME = "android.bluetooth.adapter.extra.LOCAL_NAME";
 
+    /** @hide */
+    public static final String BLUETOOTH_SERVICE = "bluetooth";
+
     private static final int ADDRESS_LENGTH = 17;
 
+    /**
+     * Lazyily initialized singleton. Guaranteed final after first object
+     * constructed.
+     */
+    private static BluetoothAdapter sAdapter;
+
     private final IBluetooth mService;
 
     /**
-     * Do not use this constructor. Use Context.getSystemService() instead.
+     * Get a handle to the default local Bluetooth adapter.
+     * <p>Currently Android only supports one Bluetooth adapter, but the API
+     * could be extended to support more. This will always return the default
+     * adapter.
+     * @return the default local adapter, or null if Bluetooth is not supported
+     *         on this hardware platform
+     */
+    public static synchronized BluetoothAdapter getDefaultAdapter() {
+        if (sAdapter == null) {
+            IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
+            if (b != null) {
+                IBluetooth service = IBluetooth.Stub.asInterface(b);
+                sAdapter = new BluetoothAdapter(service);
+            }
+        }
+        return sAdapter;
+    }
+
+    /**
+     * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
      * @hide
      */
     public BluetoothAdapter(IBluetooth service) {
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index ce975c2..9c23746 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -18,7 +18,6 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
-import android.content.Context;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -328,7 +327,7 @@
     /*package*/ static IBluetooth getService() {
         synchronized (BluetoothDevice.class) {
             if (sService == null) {
-                IBinder b = ServiceManager.getService(Context.BLUETOOTH_SERVICE);
+                IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_SERVICE);
                 if (b == null) {
                     throw new RuntimeException("Bluetooth service not available");
                 }
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fe4665e..8f1c671 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1218,14 +1218,6 @@
      */
     public static final String SENSOR_SERVICE = "sensor";
     /**
-     * Use with {@link #getSystemService} to retrieve a {@link
-     * android.bluetooth.BluetoothAdapter} for using Bluetooth.
-     *
-     * @see #getSystemService
-     * @see android.bluetooth.BluetoothAdapter
-     */
-    public static final String BLUETOOTH_SERVICE = "bluetooth";
-    /**
      * Use with {@link #getSystemService} to retrieve a
      * com.android.server.WallpaperService for accessing wallpapers.
      *
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index d61b42f..b73e53f 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -137,7 +137,7 @@
             throw new RuntimeException("Could not init BluetoothA2dpService");
         }
 
-        mAdapter = (BluetoothAdapter) context.getSystemService(Context.BLUETOOTH_SERVICE);
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
 
         mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
         mIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 3fdbb68..6d4d152 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -154,7 +154,7 @@
     }
 
     public synchronized void initAfterRegistration() {
-        mAdapter = (BluetoothAdapter) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
         mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this);
     }
 
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index 9e1f325..01f6dac 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -181,7 +181,7 @@
                 ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
         final IBluetooth bluetooth =
                 IBluetooth.Stub.asInterface(ServiceManager.checkService(
-                        Context.BLUETOOTH_SERVICE));
+                        BluetoothAdapter.BLUETOOTH_SERVICE));
         
         try {
             bluetoothOff = bluetooth == null ||
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e5c6010..b8cf844 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -23,6 +23,7 @@
 import dalvik.system.VMRuntime;
 
 import android.app.ActivityManagerNative;
+import android.bluetooth.BluetoothAdapter;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.ContentService;
@@ -172,14 +173,14 @@
             // support Bluetooth - see bug 988521
             if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
                 Log.i(TAG, "Registering null Bluetooth Service (emulator)");
-                ServiceManager.addService(Context.BLUETOOTH_SERVICE, null);
+                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null);
             } else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
                 Log.i(TAG, "Registering null Bluetooth Service (factory test)");
-                ServiceManager.addService(Context.BLUETOOTH_SERVICE, null);
+                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null);
             } else {
                 Log.i(TAG, "Bluetooth Service");
                 bluetooth = new BluetoothService(context);
-                ServiceManager.addService(Context.BLUETOOTH_SERVICE, bluetooth);
+                ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, bluetooth);
                 bluetooth.initAfterRegistration();
                 bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
                 ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index cf63d02..801a938 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -448,8 +448,7 @@
         mBluetoothData = IconData.makeIcon("bluetooth",
                 null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
         mBluetoothIcon = service.addIcon(mBluetoothData, null);
-        BluetoothAdapter adapter =
-                (BluetoothAdapter) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
         if (adapter != null) {
             mBluetoothEnabled = adapter.isEnabled();
         } else {