diff options
16 files changed, 680 insertions, 1620 deletions
| diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 442b23938ccd..1fe1b10005cf 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -22,23 +22,16 @@ import android.annotation.RequiresPermission;  import android.annotation.SdkConstant;  import android.annotation.SdkConstant.SdkConstantType;  import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.Build;  import android.os.IBinder;  import android.os.ParcelUuid;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log; -import com.android.internal.annotations.GuardedBy; -  import java.util.ArrayList;  import java.util.List; -import java.util.concurrent.locks.ReentrantReadWriteLock;  /** @@ -209,101 +202,32 @@ public final class BluetoothA2dp implements BluetoothProfile {      @UnsupportedAppUsage      public static final int OPTIONAL_CODECS_PREF_ENABLED = 1; -    private Context mContext; -    private ServiceListener mServiceListener; -    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); -    @GuardedBy("mServiceLock") -    private IBluetoothA2dp mService;      private BluetoothAdapter mAdapter; - -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        try { -                            mServiceLock.writeLock().lock(); -                            if (mService != null) { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } -                        } catch (Exception re) { -                            Log.e(TAG, "", re); -                        } finally { -                            mServiceLock.writeLock().unlock(); -                        } -                    } else { -                        try { -                            mServiceLock.readLock().lock(); -                            if (mService == null) { -                                if (VDBG) Log.d(TAG, "Binding service..."); -                                doBind(); -                            } -                        } catch (Exception re) { -                            Log.e(TAG, "", re); -                        } finally { -                            mServiceLock.readLock().unlock(); -                        } -                    } +    private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp", +                    IBluetoothA2dp.class.getName()) { +                @Override +                public IBluetoothA2dp getServiceInterface(IBinder service) { +                    return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothA2dp proxy object for interacting with the local       * Bluetooth A2DP service.       */ -    /*package*/ BluetoothA2dp(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothA2dp(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } - -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothA2dp.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      @UnsupportedAppUsage      /*package*/ void close() { -        mServiceListener = null; -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        try { -            mServiceLock.writeLock().lock(); -            if (mService != null) { -                mService = null; -                mContext.unbindService(mConnection); -            } -        } catch (Exception re) { -            Log.e(TAG, "", re); -        } finally { -            mServiceLock.writeLock().unlock(); -        } +    private IBluetoothA2dp getService() { +        return mProfileConnector.getService();      }      @Override @@ -333,17 +257,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      public boolean connect(BluetoothDevice device) {          if (DBG) log("connect(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() && isValidDevice(device)) { -                return mService.connect(device); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled() && isValidDevice(device)) { +                return service.connect(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -376,17 +298,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() && isValidDevice(device)) { -                return mService.disconnect(device); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled() && isValidDevice(device)) { +                return service.disconnect(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -397,17 +317,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      public List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getConnectedDevices(); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                return service.getConnectedDevices();              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return new ArrayList<BluetoothDevice>();          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return new ArrayList<BluetoothDevice>(); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -418,17 +336,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (VDBG) log("getDevicesMatchingStates()");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getDevicesMatchingConnectionStates(states); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                return service.getDevicesMatchingConnectionStates(states);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return new ArrayList<BluetoothDevice>();          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return new ArrayList<BluetoothDevice>(); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -439,18 +355,16 @@ public final class BluetoothA2dp implements BluetoothProfile {      public @BtProfileState int getConnectionState(BluetoothDevice device) {          if (VDBG) log("getState(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.getConnectionState(device); +                return service.getConnectionState(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return BluetoothProfile.STATE_DISCONNECTED;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return BluetoothProfile.STATE_DISCONNECTED; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -480,18 +394,16 @@ public final class BluetoothA2dp implements BluetoothProfile {      public boolean setActiveDevice(@Nullable BluetoothDevice device) {          if (DBG) log("setActiveDevice(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()                      && ((device == null) || isValidDevice(device))) { -                return mService.setActiveDevice(device); +                return service.setActiveDevice(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -511,17 +423,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      public BluetoothDevice getActiveDevice() {          if (VDBG) log("getActiveDevice()");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getActiveDevice(); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                return service.getActiveDevice();              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return null;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return null; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -543,22 +453,20 @@ public final class BluetoothA2dp implements BluetoothProfile {      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()                      && isValidDevice(device)) {                  if (priority != BluetoothProfile.PRIORITY_OFF                          && priority != BluetoothProfile.PRIORITY_ON) {                      return false;                  } -                return mService.setPriority(device, priority); +                return service.setPriority(device, priority);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -578,18 +486,16 @@ public final class BluetoothA2dp implements BluetoothProfile {      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.getPriority(device); +                return service.getPriority(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return BluetoothProfile.PRIORITY_OFF;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return BluetoothProfile.PRIORITY_OFF; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -602,17 +508,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      public boolean isAvrcpAbsoluteVolumeSupported() {          if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.isAvrcpAbsoluteVolumeSupported(); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                return service.isAvrcpAbsoluteVolumeSupported();              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -625,15 +529,13 @@ public final class BluetoothA2dp implements BluetoothProfile {      public void setAvrcpAbsoluteVolume(int volume) {          if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                mService.setAvrcpAbsoluteVolume(volume); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                service.setAvrcpAbsoluteVolume(volume);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -646,18 +548,16 @@ public final class BluetoothA2dp implements BluetoothProfile {       */      public boolean isA2dpPlaying(BluetoothDevice device) {          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.isA2dpPlaying(device); +                return service.isA2dpPlaying(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -694,19 +594,17 @@ public final class BluetoothA2dp implements BluetoothProfile {      public @Nullable BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {          if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getCodecStatus(device); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                return service.getCodecStatus(device);              } -            if (mService == null) { +            if (service == null) {                  Log.w(TAG, "Proxy not attached to service");              }              return null;          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);              return null; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -723,17 +621,15 @@ public final class BluetoothA2dp implements BluetoothProfile {                                           BluetoothCodecConfig codecConfig) {          if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                mService.setCodecConfigPreference(device, codecConfig); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) { +                service.setCodecConfigPreference(device, codecConfig);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return;          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);              return; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -772,21 +668,19 @@ public final class BluetoothA2dp implements BluetoothProfile {       */      private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()) {                  if (enable) { -                    mService.enableOptionalCodecs(device); +                    service.enableOptionalCodecs(device);                  } else { -                    mService.disableOptionalCodecs(device); +                    service.disableOptionalCodecs(device);                  }              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return;          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);              return; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -801,17 +695,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      @UnsupportedAppUsage      public int supportsOptionalCodecs(BluetoothDevice device) {          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() && isValidDevice(device)) { -                return mService.supportsOptionalCodecs(device); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled() && isValidDevice(device)) { +                return service.supportsOptionalCodecs(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return OPTIONAL_CODECS_SUPPORT_UNKNOWN;          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);              return OPTIONAL_CODECS_SUPPORT_UNKNOWN; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -826,17 +718,15 @@ public final class BluetoothA2dp implements BluetoothProfile {      @UnsupportedAppUsage      public int getOptionalCodecsEnabled(BluetoothDevice device) {          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() && isValidDevice(device)) { -                return mService.getOptionalCodecsEnabled(device); +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled() && isValidDevice(device)) { +                return service.getOptionalCodecsEnabled(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return OPTIONAL_CODECS_PREF_UNKNOWN;          } catch (RemoteException e) {              Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);              return OPTIONAL_CODECS_PREF_UNKNOWN; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -858,18 +748,16 @@ public final class BluetoothA2dp implements BluetoothProfile {                  Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);                  return;              } -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            final IBluetoothA2dp service = getService(); +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                mService.setOptionalCodecsEnabled(device, value); +                service.setOptionalCodecsEnabled(device, value);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -900,35 +788,6 @@ public final class BluetoothA2dp implements BluetoothProfile {          }      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            try { -                mServiceLock.writeLock().lock(); -                mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service)); -            } finally { -                mServiceLock.writeLock().unlock(); -            } - -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            try { -                mServiceLock.writeLock().lock(); -                mService = null; -            } finally { -                mServiceLock.writeLock().unlock(); -            } -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP); -            } -        } -    }; -      private boolean isEnabled() {          if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;          return false; diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java index cb996f3381b7..5a8055a29cfc 100755 --- a/core/java/android/bluetooth/BluetoothA2dpSink.java +++ b/core/java/android/bluetooth/BluetoothA2dpSink.java @@ -17,14 +17,10 @@  package android.bluetooth;  import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -125,93 +121,31 @@ public final class BluetoothA2dpSink implements BluetoothProfile {      public static final String EXTRA_AUDIO_CONFIG =              "android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG"; -    private Context mContext; -    private ServiceListener mServiceListener; -    private volatile IBluetoothA2dpSink mService;      private BluetoothAdapter mAdapter; - -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK, +                    "BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) { +                @Override +                public IBluetoothA2dpSink getServiceInterface(IBinder service) { +                    return IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothA2dp proxy object for interacting with the local       * Bluetooth A2DP service.       */ -    /*package*/ BluetoothA2dpSink(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothA2dpSink(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } - -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothA2dpSink.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      /*package*/ void close() { -        mServiceListener = null; -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } +    private IBluetoothA2dpSink getService() { +        return mProfileConnector.getService();      }      @Override @@ -242,7 +176,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {       */      public boolean connect(BluetoothDevice device) {          if (DBG) log("connect(" + device + ")"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.connect(device); @@ -283,7 +217,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {      @UnsupportedAppUsage      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -302,7 +236,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {      @Override      public List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -321,7 +255,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (VDBG) log("getDevicesMatchingStates()"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -340,7 +274,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {      @Override      public int getConnectionState(BluetoothDevice device) {          if (VDBG) log("getState(" + device + ")"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -366,7 +300,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {       */      public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {          if (VDBG) log("getAudioConfig(" + device + ")"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getAudioConfig(device); @@ -396,7 +330,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -428,7 +362,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {       */      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")"); -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); @@ -449,7 +383,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {       * @param device BluetoothDevice device       */      public boolean isA2dpPlaying(BluetoothDevice device) { -        final IBluetoothA2dpSink service = mService; +        final IBluetoothA2dpSink service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.isA2dpPlaying(device); @@ -488,25 +422,6 @@ public final class BluetoothA2dpSink implements BluetoothProfile {          }      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service)); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK, -                        BluetoothA2dpSink.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK); -            } -        } -    }; -      private boolean isEnabled() {          return mAdapter.getState() == BluetoothAdapter.STATE_ON;      } diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java index c447868d6f0c..4e7e4415c54d 100644 --- a/core/java/android/bluetooth/BluetoothAvrcpController.java +++ b/core/java/android/bluetooth/BluetoothAvrcpController.java @@ -16,14 +16,10 @@  package android.bluetooth; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -80,93 +76,32 @@ public final class BluetoothAvrcpController implements BluetoothProfile {      public static final String EXTRA_PLAYER_SETTING =              "android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING"; -    private Context mContext; -    private ServiceListener mServiceListener; -    private volatile IBluetoothAvrcpController mService;      private BluetoothAdapter mAdapter; - -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER, +                    "BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) { +                @Override +                public IBluetoothAvrcpController getServiceInterface(IBinder service) { +                    return IBluetoothAvrcpController.Stub.asInterface( +                            Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothAvrcpController proxy object for interacting with the local       * Bluetooth AVRCP service.       */ -    /*package*/ BluetoothAvrcpController(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothAvrcpController(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } - -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothAvrcpController.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      /*package*/ void close() { -        mServiceListener = null; -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } +    private IBluetoothAvrcpController getService() { +        return mProfileConnector.getService();      }      @Override @@ -180,7 +115,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {      @Override      public List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()"); -        final IBluetoothAvrcpController service = mService; +        final IBluetoothAvrcpController service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -199,7 +135,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (VDBG) log("getDevicesMatchingStates()"); -        final IBluetoothAvrcpController service = mService; +        final IBluetoothAvrcpController service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -218,7 +155,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {      @Override      public int getConnectionState(BluetoothDevice device) {          if (VDBG) log("getState(" + device + ")"); -        final IBluetoothAvrcpController service = mService; +        final IBluetoothAvrcpController service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -239,7 +177,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {      public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {          if (DBG) Log.d(TAG, "getPlayerSettings");          BluetoothAvrcpPlayerSettings settings = null; -        final IBluetoothAvrcpController service = mService; +        final IBluetoothAvrcpController service = +                getService();          if (service != null && isEnabled()) {              try {                  settings = service.getPlayerSettings(device); @@ -257,7 +196,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {       */      public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {          if (DBG) Log.d(TAG, "setPlayerApplicationSetting"); -        final IBluetoothAvrcpController service = mService; +        final IBluetoothAvrcpController service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.setPlayerApplicationSetting(plAppSetting); @@ -277,7 +217,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {      public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {          Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "                  + keyState); -        final IBluetoothAvrcpController service = mService; +        final IBluetoothAvrcpController service = +                getService();          if (service != null && isEnabled()) {              try {                  service.sendGroupNavigationCmd(device, keyCode, keyState); @@ -290,25 +231,6 @@ public final class BluetoothAvrcpController implements BluetoothProfile {          if (service == null) Log.w(TAG, "Proxy not attached to service");      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service)); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER, -                        BluetoothAvrcpController.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER); -            } -        } -    }; -      private boolean isEnabled() {          return mAdapter.getState() == BluetoothAdapter.STATE_ON;      } diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 8d9d340ee68b..9862a63ef238 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -337,19 +337,9 @@ public final class BluetoothHeadset implements BluetoothProfile {                  public void onBluetoothStateChange(boolean up) {                      if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);                      if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service...");                          doUnbind();                      } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } +                        doBind();                      }                  }              }; @@ -374,24 +364,32 @@ public final class BluetoothHeadset implements BluetoothProfile {          doBind();      } -    boolean doBind() { -        try { -            return mAdapter.getBluetoothManager().bindBluetoothProfileService( -                    BluetoothProfile.HEADSET, mConnection); -        } catch (RemoteException e) { -            Log.e(TAG, "Unable to bind HeadsetService", e); +    private boolean doBind() { +        synchronized (mConnection) { +            if (mService == null) { +                if (VDBG) Log.d(TAG, "Binding service..."); +                try { +                    return mAdapter.getBluetoothManager().bindBluetoothProfileService( +                            BluetoothProfile.HEADSET, mConnection); +                } catch (RemoteException e) { +                    Log.e(TAG, "Unable to bind HeadsetService", e); +                } +            }          }          return false;      } -    void doUnbind() { +    private void doUnbind() {          synchronized (mConnection) {              if (mService != null) { +                if (VDBG) Log.d(TAG, "Unbinding service...");                  try {                      mAdapter.getBluetoothManager().unbindBluetoothProfileService(                              BluetoothProfile.HEADSET, mConnection);                  } catch (RemoteException e) {                      Log.e(TAG, "Unable to unbind HeadsetService", e); +                } finally { +                    mService = null;                  }              }          } @@ -411,8 +409,8 @@ public final class BluetoothHeadset implements BluetoothProfile {          if (mgr != null) {              try {                  mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); +            } catch (RemoteException re) { +                Log.e(TAG, "", re);              }          }          mServiceListener = null; @@ -1169,7 +1167,7 @@ public final class BluetoothHeadset implements BluetoothProfile {          @Override          public void onServiceDisconnected(ComponentName className) {              if (DBG) Log.d(TAG, "Proxy object disconnected"); -            mService = null; +            doUnbind();              mHandler.sendMessage(mHandler.obtainMessage(                      MESSAGE_HEADSET_SERVICE_DISCONNECTED));          } diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java index 549c1faddd90..05833b5f571d 100644 --- a/core/java/android/bluetooth/BluetoothHeadsetClient.java +++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java @@ -17,15 +17,11 @@  package android.bluetooth;  import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.Bundle;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -367,73 +363,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      public static final int CALL_ACCEPT_HOLD = 1;      public static final int CALL_ACCEPT_TERMINATE = 2; -    private Context mContext; -    private ServiceListener mServiceListener; -    private volatile IBluetoothHeadsetClient mService;      private BluetoothAdapter mAdapter; - -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { +    private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT, +                    "BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {                  @Override -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    Intent intent = new Intent( -                                            IBluetoothHeadsetClient.class.getName()); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +                public IBluetoothHeadsetClient getServiceInterface(IBinder service) { +                    return IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothHeadsetClient proxy object.       */ -    /*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothHeadsetClient(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); - -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } - -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothHeadsetClient.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      /** @@ -444,27 +389,11 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      /*package*/ void close() {          if (VDBG) log("close()"); +        mProfileConnector.disconnect(); +    } -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } - -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothHeadsetClient getService() { +        return mProfileConnector.getService();      }      /** @@ -481,7 +410,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @UnsupportedAppUsage      public boolean connect(BluetoothDevice device) {          if (DBG) log("connect(" + device + ")"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.connect(device); @@ -504,7 +434,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @UnsupportedAppUsage      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -525,7 +456,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @Override      public List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -548,7 +480,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (VDBG) log("getDevicesMatchingStates()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -570,7 +503,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @Override      public int getConnectionState(BluetoothDevice device) {          if (VDBG) log("getConnectionState(" + device + ")"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -590,7 +524,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -612,7 +547,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); @@ -638,7 +574,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean startVoiceRecognition(BluetoothDevice device) {          if (DBG) log("startVoiceRecognition()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.startVoiceRecognition(device); @@ -663,7 +600,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean stopVoiceRecognition(BluetoothDevice device) {          if (DBG) log("stopVoiceRecognition()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.stopVoiceRecognition(device); @@ -683,7 +621,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {          if (DBG) log("getCurrentCalls()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getCurrentCalls(device); @@ -703,7 +642,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public Bundle getCurrentAgEvents(BluetoothDevice device) {          if (DBG) log("getCurrentCalls()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getCurrentAgEvents(device); @@ -727,7 +667,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @UnsupportedAppUsage      public boolean acceptCall(BluetoothDevice device, int flag) {          if (DBG) log("acceptCall()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.acceptCall(device, flag); @@ -748,7 +689,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean holdCall(BluetoothDevice device) {          if (DBG) log("holdCall()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.holdCall(device); @@ -774,7 +716,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @UnsupportedAppUsage      public boolean rejectCall(BluetoothDevice device) {          if (DBG) log("rejectCall()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.rejectCall(device); @@ -804,7 +747,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {          if (DBG) log("terminateCall()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.terminateCall(device, call); @@ -832,7 +776,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean enterPrivateMode(BluetoothDevice device, int index) {          if (DBG) log("enterPrivateMode()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.enterPrivateMode(device, index); @@ -859,7 +804,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean explicitCallTransfer(BluetoothDevice device) {          if (DBG) log("explicitCallTransfer()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.explicitCallTransfer(device); @@ -882,7 +828,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {          if (DBG) log("dial()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.dial(device, number); @@ -906,7 +853,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean sendDTMF(BluetoothDevice device, byte code) {          if (DBG) log("sendDTMF()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.sendDTMF(device, code); @@ -932,7 +880,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean getLastVoiceTagNumber(BluetoothDevice device) {          if (DBG) log("getLastVoiceTagNumber()"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getLastVoiceTagNumber(device); @@ -952,7 +901,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {      @UnsupportedAppUsage      public int getAudioState(BluetoothDevice device) {          if (VDBG) log("getAudioState"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getAudioState(device); @@ -975,7 +925,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {          if (VDBG) log("setAudioRouteAllowed"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  service.setAudioRouteAllowed(device, allowed); @@ -997,7 +948,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       */      public boolean getAudioRouteAllowed(BluetoothDevice device) {          if (VDBG) log("getAudioRouteAllowed"); -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getAudioRouteAllowed(device); @@ -1021,7 +973,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;       */      public boolean connectAudio(BluetoothDevice device) { -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.connectAudio(device); @@ -1045,7 +998,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       * otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;       */      public boolean disconnectAudio(BluetoothDevice device) { -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.disconnectAudio(device); @@ -1066,7 +1020,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {       * @return bundle of AG features; null if no service or AG not connected       */      public Bundle getCurrentAgFeatures(BluetoothDevice device) { -        final IBluetoothHeadsetClient service = mService; +        final IBluetoothHeadsetClient service = +                getService();          if (service != null && isEnabled()) {              try {                  return service.getCurrentAgFeatures(device); @@ -1080,29 +1035,6 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {          return null;      } - -    private final ServiceConnection mConnection = new ServiceConnection() { -        @Override -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            mService = IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service)); - -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT, -                        BluetoothHeadsetClient.this); -            } -        } - -        @Override -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT); -            } -        } -    }; -      private boolean isEnabled() {          return mAdapter.getState() == BluetoothAdapter.STATE_ON;      } diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java index d6edb90ca27b..60fb6fb122e3 100644 --- a/core/java/android/bluetooth/BluetoothHearingAid.java +++ b/core/java/android/bluetooth/BluetoothHearingAid.java @@ -22,21 +22,14 @@ import android.annotation.Nullable;  import android.annotation.RequiresPermission;  import android.annotation.SdkConstant;  import android.annotation.SdkConstant.SdkConstantType; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log; -import com.android.internal.annotations.GuardedBy; -  import java.util.ArrayList;  import java.util.List; -import java.util.concurrent.locks.ReentrantReadWriteLock;  /**   * This class provides the public APIs to control the Hearing Aid profile. @@ -129,97 +122,31 @@ public final class BluetoothHearingAid implements BluetoothProfile {       */      public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID; -    private Context mContext; -    private ServiceListener mServiceListener; -    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock(); -    @GuardedBy("mServiceLock") -    private IBluetoothHearingAid mService;      private BluetoothAdapter mAdapter; - -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        try { -                            mServiceLock.writeLock().lock(); -                            mService = null; -                            mContext.unbindService(mConnection); -                        } catch (Exception re) { -                            Log.e(TAG, "", re); -                        } finally { -                            mServiceLock.writeLock().unlock(); -                        } -                    } else { -                        try { -                            mServiceLock.readLock().lock(); -                            if (mService == null) { -                                if (VDBG) Log.d(TAG, "Binding service..."); -                                doBind(); -                            } -                        } catch (Exception re) { -                            Log.e(TAG, "", re); -                        } finally { -                            mServiceLock.readLock().unlock(); -                        } -                    } +    private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID, +                    "BluetoothHearingAid", IBluetoothHearingAid.class.getName()) { +                @Override +                public IBluetoothHearingAid getServiceInterface(IBinder service) { +                    return IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothHearingAid proxy object for interacting with the local       * Bluetooth Hearing Aid service.       */ -    /*package*/ BluetoothHearingAid(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothHearingAid(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } - -        doBind(); -    } - -    void doBind() { -        Intent intent = new Intent(IBluetoothHearingAid.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth Hearing Aid Service with " + intent); -            return; -        } +        mProfileConnector.connect(context, listener);      }      /*package*/ void close() { -        mServiceListener = null; -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        try { -            mServiceLock.writeLock().lock(); -            if (mService != null) { -                mService = null; -                mContext.unbindService(mConnection); -            } -        } catch (Exception re) { -            Log.e(TAG, "", re); -        } finally { -            mServiceLock.writeLock().unlock(); -        } +    private IBluetoothHearingAid getService() { +        return mProfileConnector.getService();      }      /** @@ -241,18 +168,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {       */      public boolean connect(BluetoothDevice device) {          if (DBG) log("connect(" + device + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() && isValidDevice(device)) { -                return mService.connect(device); +            if (service != null && isEnabled() && isValidDevice(device)) { +                return service.connect(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -283,18 +208,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {       */      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() && isValidDevice(device)) { -                return mService.disconnect(device); +            if (service != null && isEnabled() && isValidDevice(device)) { +                return service.disconnect(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -304,18 +227,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {      @Override      public @NonNull List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getConnectedDevices(); +            if (service != null && isEnabled()) { +                return service.getConnectedDevices();              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return new ArrayList<BluetoothDevice>();          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return new ArrayList<BluetoothDevice>(); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -326,18 +247,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {      public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(      @NonNull int[] states) {          if (VDBG) log("getDevicesMatchingStates()"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getDevicesMatchingConnectionStates(states); +            if (service != null && isEnabled()) { +                return service.getDevicesMatchingConnectionStates(states);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return new ArrayList<BluetoothDevice>();          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return new ArrayList<BluetoothDevice>(); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -348,19 +267,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {      public @BluetoothProfile.BtProfileState int getConnectionState(      @NonNull BluetoothDevice device) {          if (VDBG) log("getState(" + device + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.getConnectionState(device); +                return service.getConnectionState(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return BluetoothProfile.STATE_DISCONNECTED;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return BluetoothProfile.STATE_DISCONNECTED; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -388,20 +305,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {       */      public boolean setActiveDevice(@Nullable BluetoothDevice device) {          if (DBG) log("setActiveDevice(" + device + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            if (service != null && isEnabled()                      && ((device == null) || isValidDevice(device))) { -                mService.setActiveDevice(device); +                service.setActiveDevice(device);                  return true;              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -419,18 +334,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {      @RequiresPermission(Manifest.permission.BLUETOOTH)      public List<BluetoothDevice> getActiveDevices() {          if (VDBG) log("getActiveDevices()"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getActiveDevices(); +            if (service != null && isEnabled()) { +                return service.getActiveDevices();              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return new ArrayList<>();          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return new ArrayList<>(); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -451,23 +364,21 @@ public final class BluetoothHearingAid implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            if (service != null && isEnabled()                      && isValidDevice(device)) {                  if (priority != BluetoothProfile.PRIORITY_OFF                          && priority != BluetoothProfile.PRIORITY_ON) {                      return false;                  } -                return mService.setPriority(device, priority); +                return service.setPriority(device, priority);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return false;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return false; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -485,19 +396,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {      @RequiresPermission(Manifest.permission.BLUETOOTH)      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.getPriority(device); +                return service.getPriority(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return BluetoothProfile.PRIORITY_OFF;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return BluetoothProfile.PRIORITY_OFF; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -536,18 +445,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {          if (VDBG) {              log("getVolume()");          } +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled()) { -                return mService.getVolume(); +            if (service != null && isEnabled()) { +                return service.getVolume();              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return 0;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return 0; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -567,21 +474,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {      public void adjustVolume(int direction) {          if (DBG) log("adjustVolume(" + direction + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); - -            if (mService == null) { +            if (service == null) {                  Log.w(TAG, "Proxy not attached to service");                  return;              }              if (!isEnabled()) return; -            mService.adjustVolume(direction); +            service.adjustVolume(direction);          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -594,20 +498,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {      public void setVolume(int volume) {          if (DBG) Log.d(TAG, "setVolume(" + volume + ")"); +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService == null) { +            if (service == null) {                  Log.w(TAG, "Proxy not attached to service");                  return;              }              if (!isEnabled()) return; -            mService.setVolume(volume); +            service.setVolume(volume);          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -623,21 +525,19 @@ public final class BluetoothHearingAid implements BluetoothProfile {          if (VDBG) {              log("getCustomerId(" + device + ")");          } +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService == null) { +            if (service == null) {                  Log.w(TAG, "Proxy not attached to service");                  return HI_SYNC_ID_INVALID;              }              if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID; -            return mService.getHiSyncId(device); +            return service.getHiSyncId(device);          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return HI_SYNC_ID_INVALID; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -653,19 +553,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {          if (VDBG) {              log("getDeviceSide(" + device + ")");          } +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.getDeviceSide(device); +                return service.getDeviceSide(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return SIDE_LEFT;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return SIDE_LEFT; -        } finally { -            mServiceLock.readLock().unlock();          }      } @@ -681,52 +579,20 @@ public final class BluetoothHearingAid implements BluetoothProfile {          if (VDBG) {              log("getDeviceMode(" + device + ")");          } +        final IBluetoothHearingAid service = getService();          try { -            mServiceLock.readLock().lock(); -            if (mService != null && isEnabled() +            if (service != null && isEnabled()                      && isValidDevice(device)) { -                return mService.getDeviceMode(device); +                return service.getDeviceMode(device);              } -            if (mService == null) Log.w(TAG, "Proxy not attached to service"); +            if (service == null) Log.w(TAG, "Proxy not attached to service");              return MODE_MONAURAL;          } catch (RemoteException e) {              Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));              return MODE_MONAURAL; -        } finally { -            mServiceLock.readLock().unlock();          }      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            try { -                mServiceLock.writeLock().lock(); -                mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service)); -            } finally { -                mServiceLock.writeLock().unlock(); -            } - -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID, -                                                    BluetoothHearingAid.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            try { -                mServiceLock.writeLock().lock(); -                mService = null; -            } finally { -                mServiceLock.writeLock().unlock(); -            } -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID); -            } -        } -    }; -      private boolean isEnabled() {          if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;          return false; diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java index e44f36e90c75..e9b0be2c4cd6 100644 --- a/core/java/android/bluetooth/BluetoothHidDevice.java +++ b/core/java/android/bluetooth/BluetoothHidDevice.java @@ -18,13 +18,10 @@ package android.bluetooth;  import android.annotation.SdkConstant;  import android.annotation.SdkConstant.SdkConstantType; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; +import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -328,11 +325,6 @@ public final class BluetoothHidDevice implements BluetoothProfile {          }      } -    private Context mContext; -    private ServiceListener mServiceListener; -    private volatile IBluetoothHidDevice mService; -    private BluetoothAdapter mAdapter; -      private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {          private final Executor mExecutor; @@ -386,114 +378,33 @@ public final class BluetoothHidDevice implements BluetoothProfile {          }      } -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { - -                public void onBluetoothStateChange(boolean up) { -                    Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    synchronized (mConnection) { -                        if (up) { -                            try { -                                if (mService == null) { -                                    Log.d(TAG, "Binding HID Device service..."); -                                    doBind(); -                                } -                            } catch (IllegalStateException e) { -                                Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev " -                                        + "service: ", e); -                            } catch (SecurityException e) { -                                Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev " -                                        + "service: ", e); -                            } -                        } else { -                            Log.d(TAG, "Unbinding service..."); -                            doUnbind(); -                        } -                    } -                } -            }; - -    private final ServiceConnection mConnection = -            new ServiceConnection() { -                public void onServiceConnected(ComponentName className, IBinder service) { -                    Log.d(TAG, "onServiceConnected()"); -                    mService = IBluetoothHidDevice.Stub.asInterface(service); -                    if (mServiceListener != null) { -                        mServiceListener.onServiceConnected( -                                BluetoothProfile.HID_DEVICE, BluetoothHidDevice.this); -                    } -                } - -                public void onServiceDisconnected(ComponentName className) { -                    Log.d(TAG, "onServiceDisconnected()"); -                    mService = null; -                    if (mServiceListener != null) { -                        mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE); -                    } +    private BluetoothAdapter mAdapter; +    private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE, +                    "BluetoothHidDevice", IBluetoothHidDevice.class.getName()) { +                @Override +                public IBluetoothHidDevice getServiceInterface(IBinder service) { +                    return IBluetoothHidDevice.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      BluetoothHidDevice(Context context, ServiceListener listener) { -        mContext = context; -        mServiceListener = listener;          mAdapter = BluetoothAdapter.getDefaultAdapter(); - -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                e.printStackTrace(); -            } -        } - -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothHidDevice.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent); -            return false; -        } -        Log.d(TAG, "Bound to HID Device Service"); -        return true; -    } - -    void doUnbind() { -        if (mService != null) { -            mService = null; -            try { -                mContext.unbindService(mConnection); -            } catch (IllegalArgumentException e) { -                Log.e(TAG, "Unable to unbind HidDevService", e); -            } -        } +        mProfileConnector.connect(context, listener);      }      void close() { -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                e.printStackTrace(); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            doUnbind(); -        } -        mServiceListener = null; +    private IBluetoothHidDevice getService() { +        return mProfileConnector.getService();      }      /** {@inheritDoc} */      @Override      public List<BluetoothDevice> getConnectedDevices() { -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  return service.getConnectedDevices(); @@ -510,7 +421,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      /** {@inheritDoc} */      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -527,7 +438,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      /** {@inheritDoc} */      @Override      public int getConnectionState(BluetoothDevice device) { -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  return service.getConnectionState(device); @@ -584,7 +495,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {              throw new IllegalArgumentException("callback parameter cannot be null");          } -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  CallbackWrapper cbw = new CallbackWrapper(executor, callback); @@ -612,7 +523,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      public boolean unregisterApp() {          boolean result = false; -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  result = service.unregisterApp(); @@ -637,7 +548,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      public boolean sendReport(BluetoothDevice device, int id, byte[] data) {          boolean result = false; -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  result = service.sendReport(device, id, data); @@ -663,7 +574,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {          boolean result = false; -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  result = service.replyReport(device, type, id, data); @@ -687,7 +598,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      public boolean reportError(BluetoothDevice device, byte error) {          boolean result = false; -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  result = service.reportError(device, error); @@ -708,7 +619,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {       * {@hide}       */      public String getUserAppName() { -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try { @@ -734,7 +645,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      public boolean connect(BluetoothDevice device) {          boolean result = false; -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  result = service.connect(device); @@ -758,7 +669,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {      public boolean disconnect(BluetoothDevice device) {          boolean result = false; -        final IBluetoothHidDevice service = mService; +        final IBluetoothHidDevice service = getService();          if (service != null) {              try {                  result = service.disconnect(device); diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java index 7c925a1cb5ef..4afb382c0660 100644 --- a/core/java/android/bluetooth/BluetoothHidHost.java +++ b/core/java/android/bluetooth/BluetoothHidHost.java @@ -18,14 +18,10 @@ package android.bluetooth;  import android.annotation.SdkConstant;  import android.annotation.SdkConstant.SdkConstantType; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -220,97 +216,32 @@ public final class BluetoothHidHost implements BluetoothProfile {      public static final String EXTRA_IDLE_TIME =              "android.bluetooth.BluetoothHidHost.extra.IDLE_TIME"; -    private Context mContext; -    private ServiceListener mServiceListener;      private BluetoothAdapter mAdapter; -    private volatile IBluetoothHidHost mService; - -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                if (mService != null) { -                                    mService = null; -                                    mContext.unbindService(mConnection); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST, +                    "BluetoothHidHost", IBluetoothHidHost.class.getName()) { +                @Override +                public IBluetoothHidHost getServiceInterface(IBinder service) { +                    return IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothHidHost proxy object for interacting with the local       * Bluetooth Service which handles the InputDevice profile       */ -    /*package*/ BluetoothHidHost(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothHidHost(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); - -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } - -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothHidHost.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      /*package*/ void close() {          if (VDBG) log("close()"); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothHidHost getService() { +        return mProfileConnector.getService();      }      /** @@ -334,7 +265,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean connect(BluetoothDevice device) {          if (DBG) log("connect(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.connect(device); @@ -374,7 +305,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -393,7 +324,7 @@ public final class BluetoothHidHost implements BluetoothProfile {      @Override      public List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -412,7 +343,7 @@ public final class BluetoothHidHost implements BluetoothProfile {      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (VDBG) log("getDevicesMatchingStates()"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -431,7 +362,7 @@ public final class BluetoothHidHost implements BluetoothProfile {      @Override      public int getConnectionState(BluetoothDevice device) {          if (VDBG) log("getState(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -461,7 +392,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -493,7 +424,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); @@ -506,26 +437,6 @@ public final class BluetoothHidHost implements BluetoothProfile {          return BluetoothProfile.PRIORITY_OFF;      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            mService = IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service)); - -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.HID_HOST, -                        BluetoothHidHost.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.HID_HOST); -            } -        } -    }; -      private boolean isEnabled() {          return mAdapter.getState() == BluetoothAdapter.STATE_ON;      } @@ -545,7 +456,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean virtualUnplug(BluetoothDevice device) {          if (DBG) log("virtualUnplug(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.virtualUnplug(device); @@ -571,7 +482,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean getProtocolMode(BluetoothDevice device) {          if (VDBG) log("getProtocolMode(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getProtocolMode(device); @@ -595,7 +506,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {          if (DBG) log("setProtocolMode(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.setProtocolMode(device, protocolMode); @@ -626,7 +537,7 @@ public final class BluetoothHidHost implements BluetoothProfile {              log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId                      + "bufferSize=" + bufferSize);          } -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getReport(device, reportType, reportId, bufferSize); @@ -652,7 +563,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean setReport(BluetoothDevice device, byte reportType, String report) {          if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.setReport(device, reportType, report); @@ -677,7 +588,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean sendData(BluetoothDevice device, String report) {          if (DBG) log("sendData(" + device + "), report=" + report); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.sendData(device, report); @@ -701,7 +612,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean getIdleTime(BluetoothDevice device) {          if (DBG) log("getIdletime(" + device + ")"); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getIdleTime(device); @@ -726,7 +637,7 @@ public final class BluetoothHidHost implements BluetoothProfile {       */      public boolean setIdleTime(BluetoothDevice device, byte idleTime) {          if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime); -        final IBluetoothHidHost service = mService; +        final IBluetoothHidHost service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.setIdleTime(device, idleTime); diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java index fc5f830a8940..dd2f150ad4eb 100644 --- a/core/java/android/bluetooth/BluetoothMap.java +++ b/core/java/android/bluetooth/BluetoothMap.java @@ -17,14 +17,10 @@  package android.bluetooth;  import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -45,11 +41,6 @@ public final class BluetoothMap implements BluetoothProfile {      public static final String ACTION_CONNECTION_STATE_CHANGED =              "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; -    private volatile IBluetoothMap mService; -    private final Context mContext; -    private ServiceListener mServiceListener; -    private BluetoothAdapter mAdapter; -      /** There was an error trying to obtain the state */      public static final int STATE_ERROR = -1; @@ -58,64 +49,23 @@ public final class BluetoothMap implements BluetoothProfile {      /** Connection canceled before completion. */      public static final int RESULT_CANCELED = 2; -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private BluetoothAdapter mAdapter; +    private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.MAP, +                    "BluetoothMap", IBluetoothMap.class.getName()) { +                @Override +                public IBluetoothMap getServiceInterface(IBinder service) { +                    return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothMap proxy object.       */ -    /*package*/ BluetoothMap(Context context, ServiceListener l) { +    /*package*/ BluetoothMap(Context context, ServiceListener listener) {          if (DBG) Log.d(TAG, "Create BluetoothMap proxy object"); -        mContext = context; -        mServiceListener = l;          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothMap.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      protected void finalize() throws Throwable { @@ -133,26 +83,11 @@ public final class BluetoothMap implements BluetoothProfile {       * are ok.       */      public synchronized void close() { -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothMap getService() { +        return mProfileConnector.getService();      }      /** @@ -163,7 +98,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public int getState() {          if (VDBG) log("getState()"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null) {              try {                  return service.getState(); @@ -185,7 +120,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public BluetoothDevice getClient() {          if (VDBG) log("getClient()"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null) {              try {                  return service.getClient(); @@ -206,7 +141,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public boolean isConnected(BluetoothDevice device) {          if (VDBG) log("isConnected(" + device + ")"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null) {              try {                  return service.isConnected(device); @@ -238,7 +173,7 @@ public final class BluetoothMap implements BluetoothProfile {      @UnsupportedAppUsage      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -279,7 +214,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public List<BluetoothDevice> getConnectedDevices() {          if (DBG) log("getConnectedDevices()"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -299,7 +234,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (DBG) log("getDevicesMatchingStates()"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -319,7 +254,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public int getConnectionState(BluetoothDevice device) {          if (DBG) log("getConnectionState(" + device + ")"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -345,7 +280,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -374,7 +309,7 @@ public final class BluetoothMap implements BluetoothProfile {       */      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")"); -        final IBluetoothMap service = mService; +        final IBluetoothMap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); @@ -387,24 +322,6 @@ public final class BluetoothMap implements BluetoothProfile {          return PRIORITY_OFF;      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) log("Proxy object connected"); -            mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service)); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) log("Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.MAP); -            } -        } -    }; -      private static void log(String msg) {          Log.d(TAG, msg);      } diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java index 1c82e1984b66..ec0180c5adde 100644 --- a/core/java/android/bluetooth/BluetoothMapClient.java +++ b/core/java/android/bluetooth/BluetoothMapClient.java @@ -18,14 +18,11 @@ package android.bluetooth;  import android.annotation.UnsupportedAppUsage;  import android.app.PendingIntent; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.net.Uri; +import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -61,11 +58,6 @@ public final class BluetoothMapClient implements BluetoothProfile {      public static final String EXTRA_SENDER_CONTACT_NAME =              "android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME"; -    private volatile IBluetoothMapClient mService; -    private final Context mContext; -    private ServiceListener mServiceListener; -    private BluetoothAdapter mAdapter; -      /** There was an error trying to obtain the state */      public static final int STATE_ERROR = -1; @@ -76,64 +68,23 @@ public final class BluetoothMapClient implements BluetoothProfile {      private static final int UPLOADING_FEATURE_BITMASK = 0x08; -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private BluetoothAdapter mAdapter; +    private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT, +                    "BluetoothMapClient", IBluetoothMapClient.class.getName()) { +                @Override +                public IBluetoothMapClient getServiceInterface(IBinder service) { +                    return IBluetoothMapClient.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothMapClient proxy object.       */ -    /*package*/ BluetoothMapClient(Context context, ServiceListener l) { +    /*package*/ BluetoothMapClient(Context context, ServiceListener listener) {          if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object"); -        mContext = context; -        mServiceListener = l;          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothMapClient.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      protected void finalize() throws Throwable { @@ -151,26 +102,11 @@ public final class BluetoothMapClient implements BluetoothProfile {       * are ok.       */      public void close() { -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothMapClient getService() { +        return mProfileConnector.getService();      }      /** @@ -180,7 +116,7 @@ public final class BluetoothMapClient implements BluetoothProfile {       */      public boolean isConnected(BluetoothDevice device) {          if (VDBG) Log.d(TAG, "isConnected(" + device + ")"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null) {              try {                  return service.isConnected(device); @@ -200,7 +136,7 @@ public final class BluetoothMapClient implements BluetoothProfile {       */      public boolean connect(BluetoothDevice device) {          if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null) {              try {                  return service.connect(device); @@ -222,7 +158,7 @@ public final class BluetoothMapClient implements BluetoothProfile {       */      public boolean disconnect(BluetoothDevice device) {          if (DBG) Log.d(TAG, "disconnect(" + device + ")"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -242,7 +178,7 @@ public final class BluetoothMapClient implements BluetoothProfile {      @Override      public List<BluetoothDevice> getConnectedDevices() {          if (DBG) Log.d(TAG, "getConnectedDevices()"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -263,7 +199,7 @@ public final class BluetoothMapClient implements BluetoothProfile {      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (DBG) Log.d(TAG, "getDevicesMatchingStates()"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -284,7 +220,7 @@ public final class BluetoothMapClient implements BluetoothProfile {      @Override      public int getConnectionState(BluetoothDevice device) {          if (DBG) Log.d(TAG, "getConnectionState(" + device + ")"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -308,7 +244,7 @@ public final class BluetoothMapClient implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -337,7 +273,7 @@ public final class BluetoothMapClient implements BluetoothProfile {       */      public int getPriority(BluetoothDevice device) {          if (VDBG) Log.d(TAG, "getPriority(" + device + ")"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); @@ -366,7 +302,7 @@ public final class BluetoothMapClient implements BluetoothProfile {      public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,              PendingIntent sentIntent, PendingIntent deliveredIntent) {          if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent); @@ -386,7 +322,7 @@ public final class BluetoothMapClient implements BluetoothProfile {       */      public boolean getUnreadMessages(BluetoothDevice device) {          if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")"); -        final IBluetoothMapClient service = mService; +        final IBluetoothMapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getUnreadMessages(device); @@ -406,34 +342,16 @@ public final class BluetoothMapClient implements BluetoothProfile {       *         MapSupportedFeatures field is set. False is returned otherwise.       */      public boolean isUploadingSupported(BluetoothDevice device) { +        final IBluetoothMapClient service = getService();          try { -            return (mService != null && isEnabled() && isValidDevice(device)) -                && ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0); +            return (service != null && isEnabled() && isValidDevice(device)) +                && ((service.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);          } catch (RemoteException e) {              Log.e(TAG, e.getMessage());          }          return false;      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "Proxy object connected"); -            mService = IBluetoothMapClient.Stub.asInterface(service); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT, -                        BluetoothMapClient.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT); -            } -        } -    }; -      private boolean isEnabled() {          BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();          if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true; diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java index 8923d734c844..fb78789ba8ad 100644 --- a/core/java/android/bluetooth/BluetoothPan.java +++ b/core/java/android/bluetooth/BluetoothPan.java @@ -19,14 +19,10 @@ package android.bluetooth;  import android.annotation.SdkConstant;  import android.annotation.SdkConstant.SdkConstantType;  import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -122,108 +118,42 @@ public final class BluetoothPan implements BluetoothProfile {       */      public static final int PAN_OPERATION_SUCCESS = 1004; -    private Context mContext; -    private ServiceListener mServiceListener;      private BluetoothAdapter mAdapter; -    private volatile IBluetoothPan mPanService; +    private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.PAN, +                    "BluetoothPan", IBluetoothPan.class.getName()) { +                @Override +                public IBluetoothPan getServiceInterface(IBinder service) { +                    return IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service)); +                } +    }; +      /**       * Create a BluetoothPan proxy object for interacting with the local       * Bluetooth Service which handles the Pan profile       */      @UnsupportedAppUsage -    /*package*/ BluetoothPan(Context context, ServiceListener l) { -        mContext = context; -        mServiceListener = l; +    /*package*/ BluetoothPan(Context context, ServiceListener listener) {          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        try { -            mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback); -        } catch (RemoteException re) { -            Log.w(TAG, "Unable to register BluetoothStateChangeCallback", re); -        } -        if (VDBG) Log.d(TAG, "BluetoothPan() call bindService"); -        doBind(); -    } - -    @UnsupportedAppUsage -    boolean doBind() { -        Intent intent = new Intent(IBluetoothPan.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      @UnsupportedAppUsage      /*package*/ void close() {          if (VDBG) log("close()"); +        mProfileConnector.disconnect(); +    } -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mStateChangeCallback); -            } catch (RemoteException re) { -                Log.w(TAG, "Unable to unregister BluetoothStateChangeCallback", re); -            } -        } - -        synchronized (mConnection) { -            if (mPanService != null) { -                try { -                    mPanService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothPan getService() { +        return mProfileConnector.getService();      } +      protected void finalize() {          close();      } -    private final IBluetoothStateChangeCallback mStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { - -                @Override -                public void onBluetoothStateChange(boolean on) { -                    // Handle enable request to bind again. -                    Log.d(TAG, "onBluetoothStateChange on: " + on); -                    if (on) { -                        try { -                            if (mPanService == null) { -                                if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()"); -                                doBind(); -                            } - -                        } catch (IllegalStateException e) { -                            Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ", -                                    e); - -                        } catch (SecurityException e) { -                            Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ", -                                    e); -                        } -                    } else { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mPanService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } -                } -            }; -      /**       * Initiate connection to a profile of the remote bluetooth device.       * @@ -244,7 +174,7 @@ public final class BluetoothPan implements BluetoothProfile {      @UnsupportedAppUsage      public boolean connect(BluetoothDevice device) {          if (DBG) log("connect(" + device + ")"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.connect(device); @@ -285,7 +215,7 @@ public final class BluetoothPan implements BluetoothProfile {      @UnsupportedAppUsage      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -304,7 +234,7 @@ public final class BluetoothPan implements BluetoothProfile {      @Override      public List<BluetoothDevice> getConnectedDevices() {          if (VDBG) log("getConnectedDevices()"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -323,7 +253,7 @@ public final class BluetoothPan implements BluetoothProfile {      @Override      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (VDBG) log("getDevicesMatchingStates()"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -342,7 +272,7 @@ public final class BluetoothPan implements BluetoothProfile {      @Override      public int getConnectionState(BluetoothDevice device) {          if (VDBG) log("getState(" + device + ")"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -358,7 +288,7 @@ public final class BluetoothPan implements BluetoothProfile {      @UnsupportedAppUsage      public void setBluetoothTethering(boolean value) {          if (DBG) log("setBluetoothTethering(" + value + ")"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled()) {              try {                  service.setBluetoothTethering(value); @@ -371,7 +301,7 @@ public final class BluetoothPan implements BluetoothProfile {      @UnsupportedAppUsage      public boolean isTetheringOn() {          if (VDBG) log("isTetheringOn()"); -        final IBluetoothPan service = mPanService; +        final IBluetoothPan service = getService();          if (service != null && isEnabled()) {              try {                  return service.isTetheringOn(); @@ -382,25 +312,6 @@ public final class BluetoothPan implements BluetoothProfile {          return false;      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected"); -            mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service)); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.PAN, -                        BluetoothPan.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected"); -            mPanService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.PAN); -            } -        } -    }; -      @UnsupportedAppUsage      private boolean isEnabled() {          return mAdapter.getState() == BluetoothAdapter.STATE_ON; diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java index 359bec686a8a..d94c65742e6c 100644 --- a/core/java/android/bluetooth/BluetoothPbap.java +++ b/core/java/android/bluetooth/BluetoothPbap.java @@ -118,28 +118,9 @@ public class BluetoothPbap implements BluetoothProfile {                  public void onBluetoothStateChange(boolean up) {                      log("onBluetoothStateChange: up=" + up);                      if (!up) { -                        log("Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                if (mService != null) { -                                    mService = null; -                                    mContext.unbindService(mConnection); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } +                        doUnbind();                      } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    log("Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } +                        doBind();                      }                  }              }; @@ -155,25 +136,51 @@ public class BluetoothPbap implements BluetoothProfile {          if (mgr != null) {              try {                  mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); +            } catch (RemoteException re) { +                Log.e(TAG, "", re);              }          }          doBind();      }      boolean doBind() { -        Intent intent = new Intent(IBluetoothPbap.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent); -            return false; +        synchronized (mConnection) { +            try { +                if (mService == null) { +                    log("Binding service..."); +                    Intent intent = new Intent(IBluetoothPbap.class.getName()); +                    ComponentName comp = intent.resolveSystemService( +                            mContext.getPackageManager(), 0); +                    intent.setComponent(comp); +                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, +                            UserHandle.CURRENT_OR_SELF)) { +                        Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent); +                        return false; +                    } +                } +            } catch (SecurityException se) { +                Log.e(TAG, "", se); +                return false; +            }          }          return true;      } +    private void doUnbind() { +        synchronized (mConnection) { +            if (mService != null) { +                log("Unbinding service..."); +                try { +                    mContext.unbindService(mConnection); +                } catch (IllegalArgumentException ie) { +                    Log.e(TAG, "", ie); +                } finally { +                    mService = null; +                } +            } +        } +    } +      protected void finalize() throws Throwable {          try {              close(); @@ -193,21 +200,11 @@ public class BluetoothPbap implements BluetoothProfile {          if (mgr != null) {              try {                  mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } - -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } +            } catch (RemoteException re) { +                Log.e(TAG, "", re);              }          } +        doUnbind();          mServiceListener = null;      } @@ -313,7 +310,7 @@ public class BluetoothPbap implements BluetoothProfile {          public void onServiceDisconnected(ComponentName className) {              log("Proxy object disconnected"); -            mService = null; +            doUnbind();              if (mServiceListener != null) {                  mServiceListener.onServiceDisconnected();              } diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java index cbc96c073338..d70e1e7f3f5f 100644 --- a/core/java/android/bluetooth/BluetoothPbapClient.java +++ b/core/java/android/bluetooth/BluetoothPbapClient.java @@ -16,14 +16,10 @@  package android.bluetooth; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -43,11 +39,6 @@ public final class BluetoothPbapClient implements BluetoothProfile {      public static final String ACTION_CONNECTION_STATE_CHANGED =              "android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED"; -    private volatile IBluetoothPbapClient mService; -    private final Context mContext; -    private ServiceListener mServiceListener; -    private BluetoothAdapter mAdapter; -      /** There was an error trying to obtain the state */      public static final int STATE_ERROR = -1; @@ -56,72 +47,25 @@ public final class BluetoothPbapClient implements BluetoothProfile {      /** Connection canceled before completion. */      public static final int RESULT_CANCELED = 2; -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) { -                        Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up); -                    } -                    if (!up) { -                        if (VDBG) { -                            Log.d(TAG, "Unbinding service..."); -                        } -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) { -                                        Log.d(TAG, "Binding service..."); -                                    } -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private BluetoothAdapter mAdapter; +    private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT, +                    "BluetoothPbapClient", IBluetoothPbapClient.class.getName()) { +                @Override +                public IBluetoothPbapClient getServiceInterface(IBinder service) { +                    return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothPbapClient proxy object.       */ -    BluetoothPbapClient(Context context, ServiceListener l) { +    BluetoothPbapClient(Context context, ServiceListener listener) {          if (DBG) {              Log.d(TAG, "Create BluetoothPbapClient proxy object");          } -        mContext = context; -        mServiceListener = l;          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } -        doBind(); -    } - -    private boolean doBind() { -        Intent intent = new Intent(IBluetoothPbapClient.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      protected void finalize() throws Throwable { @@ -139,26 +83,11 @@ public final class BluetoothPbapClient implements BluetoothProfile {       * are ok.       */      public synchronized void close() { -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothPbapClient getService() { +        return mProfileConnector.getService();      }      /** @@ -174,7 +103,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (DBG) {              log("connect(" + device + ") for PBAP Client.");          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.connect(device); @@ -199,7 +128,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (DBG) {              log("disconnect(" + device + ")" + new Exception());          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  service.disconnect(device); @@ -226,7 +155,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (DBG) {              log("getConnectedDevices()");          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -251,7 +180,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (DBG) {              log("getDevicesMatchingStates()");          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -276,7 +205,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (DBG) {              log("getConnectionState(" + device + ")");          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -291,29 +220,6 @@ public final class BluetoothPbapClient implements BluetoothProfile {          return BluetoothProfile.STATE_DISCONNECTED;      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) { -                log("Proxy object connected"); -            } -            mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service)); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT, -                        BluetoothPbapClient.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) { -                log("Proxy object disconnected"); -            } -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT); -            } -        } -    }; -      private static void log(String msg) {          Log.d(TAG, msg);      } @@ -346,7 +252,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (DBG) {              log("setPriority(" + device + ", " + priority + ")");          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -379,7 +285,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {          if (VDBG) {              log("getPriority(" + device + ")");          } -        final IBluetoothPbapClient service = mService; +        final IBluetoothPbapClient service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java new file mode 100644 index 000000000000..d9987249a6e2 --- /dev/null +++ b/core/java/android/bluetooth/BluetoothProfileConnector.java @@ -0,0 +1,166 @@ +/* + * Copyright 2019 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 android.bluetooth; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.util.Log; + +/** + * Connector for Bluetooth profile proxies to bind manager service and + * profile services + * @param <T> The Bluetooth profile interface for this connection. + * @hide + */ +public abstract class BluetoothProfileConnector<T> { +    private int mProfileId; +    private BluetoothProfile.ServiceListener mServiceListener; +    private BluetoothProfile mProfileProxy; +    private Context mContext; +    private String mProfileName; +    private String mServiceName; +    private volatile T mService; + +    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = +            new IBluetoothStateChangeCallback.Stub() { +        public void onBluetoothStateChange(boolean up) { +            if (up) { +                doBind(); +            } else { +                doUnbind(); +            } +        } +    }; + +    private final ServiceConnection mConnection = new ServiceConnection() { +        public void onServiceConnected(ComponentName className, IBinder service) { +            logDebug("Proxy object connected"); +            mService = getServiceInterface(service); + +            if (mServiceListener != null) { +                mServiceListener.onServiceConnected(mProfileId, mProfileProxy); +            } +        } + +        public void onServiceDisconnected(ComponentName className) { +            logDebug("Proxy object disconnected"); +            doUnbind(); +            if (mServiceListener != null) { +                mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP); +            } +        } +    }; + +    BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName, +            String serviceName) { +        mProfileId = profileId; +        mProfileProxy = profile; +        mProfileName = profileName; +        mServiceName = serviceName; +    } + +    private boolean doBind() { +        synchronized (mConnection) { +            if (mService == null) { +                logDebug("Binding service..."); +                try { +                    Intent intent = new Intent(mServiceName); +                    ComponentName comp = intent.resolveSystemService( +                            mContext.getPackageManager(), 0); +                    intent.setComponent(comp); +                    if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, +                            UserHandle.CURRENT_OR_SELF)) { +                        logError("Could not bind to Bluetooth Service with " + intent); +                        return false; +                    } +                } catch (SecurityException se) { +                    logError("Failed to bind service. " + se); +                    return false; +                } +            } +        } +        return true; +    } + +    private void doUnbind() { +        synchronized (mConnection) { +            if (mService != null) { +                logDebug("Unbinding service..."); +                try { +                    mContext.unbindService(mConnection); +                } catch (IllegalArgumentException ie) { +                    logError("Unable to unbind service: " + ie); +                } finally { +                    mService = null; +                } +            } +        } +    } + +    void connect(Context context, BluetoothProfile.ServiceListener listener) { +        mContext = context; +        mServiceListener = listener; +        IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager(); +        if (mgr != null) { +            try { +                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); +            } catch (RemoteException re) { +                logError("Failed to register state change callback. " + re); +            } +        } +        doBind(); +    } + +    void disconnect() { +        mServiceListener = null; +        IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager(); +        if (mgr != null) { +            try { +                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); +            } catch (RemoteException re) { +                logError("Failed to unregister state change callback" + re); +            } +        } +        doUnbind(); +    } + +    T getService() { +        return mService; +    } + +    /** +     * This abstract function is used to implement method to get the +     * connected Bluetooth service interface. +     * @param service the connected binder service. +     * @return T the binder interface of {@code service}. +     * @hide +     */ +    public abstract T getServiceInterface(IBinder service); + +    private void logDebug(String log) { +        Log.d(mProfileName, log); +    } + +    private void logError(String log) { +        Log.e(mProfileName, log); +    } +} diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java index ebf6bed54475..e0610c890559 100644 --- a/core/java/android/bluetooth/BluetoothSap.java +++ b/core/java/android/bluetooth/BluetoothSap.java @@ -17,14 +17,10 @@  package android.bluetooth;  import android.annotation.UnsupportedAppUsage; -import android.content.ComponentName;  import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection;  import android.os.Binder;  import android.os.IBinder;  import android.os.RemoteException; -import android.os.UserHandle;  import android.util.Log;  import java.util.ArrayList; @@ -70,11 +66,6 @@ public final class BluetoothSap implements BluetoothProfile {      public static final String ACTION_CONNECTION_STATE_CHANGED =              "android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED"; -    private volatile IBluetoothSap mService; -    private final Context mContext; -    private ServiceListener mServiceListener; -    private BluetoothAdapter mAdapter; -      /**       * There was an error trying to obtain the state.       * @@ -96,64 +87,23 @@ public final class BluetoothSap implements BluetoothProfile {       */      public static final int RESULT_CANCELED = 2; -    private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback = -            new IBluetoothStateChangeCallback.Stub() { -                public void onBluetoothStateChange(boolean up) { -                    if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); -                    if (!up) { -                        if (VDBG) Log.d(TAG, "Unbinding service..."); -                        synchronized (mConnection) { -                            try { -                                mService = null; -                                mContext.unbindService(mConnection); -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } else { -                        synchronized (mConnection) { -                            try { -                                if (mService == null) { -                                    if (VDBG) Log.d(TAG, "Binding service..."); -                                    doBind(); -                                } -                            } catch (Exception re) { -                                Log.e(TAG, "", re); -                            } -                        } -                    } +    private BluetoothAdapter mAdapter; +    private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector = +            new BluetoothProfileConnector(this, BluetoothProfile.SAP, +                    "BluetoothSap", IBluetoothSap.class.getName()) { +                @Override +                public IBluetoothSap getServiceInterface(IBinder service) { +                    return IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));                  } -            }; +    };      /**       * Create a BluetoothSap proxy object.       */ -    /*package*/ BluetoothSap(Context context, ServiceListener l) { +    /*package*/ BluetoothSap(Context context, ServiceListener listener) {          if (DBG) Log.d(TAG, "Create BluetoothSap proxy object"); -        mContext = context; -        mServiceListener = l;          mAdapter = BluetoothAdapter.getDefaultAdapter(); -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.registerStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (RemoteException e) { -                Log.e(TAG, "", e); -            } -        } -        doBind(); -    } - -    boolean doBind() { -        Intent intent = new Intent(IBluetoothSap.class.getName()); -        ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); -        intent.setComponent(comp); -        if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, -                UserHandle.CURRENT_OR_SELF)) { -            Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent); -            return false; -        } -        return true; +        mProfileConnector.connect(context, listener);      }      protected void finalize() throws Throwable { @@ -173,26 +123,11 @@ public final class BluetoothSap implements BluetoothProfile {       * @hide       */      public synchronized void close() { -        IBluetoothManager mgr = mAdapter.getBluetoothManager(); -        if (mgr != null) { -            try { -                mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback); -            } catch (Exception e) { -                Log.e(TAG, "", e); -            } -        } +        mProfileConnector.disconnect(); +    } -        synchronized (mConnection) { -            if (mService != null) { -                try { -                    mService = null; -                    mContext.unbindService(mConnection); -                } catch (Exception re) { -                    Log.e(TAG, "", re); -                } -            } -        } -        mServiceListener = null; +    private IBluetoothSap getService() { +        return mProfileConnector.getService();      }      /** @@ -204,7 +139,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public int getState() {          if (VDBG) log("getState()"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null) {              try {                  return service.getState(); @@ -227,7 +162,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public BluetoothDevice getClient() {          if (VDBG) log("getClient()"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null) {              try {                  return service.getClient(); @@ -250,7 +185,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public boolean isConnected(BluetoothDevice device) {          if (VDBG) log("isConnected(" + device + ")"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null) {              try {                  return service.isConnected(device); @@ -285,7 +220,7 @@ public final class BluetoothSap implements BluetoothProfile {      @UnsupportedAppUsage      public boolean disconnect(BluetoothDevice device) {          if (DBG) log("disconnect(" + device + ")"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.disconnect(device); @@ -306,7 +241,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public List<BluetoothDevice> getConnectedDevices() {          if (DBG) log("getConnectedDevices()"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null && isEnabled()) {              try {                  return service.getConnectedDevices(); @@ -327,7 +262,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {          if (DBG) log("getDevicesMatchingStates()"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null && isEnabled()) {              try {                  return service.getDevicesMatchingConnectionStates(states); @@ -348,7 +283,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public int getConnectionState(BluetoothDevice device) {          if (DBG) log("getConnectionState(" + device + ")"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getConnectionState(device); @@ -373,7 +308,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public boolean setPriority(BluetoothDevice device, int priority) {          if (DBG) log("setPriority(" + device + ", " + priority + ")"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              if (priority != BluetoothProfile.PRIORITY_OFF                      && priority != BluetoothProfile.PRIORITY_ON) { @@ -399,7 +334,7 @@ public final class BluetoothSap implements BluetoothProfile {       */      public int getPriority(BluetoothDevice device) {          if (VDBG) log("getPriority(" + device + ")"); -        final IBluetoothSap service = mService; +        final IBluetoothSap service = getService();          if (service != null && isEnabled() && isValidDevice(device)) {              try {                  return service.getPriority(device); @@ -412,24 +347,6 @@ public final class BluetoothSap implements BluetoothProfile {          return PRIORITY_OFF;      } -    private final ServiceConnection mConnection = new ServiceConnection() { -        public void onServiceConnected(ComponentName className, IBinder service) { -            if (DBG) log("Proxy object connected"); -            mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service)); -            if (mServiceListener != null) { -                mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this); -            } -        } - -        public void onServiceDisconnected(ComponentName className) { -            if (DBG) log("Proxy object disconnected"); -            mService = null; -            if (mServiceListener != null) { -                mServiceListener.onServiceDisconnected(BluetoothProfile.SAP); -            } -        } -    }; -      private static void log(String msg) {          Log.d(TAG, msg);      } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index c4bc52c6f4de..9405ed26e513 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -1091,11 +1091,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub {      public void unbindBluetoothProfileService(int bluetoothProfile,              IBluetoothProfileServiceConnection proxy) {          synchronized (mProfileServices) { -            ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile)); +            Integer profile = new Integer(bluetoothProfile); +            ProfileServiceConnections psc = mProfileServices.get(profile);              if (psc == null) {                  return;              }              psc.removeProxy(proxy); +            if (psc.isEmpty()) { +                // All prxoies are disconnected, unbind with the service. +                try { +                    mContext.unbindService(psc); +                } catch (IllegalArgumentException e) { +                    Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e); +                } +                mProfileServices.remove(profile); +            }          }      } @@ -1252,6 +1262,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {              mProxies.kill();          } +        private boolean isEmpty() { +            return mProxies.getRegisteredCallbackCount() == 0; +        } +          @Override          public void onServiceConnected(ComponentName className, IBinder service) {              // remove timeout message |