summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorfredc <fredc@broadcom.com>2012-05-07 00:10:27 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-07-16 22:05:28 -0700
commit74ae04c73312403e89db0f8e9bd9601d403b4783 (patch)
tree60bc40da3e469998bded767fa88e86bb4574cbfc /src
parentce4edb8ed132976651b32b337f3d90e1a170afa9 (diff)
downloadandroid_packages_apps_Bluetooth-74ae04c73312403e89db0f8e9bd9601d403b4783.tar.gz
android_packages_apps_Bluetooth-74ae04c73312403e89db0f8e9bd9601d403b4783.tar.bz2
android_packages_apps_Bluetooth-74ae04c73312403e89db0f8e9bd9601d403b4783.zip
Fixed memory leak in Binder objects from repeatedly turning on/off Bluetooth
Change-Id: Ibee5382816d47b1e9b846461942a9daccc4210a7
Diffstat (limited to 'src')
-rw-r--r--src/com/android/bluetooth/Utils.java5
-rwxr-xr-xsrc/com/android/bluetooth/a2dp/A2dpService.java192
-rwxr-xr-xsrc/com/android/bluetooth/a2dp/A2dpStateMachine.java15
-rw-r--r--src/com/android/bluetooth/btservice/AdapterApp.java22
-rwxr-xr-xsrc/com/android/bluetooth/btservice/AdapterProperties.java19
-rwxr-xr-xsrc/com/android/bluetooth/btservice/AdapterService.java821
-rwxr-xr-xsrc/com/android/bluetooth/btservice/AdapterState.java19
-rwxr-xr-xsrc/com/android/bluetooth/btservice/BondStateMachine.java9
-rw-r--r--src/com/android/bluetooth/btservice/JniCallbacks.java35
-rw-r--r--src/com/android/bluetooth/btservice/ProfileService.java135
-rwxr-xr-xsrc/com/android/bluetooth/btservice/RemoteDevices.java30
-rwxr-xr-xsrc/com/android/bluetooth/hdp/HealthService.java251
-rwxr-xr-xsrc/com/android/bluetooth/hfp/AtPhonebook.java22
-rw-r--r--src/com/android/bluetooth/hfp/HeadsetPhoneState.java21
-rwxr-xr-xsrc/com/android/bluetooth/hfp/HeadsetService.java399
-rwxr-xr-xsrc/com/android/bluetooth/hfp/HeadsetStateMachine.java51
-rwxr-xr-xsrc/com/android/bluetooth/hid/HidService.java409
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java1
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java2
-rw-r--r--src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java2
-rwxr-xr-xsrc/com/android/bluetooth/pan/PanService.java231
-rwxr-xr-xsrc/com/android/bluetooth/pbap/BluetoothPbapService.java5
22 files changed, 1702 insertions, 994 deletions
diff --git a/src/com/android/bluetooth/Utils.java b/src/com/android/bluetooth/Utils.java
index 477f8c5e4..7ace4cd3c 100644
--- a/src/com/android/bluetooth/Utils.java
+++ b/src/com/android/bluetooth/Utils.java
@@ -5,6 +5,7 @@
package com.android.bluetooth;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.os.ParcelUuid;
import java.nio.ByteBuffer;
@@ -29,6 +30,10 @@ final public class Utils {
address[5]);
}
+ public static byte[] getByteAddress(BluetoothDevice device) {
+ return getBytesFromAddress(device.getAddress());
+ }
+
public static byte[] getBytesFromAddress(String address) {
int i, j = 0;
byte[] output = new byte[BD_ADDR_LEN];
diff --git a/src/com/android/bluetooth/a2dp/A2dpService.java b/src/com/android/bluetooth/a2dp/A2dpService.java
index bd0d0bb98..bce55f72d 100755
--- a/src/com/android/bluetooth/a2dp/A2dpService.java
+++ b/src/com/android/bluetooth/a2dp/A2dpService.java
@@ -3,24 +3,17 @@
*/
package com.android.bluetooth.a2dp;
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothA2dp;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
import android.provider.Settings;
import android.util.Log;
+import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Map;
-import android.content.pm.PackageManager;
-import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
/**
@@ -33,110 +26,173 @@ public class A2dpService extends ProfileService {
private A2dpStateMachine mStateMachine;
+ protected String getName() {
+ return TAG;
+ }
+
+ protected IProfileServiceBinder initBinder() {
+ return new BluetoothA2dpBinder(this);
+ }
protected boolean start() {
- if (DBG) log("startService()");
- mStateMachine = new A2dpStateMachine(this);
+ mStateMachine = new A2dpStateMachine(this,this);
mStateMachine.start();
return true;
}
protected boolean stop() {
- if (DBG) log("stopService()");
+ mStateMachine.quit();
+ return true;
+ }
+
+ protected boolean cleanup() {
if (mStateMachine!= null) {
- mStateMachine.quit();
mStateMachine.cleanup();
mStateMachine=null;
}
return true;
}
- protected String getName() {
- return TAG;
+ //API Methods
+ boolean connect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+
+ if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
+ return false;
+ }
+
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState == BluetoothProfile.STATE_CONNECTED ||
+ connectionState == BluetoothProfile.STATE_CONNECTING) {
+ return false;
+ }
+
+ mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
+ return true;
}
- @Override
- public IBinder onBind(Intent intent) {
- log("onBind");
- return mBinder;
+ boolean disconnect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState != BluetoothProfile.STATE_CONNECTED &&
+ connectionState != BluetoothProfile.STATE_CONNECTING) {
+ return false;
+ }
+
+ mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device);
+ return true;
}
- /**
- * Handlers for incoming service calls
- */
- private final IBluetoothA2dp.Stub mBinder = new IBluetoothA2dp.Stub() {
+ List<BluetoothDevice> getConnectedDevices() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.getConnectedDevices();
+ }
- public boolean connect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.getDevicesMatchingConnectionStates(states);
+ }
- if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
- return false;
- }
+ int getConnectionState(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.getConnectionState(device);
+ }
+
+ boolean setPriority(BluetoothDevice device, int priority) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
+ priority);
+ if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority);
+ return true;
+ }
- int connectionState = mStateMachine.getConnectionState(device);
- if (connectionState == BluetoothProfile.STATE_CONNECTED ||
- connectionState == BluetoothProfile.STATE_CONNECTING) {
- return false;
+ int getPriority(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int priority = Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
+ BluetoothProfile.PRIORITY_UNDEFINED);
+ return priority;
+ }
+
+ synchronized boolean isA2dpPlaying(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ if (DBG) Log.d(TAG, "isA2dpPlaying(" + device + ")");
+ return mStateMachine.isPlaying(device);
+ }
+
+ //Binder object: Must be static class or memory leak may occur
+ private static class BluetoothA2dpBinder extends IBluetoothA2dp.Stub
+ implements IProfileServiceBinder {
+ private A2dpService mService;
+
+ private A2dpService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
}
+ return null;
+ }
- mStateMachine.sendMessage(A2dpStateMachine.CONNECT, device);
+ BluetoothA2dpBinder(A2dpService svc) {
+ mService = svc;
+ }
+
+ public boolean cleanup() {
+ mService = null;
return true;
}
- public boolean disconnect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- int connectionState = mStateMachine.getConnectionState(device);
- if (connectionState != BluetoothProfile.STATE_CONNECTED &&
- connectionState != BluetoothProfile.STATE_CONNECTING) {
- return false;
- }
+ public boolean connect(BluetoothDevice device) {
+ A2dpService service = getService();
+ if (service == null) return false;
+ return service.connect(device);
+ }
- mStateMachine.sendMessage(A2dpStateMachine.DISCONNECT, device);
- return true;
+ public boolean disconnect(BluetoothDevice device) {
+ A2dpService service = getService();
+ if (service == null) return false;
+ return service.disconnect(device);
}
public List<BluetoothDevice> getConnectedDevices() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.getConnectedDevices();
+ A2dpService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getConnectedDevices();
}
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.getDevicesMatchingConnectionStates(states);
+ A2dpService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getDevicesMatchingConnectionStates(states);
}
public int getConnectionState(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.getConnectionState(device);
+ A2dpService service = getService();
+ if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
+ return service.getConnectionState(device);
}
public boolean setPriority(BluetoothDevice device, int priority) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- Settings.Secure.putInt(getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
- priority);
- if (DBG) log("Saved priority " + device + " = " + priority);
- return true;
+ A2dpService service = getService();
+ if (service == null) return false;
+ return service.setPriority(device, priority);
}
public int getPriority(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int priority = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
- BluetoothProfile.PRIORITY_UNDEFINED);
- return priority;
+ A2dpService service = getService();
+ if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
+ return service.getPriority(device);
}
- public synchronized boolean isA2dpPlaying(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM,
- "Need BLUETOOTH permission");
- if (DBG) log("isA2dpPlaying(" + device + ")");
- return mStateMachine.isPlaying(device);
+ public boolean isA2dpPlaying(BluetoothDevice device) {
+ A2dpService service = getService();
+ if (service == null) return false;
+ return service.isA2dpPlaying(device);
}
};
-
}
diff --git a/src/com/android/bluetooth/a2dp/A2dpStateMachine.java b/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
index c7debf407..59df75787 100755
--- a/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
+++ b/src/com/android/bluetooth/a2dp/A2dpStateMachine.java
@@ -52,6 +52,7 @@ final class A2dpStateMachine extends StateMachine {
private Pending mPending;
private Connected mConnected;
+ private A2dpService mService;
private Context mContext;
private BluetoothAdapter mAdapter;
private static final ParcelUuid[] A2DP_UUIDS = {
@@ -89,8 +90,9 @@ final class A2dpStateMachine extends StateMachine {
classInitNative();
}
- A2dpStateMachine(Context context) {
+ A2dpStateMachine(A2dpService svc, Context context) {
super(TAG);
+ mService = svc;
mContext = context;
mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -109,7 +111,9 @@ final class A2dpStateMachine extends StateMachine {
public void cleanup() {
cleanupNative();
- if(mContext != null)
+ if(mService != null)
+ mService = null;
+ if (mContext != null)
mContext = null;
if(mAdapter != null)
mAdapter = null;
@@ -600,10 +604,7 @@ final class A2dpStateMachine extends StateMachine {
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
mContext.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
if (DBG) log("Connection state " + device + ": " + prevState + "->" + newState);
- AdapterService svc = AdapterService.getAdapterService();
- if (svc != null) {
- svc.onProfileConnectionStateChanged(device, BluetoothProfile.A2DP, newState, prevState);
- }
+ mService.notifyProfileConnectionStateChanged(device, BluetoothProfile.A2DP, newState, prevState);
}
private void broadcastAudioState(BluetoothDevice device, int state, int prevState) {
@@ -659,7 +660,7 @@ final class A2dpStateMachine extends StateMachine {
final private static int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1;
final private static int EVENT_TYPE_AUDIO_STATE_CHANGED = 2;
- // Do not modify without upating the HAL bt_av.h files.
+ // Do not modify without updating the HAL bt_av.h files.
// match up with btav_connection_state_t enum of bt_av.h
final static int CONNECTION_STATE_DISCONNECTED = 0;
diff --git a/src/com/android/bluetooth/btservice/AdapterApp.java b/src/com/android/bluetooth/btservice/AdapterApp.java
index b419fcd30..be5d76998 100644
--- a/src/com/android/bluetooth/btservice/AdapterApp.java
+++ b/src/com/android/bluetooth/btservice/AdapterApp.java
@@ -14,12 +14,24 @@ import android.util.Log;
public class AdapterApp extends Application {
private static final String TAG = "BluetoothAdapterApp";
private static final boolean DBG = true;
+ //For Debugging only
+ private static int sRefCount=0;
static {
if (DBG) Log.d(TAG,"Loading JNI Library");
System.loadLibrary("bluetooth_jni");
}
+ public AdapterApp() {
+ super();
+ if (DBG) {
+ synchronized (AdapterApp.class) {
+ sRefCount++;
+ Log.d(TAG, "REFCOUNT: Constructed "+ this + " Instance Count = " + sRefCount);
+ }
+ }
+ }
+
@Override
public void onCreate() {
super.onCreate();
@@ -27,8 +39,12 @@ public class AdapterApp extends Application {
}
@Override
- protected void finalize() throws Throwable {
- super.finalize();
- if (DBG) Log.d(TAG, "finalize");
+ protected void finalize() {
+ if (DBG) {
+ synchronized (AdapterApp.class) {
+ sRefCount--;
+ Log.d(TAG, "REFCOUNT: Finalized: " + this +", Instance Count = " + sRefCount);
+ }
+ }
}
}
diff --git a/src/com/android/bluetooth/btservice/AdapterProperties.java b/src/com/android/bluetooth/btservice/AdapterProperties.java
index aea4e5bfc..d061138c1 100755
--- a/src/com/android/bluetooth/btservice/AdapterProperties.java
+++ b/src/com/android/bluetooth/btservice/AdapterProperties.java
@@ -38,9 +38,7 @@ class AdapterProperties {
private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED;
private int mState = BluetoothAdapter.STATE_OFF;
- //private static AdapterProperties sInstance;
private AdapterService mService;
- private Context mContext;
private boolean mDiscovering;
private RemoteDevices mRemoteDevices;
@@ -49,11 +47,9 @@ class AdapterProperties {
// can be added here.
private Object mObject = new Object();
- AdapterProperties(AdapterService service, Context context) {
+ public AdapterProperties(AdapterService service) {
mService = service;
- mContext = context;
}
-
public void init(RemoteDevices remoteDevices) {
if (mProfileConnectionState ==null) {
mProfileConnectionState = new HashMap<Integer, Pair<Integer, Integer>>();
@@ -64,13 +60,12 @@ class AdapterProperties {
}
public void cleanup() {
+ mRemoteDevices = null;
if (mProfileConnectionState != null) {
mProfileConnectionState.clear();
mProfileConnectionState = null;
}
- mRemoteDevices = null;
mService = null;
- mContext = null;
}
public Object Clone() throws CloneNotSupportedException {
@@ -257,7 +252,7 @@ class AdapterProperties {
intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_CONNECTION_STATE,
convertToAdapterState(prevState));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, mService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
debugLog("CONNECTION_STATE_CHANGE: " + device + ": "
+ prevState + " -> " + state);
}
@@ -389,7 +384,7 @@ class AdapterProperties {
intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, mService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
debugLog("Name is: " + mName);
break;
case AbstractionLayer.BT_PROPERTY_BDADDR:
@@ -406,7 +401,7 @@ class AdapterProperties {
intent = new Intent(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
intent.putExtra(BluetoothAdapter.EXTRA_SCAN_MODE, mScanMode);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, mService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
debugLog("Scan Mode:" + mScanMode);
if (mBluetoothDisabling) {
mBluetoothDisabling=false;
@@ -488,11 +483,11 @@ class AdapterProperties {
if (state == AbstractionLayer.BT_DISCOVERY_STOPPED) {
mDiscovering = false;
intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
- mContext.sendBroadcast(intent, mService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
} else if (state == AbstractionLayer.BT_DISCOVERY_STARTED) {
mDiscovering = true;
intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
- mContext.sendBroadcast(intent, mService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, mService.BLUETOOTH_PERM);
}
}
}
diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java
index b78da08d7..7ddf5f96b 100755
--- a/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/src/com/android/bluetooth/btservice/AdapterService.java
@@ -52,6 +52,9 @@ import android.os.ServiceManager;
public class AdapterService extends Service {
private static final String TAG = "BluetoothAdapterService";
private static final boolean DBG = true;
+ private static final boolean TRACE_REF = true;
+ //For Debugging only
+ private static int sRefCount=0;
/**
* List of profile services to support.Comment out to disable a profile
@@ -81,25 +84,61 @@ public class AdapterService extends Service {
}
private static AdapterService sAdapterService;
- public static AdapterService getAdapterService(){
- return sAdapterService;
+ public static synchronized AdapterService getAdapterService(){
+ if (sAdapterService != null && !sAdapterService.mCleaningUp) {
+ if (DBG) Log.d(TAG, "getAdapterService(): returning " + sAdapterService);
+ return sAdapterService;
+ }
+ if (DBG) {
+ if (sAdapterService == null) {
+ Log.d(TAG, "getAdapterService(): service not available");
+ } else if (sAdapterService.mCleaningUp) {
+ Log.d(TAG,"getAdapterService(): service is cleaning up");
+ }
+ }
+ return null;
}
- private IBluetoothManager mBluetoothManager;
- private IBluetooth mBluetoothService;
- private AdapterProperties mAdapterProperties;
- private int mAdapterState;
- private Context mContext;
+ private static synchronized void setAdapterService(AdapterService instance) {
+ if (instance != null && !instance.mCleaningUp) {
+ if (DBG) Log.d(TAG, "setAdapterService(): set to: " + sAdapterService);
+ sAdapterService = instance;
+ } else {
+ if (DBG) {
+ if (sAdapterService == null) {
+ Log.d(TAG, "setAdapterService(): service not available");
+ } else if (sAdapterService.mCleaningUp) {
+ Log.d(TAG,"setAdapterService(): service is cleaning up");
+ }
+ }
+ }
+ }
+
+ private static synchronized void clearAdapterService() {
+ sAdapterService = null;
+ }
+ private AdapterProperties mAdapterProperties;
private AdapterState mAdapterStateMachine;
private BondStateMachine mBondStateMachine;
private JniCallbacks mJniCallbacks;
private RemoteDevices mRemoteDevices;
private boolean mProfilesStarted;
private boolean mNativeAvailable;
+ private boolean mCleaningUp;
private HashMap<String,Integer> mProfileServicesState = new HashMap<String,Integer>();
private int mCurrentRequestId;
+ public AdapterService() {
+ super();
+ if (TRACE_REF) {
+ synchronized (AdapterService.class) {
+ sRefCount++;
+ Log.d(TAG, "REFCOUNT: CREATED. INSTANCE_COUNT" + sRefCount);
+ }
+ }
+ }
+
public void onProfileConnectionStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
Message m = mHandler.obtainMessage(MESSAGE_PROFILE_CONNECTION_STATE_CHANGED);
m.obj = device;
@@ -112,10 +151,10 @@ public class AdapterService extends Service {
}
private void processProfileStateChanged(BluetoothDevice device, int profileId, int newState, int prevState) {
- if (mBluetoothService != null) {
+ IBluetooth.Stub binder = mBinder;
+ if (binder != null) {
try {
- mBluetoothService.sendConnectionStateChange(device, profileId, newState,
- prevState);
+ binder.sendConnectionStateChange(device, profileId, newState,prevState);
} catch (RemoteException re) {
Log.e(TAG, "",re);
}
@@ -167,7 +206,9 @@ public class AdapterService extends Service {
}
}
if (DBG) Log.d(TAG, "All profile services stopped...");
- onProfilesStopped();
+ //Send message to state machine
+ mProfilesStarted=false;
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STOPPED));
} else if (isTurningOn) {
//Process start pending
//Check if all services are started if so, update state
@@ -183,7 +224,9 @@ public class AdapterService extends Service {
}
}
if (DBG) Log.d(TAG, "All profile services started.");
- onProfilesStarted();
+ mProfilesStarted=true;
+ //Send message to state machine
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
}
}
@@ -191,11 +234,10 @@ public class AdapterService extends Service {
public void onCreate() {
super.onCreate();
if (DBG) debugLog("onCreate");
- mContext = this;
- sAdapterService = this;
- mAdapterProperties = new AdapterProperties(this, mContext);
- mAdapterStateMachine = new AdapterState(this, mContext, mAdapterProperties);
- mJniCallbacks = JniCallbacks.getInstance(null, mAdapterProperties,mAdapterStateMachine,null);
+ mBinder = new AdapterServiceBinder(this);
+ mAdapterProperties = new AdapterProperties(this);
+ mAdapterStateMachine = new AdapterState(this, mAdapterProperties);
+ mJniCallbacks = new JniCallbacks(mAdapterStateMachine, mAdapterProperties);
initNative();
mNativeAvailable=true;
mAdapterStateMachine.start();
@@ -203,6 +245,7 @@ public class AdapterService extends Service {
//Load the name and address
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
+
}
@Override
@@ -222,8 +265,11 @@ public class AdapterService extends Service {
}
public int onStartCommand(Intent intent ,int flags, int startId) {
-
mCurrentRequestId = startId;
+ if (mCleaningUp) {
+ Log.e(TAG,"*************Received new request while service is cleaning up****************************");
+ }
+
if (DBG) debugLog("onStartCommand: flags = " + flags + ", startId = " + startId);
if (checkCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM)!=PackageManager.PERMISSION_GRANTED) {
Log.e(TAG, "Permission denied!");
@@ -275,89 +321,40 @@ public class AdapterService extends Service {
for (int i=0; i < SUPPORTED_PROFILE_SERVICES.length;i++) {
mProfileServicesState.put(SUPPORTED_PROFILE_SERVICES[i].getName(),BluetoothAdapter.STATE_OFF);
}
-
- mRemoteDevices = new RemoteDevices(this, mContext);
- mRemoteDevices.init();
+ mRemoteDevices = new RemoteDevices(this);
+ mBondStateMachine = new BondStateMachine(this, mAdapterProperties, mRemoteDevices);
mAdapterProperties.init(mRemoteDevices);
- mBondStateMachine = new BondStateMachine(this, mContext, mAdapterProperties, mRemoteDevices);
- mJniCallbacks.init(mRemoteDevices, mAdapterProperties,mAdapterStateMachine,mBondStateMachine);
-
- //Init BluetoothManager
- if (DBG) {debugLog("processStart(): Initializing Bluetooth Manager");}
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- mBluetoothManager = IBluetoothManager.Stub.asInterface(b);
- if (mBluetoothManager != null) {
- try {
- Log.d(TAG, "FRED: Registering manager callback " + mManagerCallback);
- mBluetoothService = mBluetoothManager.registerAdapter(mManagerCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "",re);
- }
- }
- }
+ mJniCallbacks.init(mBondStateMachine,mRemoteDevices);
//Start Bond State Machine
if (DBG) {debugLog("processStart(): Starting Bond State Machine");}
mBondStateMachine.start();
+ //FIXME: Set static instance here???
+ setAdapterService(this);
+
//Start profile services
- if (SUPPORTED_PROFILE_SERVICES.length==0 || mProfilesStarted) {
- //Skip starting profiles and go to next step
- if (DBG) {debugLog("processStart(): Profile Services started");}
- Message m = mAdapterStateMachine.obtainMessage(AdapterState.STARTED);
- mAdapterStateMachine.sendMessage(m);
- } else {
+ if (!mProfilesStarted && SUPPORTED_PROFILE_SERVICES.length >0) {
//Startup all profile services
setProfileServiceState(SUPPORTED_PROFILE_SERVICES,BluetoothAdapter.STATE_ON);
+ }else {
+ if (DBG) {debugLog("processStart(): Profile Services alreay started");}
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.STARTED));
}
}
void startBluetoothDisable() {
- Log.d(TAG,"startBluetoothDisable()");
- Message m = mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE);
- mAdapterStateMachine.sendMessage(m);
- }
-
- void onProfilesStarted(){
- Log.d(TAG,"onProfilesStarted()");
- mProfilesStarted=true;
- Message m = mAdapterStateMachine.obtainMessage(AdapterState.STARTED);
- mAdapterStateMachine.sendMessage(m);
- }
-
- void onProfilesStopped() {
- Log.d(TAG,"onProfilesStopped()");
- mProfilesStarted=false;
- //Message m = mAdapterStateMachine.obtainMessage(AdapterState.DISABLE);
- Message m = mAdapterStateMachine.obtainMessage(AdapterState.STOPPED);
- mAdapterStateMachine.sendMessage(m);
+ mAdapterStateMachine.sendMessage(mAdapterStateMachine.obtainMessage(AdapterState.BEGIN_DISABLE));
}
-
boolean stopProfileServices() {
- if (SUPPORTED_PROFILE_SERVICES.length==0 || !mProfilesStarted) {
- if (DBG) {debugLog("processDisable(): No profiles services to stop or already stopped.");}
+ if (mProfilesStarted && SUPPORTED_PROFILE_SERVICES.length>0) {
+ setProfileServiceState(SUPPORTED_PROFILE_SERVICES,BluetoothAdapter.STATE_OFF);
+ return true;
+ } else {
+ if (DBG) {debugLog("stopProfileServices(): No profiles services to stop or already stopped.");}
return false;
}
- setProfileServiceState(SUPPORTED_PROFILE_SERVICES,BluetoothAdapter.STATE_OFF);
- return true;
- }
-
- void processStopped() {
- Log.d(TAG, "processStopped()");
-
- if (mBluetoothManager != null) {
- try {
- Log.d(TAG,"FRED: Unregistering manager callback " + mManagerCallback);
- mBluetoothManager.unregisterAdapter(mManagerCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "",re);
- }
- }
- mBondStateMachine.quit();
- mBondStateMachine.cleanup();
- mBondStateMachine = null;
}
void startShutdown(int requestId) {
@@ -366,7 +363,6 @@ public class AdapterService extends Service {
Log.w(TAG, "Ignoring shutdown request. Invalid requestId");
return;
}
-
Message m = mHandler.obtainMessage(MESSAGE_SHUTDOWN);
synchronized(mHandler) {
mHandler.sendMessageDelayed(m, SHUTDOWN_TIMEOUT);
@@ -376,50 +372,61 @@ public class AdapterService extends Service {
void cleanup () {
if (DBG)debugLog("cleanup()");
-
- if (mNativeAvailable) {
- Log.d(TAG, "Cleaning up adapter native....");
- cleanupNative();
- Log.d(TAG, "Done cleaning up adapter native....");
- mNativeAvailable=false;
+ if (mCleaningUp) {
+ Log.w(TAG,"*************service already starting to cleanup... Ignoring cleanup request.........");
+ return;
}
+ mCleaningUp = true;
+
if (mAdapterStateMachine != null) {
mAdapterStateMachine.quit();
mAdapterStateMachine.cleanup();
mAdapterStateMachine = null;
}
+ if (mBondStateMachine != null) {
+ mBondStateMachine.quit();
+ mBondStateMachine.cleanup();
+ mBondStateMachine = null;
+ }
+
if (mRemoteDevices != null) {
mRemoteDevices.cleanup();
mRemoteDevices = null;
}
+ if (mNativeAvailable) {
+ Log.d(TAG, "Cleaning up adapter native....");
+ cleanupNative();
+ Log.d(TAG, "Done cleaning up adapter native....");
+ mNativeAvailable=false;
+ }
+
if (mAdapterProperties != null) {
mAdapterProperties.cleanup();
mAdapterProperties = null;
}
- mProfileServicesState.clear();
- if (DBG)debugLog("cleanup() done");
- }
+ if (mJniCallbacks != null) {
+ mJniCallbacks.cleanup();
+ mJniCallbacks = null;
+ }
- final private IBluetoothManagerCallback mManagerCallback =
- new IBluetoothManagerCallback.Stub() {
- public void onBluetoothServiceUp(IBluetooth bluetoothService) {
- if (DBG) Log.d(TAG, "onBluetoothServiceUp");
- synchronized (mManagerCallback) {
- mBluetoothService = bluetoothService;
- }
- }
+ if (mProfileServicesState != null) {
+ mProfileServicesState.clear();
+ mProfileServicesState= null;
+ }
- public void onBluetoothServiceDown() {
- if (DBG) Log.d(TAG, "onBluetoothServiceDown " + this);
- synchronized (mManagerCallback) {
- mBluetoothService = null;
- }
- }
- };
+ //FIXME: Set static instance here???
+ clearAdapterService();
+
+ if (mBinder != null) {
+ mBinder.cleanup();
+ mBinder = null;
+ }
+ if (DBG)debugLog("cleanup() done");
+ }
private static final int MESSAGE_PROFILE_SERVICE_STATE_CHANGED =1;
private static final int MESSAGE_PROFILE_CONNECTION_STATE_CHANGED=20;
@@ -487,285 +494,525 @@ public class AdapterService extends Service {
}
}
+ private boolean isAvailable() {
+ return !mCleaningUp;
+ }
+
/**
* Handlers for incoming service calls
*/
- private final IBluetooth.Stub mBinder = new IBluetooth.Stub() {
+ private AdapterServiceBinder mBinder;
+
+ /**
+ * The Binder implementation must be declared to be a static class, with
+ * the AdapterService instance passed in the constructor. Furthermore,
+ * when the AdapterService shuts down, the reference to the AdapterService
+ * must be explicitly removed.
+ *
+ * Otherwise, a memory leak can occur from repeated starting/stopping the
+ * service...Please refer to android.os.Binder for further details on
+ * why an inner instance class should be avoided.
+ *
+ */
+ private static class AdapterServiceBinder extends IBluetooth.Stub {
+ private AdapterService mService;
+
+ public AdapterServiceBinder(AdapterService svc) {
+ mService = svc;
+ }
+ public boolean cleanup() {
+ mService = null;
+ return true;
+ }
+
+ public AdapterService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
+ }
+ return null;
+ }
public boolean isEnabled() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.isEnabled();
}
public int getState() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- debugLog("getState(): mAdapterProperties: " + mAdapterProperties);
- return mAdapterProperties.getState();
+ AdapterService service = getService();
+ if (service == null) return BluetoothAdapter.STATE_OFF;
+ return service.getState();
}
public boolean enable() {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- if (DBG) debugLog("enable() called...");
- Message m =
- mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
- m.arg1 = 1; //persist state
- mAdapterStateMachine.sendMessage(m);
- return true;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.enable();
}
public boolean disable(boolean persist) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- if (DBG) debugLog("disable() called...");
- int val = (persist ? 1 : 0);
- Message m =
- mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
- m.arg1 = val;
- mAdapterStateMachine.sendMessage(m);
- return true;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.disable(persist);
}
public String getAddress() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- String addrString = null;
- byte[] address = mAdapterProperties.getAddress();
- return Utils.getAddressStringFromByte(address);
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.getAddress();
}
public ParcelUuid[] getUuids() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.getUuids();
+ AdapterService service = getService();
+ if (service == null) return new ParcelUuid[0];
+ return service.getUuids();
}
public String getName() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM,
- "Need BLUETOOTH permission");
- try {
- return mAdapterProperties.getName();
- } catch (Throwable t) {
- Log.d(TAG, "Unexpected exception while calling getName()",t);
- }
- return null;
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.getName();
}
public boolean setName(String name) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- return mAdapterProperties.setName(name);
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setName(name);
}
public int getScanMode() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.getScanMode();
+ AdapterService service = getService();
+ if (service == null) return BluetoothAdapter.SCAN_MODE_NONE;
+ return service.getScanMode();
}
public boolean setScanMode(int mode, int duration) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- setDiscoverableTimeout(duration);
-
- int newMode = convertScanModeToHal(mode);
- return mAdapterProperties.setScanMode(newMode);
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setScanMode(mode,duration);
}
public int getDiscoverableTimeout() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.getDiscoverableTimeout();
+ AdapterService service = getService();
+ if (service == null) return 0;
+ return service.getDiscoverableTimeout();
}
public boolean setDiscoverableTimeout(int timeout) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.setDiscoverableTimeout(timeout);
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setDiscoverableTimeout(timeout);
}
public boolean startDiscovery() {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- return startDiscoveryNative();
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.startDiscovery();
}
public boolean cancelDiscovery() {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- return cancelDiscoveryNative();
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.cancelDiscovery();
}
-
public boolean isDiscovering() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.isDiscovering();
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.isDiscovering();
}
public BluetoothDevice[] getBondedDevices() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- debugLog("Get Bonded Devices being called");
- return mAdapterProperties.getBondedDevices();
+ AdapterService service = getService();
+ if (service == null) return new BluetoothDevice[0];
+ return service.getBondedDevices();
}
public int getAdapterConnectionState() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.getConnectionState();
+ AdapterService service = getService();
+ if (service == null) return BluetoothAdapter.STATE_DISCONNECTED;
+ return service.getAdapterConnectionState();
}
public int getProfileConnectionState(int profile) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mAdapterProperties.getProfileConnectionState(profile);
+ AdapterService service = getService();
+ if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
+ return service.getProfileConnectionState(profile);
}
public boolean createBond(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
- return false;
- }
-
- Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
- msg.obj = device;
- mBondStateMachine.sendMessage(msg);
- return true;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.createBond(device);
}
public boolean cancelBondProcess(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
- byte[] addr = Utils.getBytesFromAddress(device.getAddress());
- return cancelBondNative(addr);
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.cancelBondProcess(device);
}
public boolean removeBond(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
- return false;
- }
- Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
- msg.obj = device;
- mBondStateMachine.sendMessage(msg);
- return true;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.removeBond(device);
}
public int getBondState(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) {
- return BluetoothDevice.BOND_NONE;
- }
- return deviceProp.getBondState();
+ AdapterService service = getService();
+ if (service == null) return BluetoothDevice.BOND_NONE;
+ return service.getBondState(device);
}
public String getRemoteName(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) return null;
- return deviceProp.getName();
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.getRemoteName(device);
}
public String getRemoteAlias(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) return null;
- return deviceProp.getAlias();
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.getRemoteAlias(device);
}
public boolean setRemoteAlias(BluetoothDevice device, String name) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) return false;
- deviceProp.setAlias(name);
- return true;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setRemoteAlias(device, name);
}
public int getRemoteClass(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) return 0;
-
- return deviceProp.getBluetoothClass();
+ AdapterService service = getService();
+ if (service == null) return 0;
+ return service.getRemoteClass(device);
}
public ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null) return null;
- return deviceProp.getUuids();
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.getRemoteUuids(device);
}
public boolean fetchRemoteUuids(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- mRemoteDevices.fetchUuids(device);
- return true;
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.fetchRemoteUuids(device);
}
public boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
- return false;
- }
-
- byte[] addr = Utils.getBytesFromAddress(device.getAddress());
- return pinReplyNative(addr, accept, len, pinCode);
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setPin(device, accept, len, pinCode);
}
public boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
- return false;
- }
-
- byte[] addr = Utils.getBytesFromAddress(device.getAddress());
- return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
- Utils.byteArrayToInt(passkey));
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setPasskey(device, accept, len, passkey);
}
public boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
- if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
- return false;
- }
-
- byte[] addr = Utils.getBytesFromAddress(device.getAddress());
- return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
- accept, 0);
+ AdapterService service = getService();
+ if (service == null) return false;
+ return service.setPairingConfirmation(device, accept);
}
public void sendConnectionStateChange(BluetoothDevice
device, int profile, int state, int prevState) {
- // TODO(BT) permission check?
- // Since this is a binder call check if Bluetooth is on still
- if (getState() == BluetoothAdapter.STATE_OFF) return;
-
- mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
-
+ AdapterService service = getService();
+ if (service == null) return;
+ service.sendConnectionStateChange(device, profile, state, prevState);
}
public ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
ParcelUuid uuid, int port, int flag) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()),
- type, Utils.uuidToByteArray(uuid), port, flag);
- if (fd < 0) {
- errorLog("Failed to connect socket");
- return null;
- }
- return ParcelFileDescriptor.adoptFd(fd);
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.connectSocket(device, type, uuid, port, flag);
}
public ParcelFileDescriptor createSocketChannel(int type, String serviceName,
ParcelUuid uuid, int port, int flag) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- int fd = createSocketChannelNative(type, serviceName,
- Utils.uuidToByteArray(uuid), port, flag);
- if (fd < 0) {
- errorLog("Failed to create socket channel");
- return null;
- }
- return ParcelFileDescriptor.adoptFd(fd);
+ AdapterService service = getService();
+ if (service == null) return null;
+ return service.createSocketChannel(type, serviceName, uuid, port, flag);
}
};
- private int convertScanModeToHal(int mode) {
+
+ //----API Methods--------
+ boolean isEnabled() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.getState() == BluetoothAdapter.STATE_ON;
+ }
+
+ int getState() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ debugLog("getState(): mAdapterProperties: " + mAdapterProperties);
+ return mAdapterProperties.getState();
+ }
+
+ boolean enable() {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ if (DBG) debugLog("enable() called...");
+ Message m =
+ mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_ON);
+ m.arg1 = 1; //persist state
+ mAdapterStateMachine.sendMessage(m);
+ return true;
+ }
+
+ boolean disable(boolean persist) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ if (DBG) debugLog("disable() called...");
+ int val = (persist ? 1 : 0);
+ Message m =
+ mAdapterStateMachine.obtainMessage(AdapterState.USER_TURN_OFF);
+ m.arg1 = val;
+ mAdapterStateMachine.sendMessage(m);
+ return true;
+ }
+
+ String getAddress() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ String addrString = null;
+ byte[] address = mAdapterProperties.getAddress();
+ return Utils.getAddressStringFromByte(address);
+ }
+
+ ParcelUuid[] getUuids() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.getUuids();
+ }
+
+ String getName() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ try {
+ return mAdapterProperties.getName();
+ } catch (Throwable t) {
+ Log.d(TAG, "Unexpected exception while calling getName()",t);
+ }
+ return null;
+ }
+
+ boolean setName(String name) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ return mAdapterProperties.setName(name);
+ }
+
+ int getScanMode() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.getScanMode();
+ }
+
+ boolean setScanMode(int mode, int duration) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ setDiscoverableTimeout(duration);
+
+ int newMode = convertScanModeToHal(mode);
+ return mAdapterProperties.setScanMode(newMode);
+ }
+
+ int getDiscoverableTimeout() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.getDiscoverableTimeout();
+ }
+
+ boolean setDiscoverableTimeout(int timeout) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.setDiscoverableTimeout(timeout);
+ }
+
+ boolean startDiscovery() {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ return startDiscoveryNative();
+ }
+
+ boolean cancelDiscovery() {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ return cancelDiscoveryNative();
+ }
+
+ boolean isDiscovering() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.isDiscovering();
+ }
+
+ BluetoothDevice[] getBondedDevices() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ debugLog("Get Bonded Devices being called");
+ return mAdapterProperties.getBondedDevices();
+ }
+
+ int getAdapterConnectionState() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.getConnectionState();
+ }
+
+ int getProfileConnectionState(int profile) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mAdapterProperties.getProfileConnectionState(profile);
+ }
+
+ boolean createBond(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
+ return false;
+ }
+
+ Message msg = mBondStateMachine.obtainMessage(BondStateMachine.CREATE_BOND);
+ msg.obj = device;
+ mBondStateMachine.sendMessage(msg);
+ return true;
+ }
+
+ boolean cancelBondProcess(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
+ byte[] addr = Utils.getBytesFromAddress(device.getAddress());
+ return cancelBondNative(addr);
+ }
+
+ boolean removeBond(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
+ return false;
+ }
+ Message msg = mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
+ msg.obj = device;
+ mBondStateMachine.sendMessage(msg);
+ return true;
+ }
+
+ int getBondState(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) {
+ return BluetoothDevice.BOND_NONE;
+ }
+ return deviceProp.getBondState();
+ }
+
+ String getRemoteName(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) return null;
+ return deviceProp.getName();
+ }
+
+ String getRemoteAlias(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) return null;
+ return deviceProp.getAlias();
+ }
+
+ boolean setRemoteAlias(BluetoothDevice device, String name) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) return false;
+ deviceProp.setAlias(name);
+ return true;
+ }
+
+ int getRemoteClass(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) return 0;
+
+ return deviceProp.getBluetoothClass();
+ }
+
+ ParcelUuid[] getRemoteUuids(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null) return null;
+ return deviceProp.getUuids();
+ }
+
+ boolean fetchRemoteUuids(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ mRemoteDevices.fetchUuids(device);
+ return true;
+ }
+
+ boolean setPin(BluetoothDevice device, boolean accept, int len, byte[] pinCode) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
+ return false;
+ }
+
+ byte[] addr = Utils.getBytesFromAddress(device.getAddress());
+ return pinReplyNative(addr, accept, len, pinCode);
+ }
+
+ boolean setPasskey(BluetoothDevice device, boolean accept, int len, byte[] passkey) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
+ return false;
+ }
+
+ byte[] addr = Utils.getBytesFromAddress(device.getAddress());
+ return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, accept,
+ Utils.byteArrayToInt(passkey));
+ }
+
+ boolean setPairingConfirmation(BluetoothDevice device, boolean accept) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
+ if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDING) {
+ return false;
+ }
+
+ byte[] addr = Utils.getBytesFromAddress(device.getAddress());
+ return sspReplyNative(addr, AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
+ accept, 0);
+ }
+
+ void sendConnectionStateChange(BluetoothDevice
+ device, int profile, int state, int prevState) {
+ // TODO(BT) permission check?
+ // Since this is a binder call check if Bluetooth is on still
+ if (getState() == BluetoothAdapter.STATE_OFF) return;
+
+ mAdapterProperties.sendConnectionStateChange(device, profile, state, prevState);
+
+ }
+
+ ParcelFileDescriptor connectSocket(BluetoothDevice device, int type,
+ ParcelUuid uuid, int port, int flag) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ int fd = connectSocketNative(Utils.getBytesFromAddress(device.getAddress()),
+ type, Utils.uuidToByteArray(uuid), port, flag);
+ if (fd < 0) {
+ errorLog("Failed to connect socket");
+ return null;
+ }
+ return ParcelFileDescriptor.adoptFd(fd);
+ }
+
+ ParcelFileDescriptor createSocketChannel(int type, String serviceName,
+ ParcelUuid uuid, int port, int flag) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ int fd = createSocketChannelNative(type, serviceName,
+ Utils.uuidToByteArray(uuid), port, flag);
+ if (fd < 0) {
+ errorLog("Failed to create socket channel");
+ return null;
+ }
+ return ParcelFileDescriptor.adoptFd(fd);
+ }
+
+ private static int convertScanModeToHal(int mode) {
switch (mode) {
case BluetoothAdapter.SCAN_MODE_NONE:
return AbstractionLayer.BT_SCAN_MODE_NONE;
@@ -774,11 +1021,11 @@ public class AdapterService extends Service {
case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
return AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE;
}
- errorLog("Incorrect scan mode in convertScanModeToHal");
+ // errorLog("Incorrect scan mode in convertScanModeToHal");
return -1;
}
- int convertScanModeFromHal(int mode) {
+ static int convertScanModeFromHal(int mode) {
switch (mode) {
case AbstractionLayer.BT_SCAN_MODE_NONE:
return BluetoothAdapter.SCAN_MODE_NONE;
@@ -787,7 +1034,7 @@ public class AdapterService extends Service {
case AbstractionLayer.BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
}
- errorLog("Incorrect scan mode in convertScanModeFromHal");
+ //errorLog("Incorrect scan mode in convertScanModeFromHal");
return -1;
}
@@ -830,4 +1077,14 @@ public class AdapterService extends Service {
byte[] uuid, int port, int flag);
private native int createSocketChannelNative(int type, String serviceName,
byte[] uuid, int port, int flag);
+
+ protected void finalize() {
+ cleanup();
+ if (TRACE_REF) {
+ synchronized (AdapterService.class) {
+ sRefCount--;
+ Log.d(TAG, "REFCOUNT: FINALIZED. INSTANCE_COUNT= " + sRefCount);
+ }
+ }
+ }
}
diff --git a/src/com/android/bluetooth/btservice/AdapterState.java b/src/com/android/bluetooth/btservice/AdapterState.java
index f0b4300e6..9c6fc97bb 100755
--- a/src/com/android/bluetooth/btservice/AdapterState.java
+++ b/src/com/android/bluetooth/btservice/AdapterState.java
@@ -30,12 +30,11 @@ final class AdapterState extends StateMachine {
static final int USER_TURN_ON = 1;
static final int STARTED=2;
static final int ENABLED_READY = 3;
- // static final int POST_ENABLE =4;
static final int USER_TURN_OFF = 20;
static final int BEGIN_DISABLE = 21;
static final int ALL_DEVICES_DISCONNECTED = 22;
- // static final int DISABLE=23;
+
static final int DISABLED = 24;
static final int STOPPED=25;
@@ -53,7 +52,6 @@ final class AdapterState extends StateMachine {
private static final int STOP_TIMEOUT_DELAY = 5000;
private static final int PROPERTY_OP_DELAY =2000;
private AdapterService mAdapterService;
- private Context mContext;
private AdapterProperties mAdapterProperties;
private PendingCommandState mPendingCommandState = new PendingCommandState();
private OnState mOnState = new OnState();
@@ -61,24 +59,22 @@ final class AdapterState extends StateMachine {
public boolean isTurningOn() {
boolean isTurningOn= mPendingCommandState.isTurningOn();
- Log.d(TAG,"isTurningOn()=" + isTurningOn);
+ if (DBG) Log.d(TAG,"isTurningOn()=" + isTurningOn);
return isTurningOn;
}
public boolean isTurningOff() {
boolean isTurningOff= mPendingCommandState.isTurningOff();
- Log.d(TAG,"isTurningOff()=" + isTurningOff);
+ if (DBG) Log.d(TAG,"isTurningOff()=" + isTurningOff);
return isTurningOff;
}
- public AdapterState(AdapterService service, Context context,
- AdapterProperties adapterProperties) {
+ public AdapterState(AdapterService service,AdapterProperties adapterProperties) {
super("BluetoothAdapterState:");
addState(mOnState);
addState(mOffState);
addState(mPendingCommandState);
mAdapterService = service;
- mContext = context;
mAdapterProperties = adapterProperties;
setInitialState(mOffState);
}
@@ -88,8 +84,6 @@ final class AdapterState extends StateMachine {
mAdapterProperties = null;
if(mAdapterService != null)
mAdapterService = null;
- if(mContext != null)
- mContext = null;
}
private class OffState extends State {
@@ -273,7 +267,7 @@ final class AdapterState extends StateMachine {
Log.d(TAG,"Stopping profile services that were post enabled");
break;
}
- //Fall through if no post-enabled services or services already stopped
+ //Fall through if no services or services already stopped
case STOPPED:
if (DBG) Log.d(TAG,"CURRENT_STATE=PENDING, MESSAGE = STOPPED, isTurningOn=" + isTurningOn + ", isTurningOff=" + isTurningOff);
removeMessages(STOP_TIMEOUT);
@@ -282,7 +276,6 @@ final class AdapterState extends StateMachine {
setOffRequestId(-1);
transitionTo(mOffState);
sendIntent(BluetoothAdapter.STATE_OFF);
- mAdapterService.processStopped();
mAdapterService.startShutdown(requestId);
break;
case START_TIMEOUT:
@@ -328,7 +321,7 @@ final class AdapterState extends StateMachine {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mAdapterProperties.setState(newState);
- mContext.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
+ mAdapterService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
infoLog("Bluetooth State Change Intent: " + oldState + " -> " + newState);
}
diff --git a/src/com/android/bluetooth/btservice/BondStateMachine.java b/src/com/android/bluetooth/btservice/BondStateMachine.java
index 0bc53705d..70cfac683 100755
--- a/src/com/android/bluetooth/btservice/BondStateMachine.java
+++ b/src/com/android/bluetooth/btservice/BondStateMachine.java
@@ -40,14 +40,13 @@ final class BondStateMachine extends StateMachine {
static final int BOND_STATE_BONDED = 2;
private AdapterService mAdapterService;
- private Context mContext;
private AdapterProperties mAdapterProperties;
private RemoteDevices mRemoteDevices;
private PendingCommandState mPendingCommandState = new PendingCommandState();
private StableState mStableState = new StableState();
- public BondStateMachine(AdapterService service, Context context,
+ public BondStateMachine(AdapterService service,
AdapterProperties prop, RemoteDevices remoteDevices) {
super("BondStateMachine:");
addState(mStableState);
@@ -55,11 +54,13 @@ final class BondStateMachine extends StateMachine {
mRemoteDevices = remoteDevices;
mAdapterService = service;
mAdapterProperties = prop;
- mContext = context;
setInitialState(mStableState);
}
public void cleanup() {
+ mAdapterService = null;
+ mRemoteDevices = null;
+ mAdapterProperties = null;
}
private class StableState extends State {
@@ -221,7 +222,7 @@ final class BondStateMachine extends StateMachine {
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_BOND_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, oldState);
- mContext.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
+ mAdapterService.sendBroadcast(intent, AdapterService.BLUETOOTH_PERM);
infoLog("Bond State Change Intent:" + device + " OldState: " + oldState
+ " NewState: " + newState);
}
diff --git a/src/com/android/bluetooth/btservice/JniCallbacks.java b/src/com/android/bluetooth/btservice/JniCallbacks.java
index e992d5e97..61b0741f2 100644
--- a/src/com/android/bluetooth/btservice/JniCallbacks.java
+++ b/src/com/android/bluetooth/btservice/JniCallbacks.java
@@ -6,43 +6,28 @@ package com.android.bluetooth.btservice;
final class JniCallbacks {
- private static JniCallbacks sInstance;
private RemoteDevices mRemoteDevices;
private AdapterProperties mAdapterProperties;
private AdapterState mAdapterStateMachine;
private BondStateMachine mBondStateMachine;
- private JniCallbacks(RemoteDevices remoteDevices, AdapterProperties adapterProperties,
- AdapterState adapterStateMachine, BondStateMachine bondStateMachine) {
- mRemoteDevices = remoteDevices;
- mAdapterProperties = adapterProperties;
+ JniCallbacks(AdapterState adapterStateMachine,AdapterProperties adapterProperties) {
mAdapterStateMachine = adapterStateMachine;
- mBondStateMachine = bondStateMachine;
- }
-
- static synchronized JniCallbacks getInstance(RemoteDevices remoteDevices,
- AdapterProperties adapterProperties, AdapterState adapterStateMachine,
- BondStateMachine bondStateMachine) {
- if (sInstance == null) {
- sInstance =
- new JniCallbacks(remoteDevices, adapterProperties, adapterStateMachine,
- bondStateMachine);
- } else {
- sInstance.init(remoteDevices, adapterProperties, adapterStateMachine,
- bondStateMachine);
- }
- return sInstance;
+ mAdapterProperties = adapterProperties;
}
- void init(RemoteDevices remoteDevices,
- AdapterProperties adapterProperties, AdapterState adapterStateMachine,
- BondStateMachine bondStateMachine) {
+ void init(BondStateMachine bondStateMachine, RemoteDevices remoteDevices) {
mRemoteDevices = remoteDevices;
- mAdapterProperties = adapterProperties;
- mAdapterStateMachine = adapterStateMachine;
mBondStateMachine = bondStateMachine;
}
+ void cleanup() {
+ mRemoteDevices = null;
+ mAdapterProperties = null;
+ mAdapterStateMachine = null;
+ mBondStateMachine = null;
+ }
+
public Object Clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
diff --git a/src/com/android/bluetooth/btservice/ProfileService.java b/src/com/android/bluetooth/btservice/ProfileService.java
index 64b58d3be..baaf40397 100644
--- a/src/com/android/bluetooth/btservice/ProfileService.java
+++ b/src/com/android/bluetooth/btservice/ProfileService.java
@@ -1,60 +1,94 @@
package com.android.bluetooth.btservice;
+import java.util.HashMap;
+
+import com.android.bluetooth.Utils;
+
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.util.Log;
public abstract class ProfileService extends Service {
+ private static final boolean DBG = true;
+ //For Debugging only
+ private static HashMap<String, Integer> sReferenceCount = new HashMap<String,Integer>();
+
public static final String BLUETOOTH_ADMIN_PERM =
android.Manifest.permission.BLUETOOTH_ADMIN;
public static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+ public static interface IProfileServiceBinder extends IBinder {
+ public boolean cleanup();
+ }
//Profile services will not be automatically restarted.
//They must be explicitly restarted by AdapterService
private static final int PROFILE_SERVICE_MODE=Service.START_NOT_STICKY;
-
- protected BluetoothAdapter mAdapter;
protected String mName;
+ protected BluetoothAdapter mAdapter;
+ protected IProfileServiceBinder mBinder;
+ protected boolean mStartError=false;
+ private boolean mCleaningUp = false;
protected String getName() {
return getClass().getSimpleName();
}
- public abstract IBinder onBind(Intent intent);
+ protected boolean isAvailable() {
+ return !mStartError && !mCleaningUp;
+ }
+
+ protected abstract IProfileServiceBinder initBinder();
protected abstract boolean start();
protected abstract boolean stop();
+ protected boolean cleanup() {
+ return true;
+ }
- public boolean mStartError=false;
- @Override
- public void onCreate() {
+ protected ProfileService() {
mName = getName();
- if (mName == null) {
- mName = "UnknownProfileService";
+ if (DBG) {
+ synchronized (sReferenceCount) {
+ Integer refCount = sReferenceCount.get(mName);
+ if (refCount==null) {
+ refCount = 1;
+ } else {
+ refCount = refCount+1;
+ }
+ sReferenceCount.put(mName, refCount);
+ log("REFCOUNT: CREATED. INSTANCE_COUNT=" +refCount);
+ }
}
- mAdapter = BluetoothAdapter.getDefaultAdapter();
-
- log("onCreate");
- super.onCreate();
}
- private void doStart(Intent intent) {
-
- //Start service
- if (mAdapter == null) {
- Log.e(mName, "Error starting profile. BluetoothAdapter is null");
- } else {
- mStartError = !start();
- if (!mStartError) {
- notifyProfileServiceStateChange(BluetoothAdapter.STATE_ON);
- } else {
- Log.e(mName, "Error starting profile. BluetoothAdapter is null");
+ protected void finalize() {
+ if (DBG) {
+ synchronized (sReferenceCount) {
+ Integer refCount = sReferenceCount.get(mName);
+ if (refCount!=null) {
+ refCount = refCount-1;
+ } else {
+ refCount = 0;
+ }
+ sReferenceCount.put(mName, refCount);
+ log("REFCOUNT: FINALIZED. INSTANCE_COUNT=" +refCount);
}
}
}
+ @Override
+ public void onCreate() {
+ log("onCreate");
+ super.onCreate();
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mBinder = initBinder();
+ }
+
public int onStartCommand(Intent intent, int flags, int startId) {
log("onStartCommand()");
if (mStartError || mAdapter == null) {
@@ -87,22 +121,60 @@ public abstract class ProfileService extends Service {
return PROFILE_SERVICE_MODE;
}
+ public IBinder onBind(Intent intent) {
+ log("onBind");
+ return mBinder;
+ }
+
+ public boolean onUnbind(Intent intent) {
+ log("onUnbind");
+ return super.onUnbind(intent);
+ }
+
@Override
public void onDestroy() {
- super.onDestroy();
log("Destroying service.");
+ if (mCleaningUp) {
+ log("Cleanup already started... Skipping cleanup()...");
+ } else {
+ log("cleanup()");
+ mCleaningUp = true;
+ cleanup();
+ if (mBinder != null) {
+ mBinder.cleanup();
+ mBinder= null;
+ }
+ }
+ super.onDestroy();
+ mAdapter = null;
+ }
+
+ private void doStart(Intent intent) {
+ //Start service
+ if (mAdapter == null) {
+ Log.e(mName, "Error starting profile. BluetoothAdapter is null");
+ } else {
+ log("start()");
+ mStartError = !start();
+ if (!mStartError) {
+ notifyProfileServiceStateChanged(BluetoothAdapter.STATE_ON);
+ } else {
+ Log.e(mName, "Error starting profile. BluetoothAdapter is null");
+ }
+ }
}
private void doStop(Intent intent) {
if (stop()) {
- notifyProfileServiceStateChange(BluetoothAdapter.STATE_OFF);
+ log("stop()");
+ notifyProfileServiceStateChanged(BluetoothAdapter.STATE_OFF);
stopSelf();
} else {
Log.e(mName, "Unable to stop profile");
}
}
- protected void notifyProfileServiceStateChange(int state) {
+ protected void notifyProfileServiceStateChanged(int state) {
//Notify adapter service
AdapterService sAdapter = AdapterService.getAdapterService();
if (sAdapter!= null) {
@@ -110,6 +182,17 @@ public abstract class ProfileService extends Service {
}
}
+ public void notifyProfileConnectionStateChanged(BluetoothDevice device,
+ int profileId, int newState, int prevState) {
+ AdapterService svc = AdapterService.getAdapterService();
+ if (svc != null) {
+ svc.onProfileConnectionStateChanged(device, profileId, newState, prevState);
+ }
+ }
+
+ protected BluetoothDevice getDevice(byte[] address) {
+ return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
+ }
protected void log(String msg) {
Log.d(mName, msg);
diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java
index 21201f0a3..08ef48aba 100755
--- a/src/com/android/bluetooth/btservice/RemoteDevices.java
+++ b/src/com/android/bluetooth/btservice/RemoteDevices.java
@@ -26,7 +26,7 @@ final class RemoteDevices {
private static final boolean DBG = true;
private static final String TAG = "BluetoothRemoteDevices";
- private static Context mContext;
+
private static BluetoothAdapter mAdapter;
private static AdapterService mAdapterService;
private static ArrayList<BluetoothDevice> mSdpTracker;
@@ -37,28 +37,21 @@ final class RemoteDevices {
private static final int MESSAGE_UUID_INTENT = 1;
private HashMap<BluetoothDevice, DeviceProperties> mDevices;
- private static RemoteDevices sInstance;
- RemoteDevices(AdapterService service, Context context) {
+ RemoteDevices(AdapterService service) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
- mContext = context;
mAdapterService = service;
mSdpTracker = new ArrayList<BluetoothDevice>();
mDevices = new HashMap<BluetoothDevice, DeviceProperties>();
}
- public void init() {
- mSdpTracker.clear();
- mDevices.clear();
- }
- public void cleanup() {
+ void cleanup() {
mSdpTracker.clear();
mSdpTracker = null;
mDevices.clear();
mDevices = null;
mAdapterService = null;
- mContext = null;
mAdapter= null;
}
@@ -204,7 +197,7 @@ final class RemoteDevices {
Intent intent = new Intent(BluetoothDevice.ACTION_UUID);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.putExtra(BluetoothDevice.EXTRA_UUID, prop == null? null: prop.mUuids);
- mContext.sendBroadcast(intent, AdapterService.BLUETOOTH_ADMIN_PERM);
+ mAdapterService.sendBroadcast(intent, AdapterService.BLUETOOTH_ADMIN_PERM);
//Remove the outstanding UUID request
mSdpTracker.remove(device);
@@ -216,7 +209,7 @@ final class RemoteDevices {
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, pin);
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.PAIRING_VARIANT_DISPLAY_PIN);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
}
void devicePropertyChangedCallback(byte[] address, int[] types, byte[][] values) {
@@ -243,7 +236,7 @@ final class RemoteDevices {
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, bdDevice);
intent.putExtra(BluetoothDevice.EXTRA_NAME, device.mName);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
debugLog("Remote Device name is: " + device.mName);
break;
case AbstractionLayer.BT_PROPERTY_REMOTE_FRIENDLY_NAME:
@@ -263,7 +256,7 @@ final class RemoteDevices {
intent.putExtra(BluetoothDevice.EXTRA_CLASS,
new BluetoothClass(device.mBluetoothClass));
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
debugLog("Remote class is:" + device.mBluetoothClass);
break;
case AbstractionLayer.BT_PROPERTY_UUIDS:
@@ -300,7 +293,7 @@ final class RemoteDevices {
intent.putExtra(BluetoothDevice.EXTRA_RSSI, deviceProp.mRssi);
intent.putExtra(BluetoothDevice.EXTRA_NAME, deviceProp.mName);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
}
void pinRequestCallback(byte[] address, byte[] name, int cod) {
@@ -333,7 +326,7 @@ final class RemoteDevices {
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, getDevice(address));
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.PAIRING_VARIANT_PIN);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
return;
}
@@ -375,7 +368,7 @@ final class RemoteDevices {
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_KEY, passkey);
}
intent.putExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, variant);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_ADMIN_PERM);
}
void aclStateChangeCallback(int status, byte[] address, int newState) {
@@ -396,7 +389,7 @@ final class RemoteDevices {
}
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- mContext.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
+ mAdapterService.sendBroadcast(intent, mAdapterService.BLUETOOTH_PERM);
}
void fetchUuids(BluetoothDevice device) {
@@ -440,4 +433,5 @@ final class RemoteDevices {
private void warnLog(String msg) {
Log.w(TAG, msg);
}
+
}
diff --git a/src/com/android/bluetooth/hdp/HealthService.java b/src/com/android/bluetooth/hdp/HealthService.java
index 458deb2d3..085fcc8c1 100755
--- a/src/com/android/bluetooth/hdp/HealthService.java
+++ b/src/com/android/bluetooth/hdp/HealthService.java
@@ -4,8 +4,6 @@
package com.android.bluetooth.hdp;
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHealth;
import android.bluetooth.BluetoothHealthAppConfiguration;
@@ -14,7 +12,6 @@ import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothHealth;
import android.bluetooth.IBluetoothHealthCallback;
import android.content.Intent;
-import android.os.IBinder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -33,8 +30,8 @@ import java.util.Map;
import java.util.Map.Entry;
import com.android.bluetooth.Utils;
import android.content.pm.PackageManager;
-import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
+import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;
/**
* Provides Bluetooth Health Device profile, as a service in
@@ -44,9 +41,11 @@ import com.android.bluetooth.btservice.ProfileService;
public class HealthService extends ProfileService {
private static final boolean DBG = true;
private static final String TAG="HealthService";
+
private List<HealthChannel> mHealthChannels;
private Map <BluetoothHealthAppConfiguration, AppInfo> mApps;
private Map <BluetoothDevice, Integer> mHealthDevices;
+ private boolean mNativeAvailable;
private HealthServiceMessageHandler mHandler;
private static final int MESSAGE_REGISTER_APPLICATION = 1;
private static final int MESSAGE_UNREGISTER_APPLICATION = 2;
@@ -63,29 +62,11 @@ public class HealthService extends ProfileService {
return TAG;
}
- @Override
- public IBinder onBind(Intent intent) {
- log("onBind");
- return mBinder;
+ protected IProfileServiceBinder initBinder() {
+ return new BluetoothHealthBinder(this);
}
protected boolean start() {
-
- //Cleanup other object references
- if(mHealthChannels != null) {
- mHealthChannels.clear();
- mHealthChannels = null;
- }
- if(mHealthDevices != null) {
- mHealthDevices.clear();
- mHealthDevices = null;
- }
- if(mApps != null) {
- mApps.clear();
- mApps = null;
- }
-
- if (DBG) log("startService");
mHealthChannels = Collections.synchronizedList(new ArrayList<HealthChannel>());
mApps = Collections.synchronizedMap(new HashMap<BluetoothHealthAppConfiguration,
AppInfo>());
@@ -96,24 +77,26 @@ public class HealthService extends ProfileService {
Looper looper = thread.getLooper();
mHandler = new HealthServiceMessageHandler(looper);
initializeNative();
-
+ mNativeAvailable=true;
return true;
}
protected boolean stop() {
- if (DBG) log("stop()");
-
- //Cleanup looper
mHandler.removeCallbacksAndMessages(null);
Looper looper = mHandler.getLooper();
if (looper != null) {
looper.quit();
}
- mHandler = null;
+ return true;
+ }
+ protected boolean cleanup() {
+ mHandler = null;
//Cleanup native
- cleanupNative();
-
+ if (mNativeAvailable) {
+ cleanupNative();
+ mNativeAvailable=false;
+ }
if(mHealthChannels != null) {
mHealthChannels.clear();
mHealthChannels = null;
@@ -175,7 +158,7 @@ public class HealthService extends ProfileService {
case MESSAGE_CONNECT_CHANNEL:
{
HealthChannel chan = (HealthChannel) msg.obj;
- byte[] devAddr = getByteAddress(chan.mDevice);
+ byte[] devAddr = Utils.getByteAddress(chan.mDevice);
int appId = (mApps.get(chan.mConfig)).mAppId;
chan.mChannelId = connectChannelNative(devAddr, appId);
if (chan.mChannelId == -1) {
@@ -256,96 +239,170 @@ public class HealthService extends ProfileService {
/**
* Handlers for incoming service calls
*/
- private final IBluetoothHealth.Stub mBinder = new IBluetoothHealth.Stub() {
- public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
- IBluetoothHealthCallback callback) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM,
- "Need BLUETOOTH permission");
- if (mApps.get(config) != null) {
- if (DBG) log("Config has already been registered");
- return false;
- }
- mApps.put(config, new AppInfo(callback));
- Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION);
- msg.obj = config;
- mHandler.sendMessage(msg);
+ private static class BluetoothHealthBinder extends IBluetoothHealth.Stub implements IProfileServiceBinder {
+ private HealthService mService;
+
+ public BluetoothHealthBinder(HealthService svc) {
+ mService = svc;
+ }
+
+ public boolean cleanup() {
+ mService = null;
return true;
}
- public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (mApps.get(config) == null) {
- if (DBG) log("unregisterAppConfiguration: no app found");
- return false;
+ private HealthService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
}
+ return null;
+ }
- Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_APPLICATION);
- msg.obj = config;
- mHandler.sendMessage(msg);
- return true;
+ public boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
+ IBluetoothHealthCallback callback) {
+ HealthService service = getService();
+ if (service == null) return false;
+ return service.registerAppConfiguration(config, callback);
+ }
+
+ public boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
+ HealthService service = getService();
+ if (service == null) return false;
+ return service.unregisterAppConfiguration(config);
}
public boolean connectChannelToSource(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return connectChannel(device, config, BluetoothHealth.CHANNEL_TYPE_ANY);
+ HealthService service = getService();
+ if (service == null) return false;
+ return service.connectChannelToSource(device, config);
}
public boolean connectChannelToSink(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int channelType) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return connectChannel(device, config, channelType);
+ HealthService service = getService();
+ if (service == null) return false;
+ return service.connectChannelToSink(device, config, channelType);
}
public boolean disconnectChannel(BluetoothDevice device,
BluetoothHealthAppConfiguration config, int channelId) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- HealthChannel chan = findChannelById(channelId);
- if (chan == null) {
- if (DBG) log("disconnectChannel: no channel found");
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT_CHANNEL);
- msg.obj = chan;
- mHandler.sendMessage(msg);
- return true;
+ HealthService service = getService();
+ if (service == null) return false;
+ return service.disconnectChannel(device, config, channelId);
}
public ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
BluetoothHealthAppConfiguration config) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- HealthChannel healthChan = null;
- for (HealthChannel chan: mHealthChannels) {
- if (chan.mDevice.equals(device) && chan.mConfig.equals(config)) {
- healthChan = chan;
- }
- }
- if (healthChan == null) {
- Log.e(TAG, "No channel found for device: " + device + " config: " + config);
- return null;
- }
- return healthChan.mChannelFd;
+ HealthService service = getService();
+ if (service == null) return null;
+ return service.getMainChannelFd(device, config);
}
public int getHealthDeviceConnectionState(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return getConnectionState(device);
+ HealthService service = getService();
+ if (service == null) return BluetoothHealth.STATE_DISCONNECTED;
+ return service.getHealthDeviceConnectionState(device);
}
public List<BluetoothDevice> getConnectedHealthDevices() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(
- new int[] {BluetoothHealth.STATE_CONNECTED});
- return devices;
+ HealthService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice> (0);
+ return service.getConnectedHealthDevices();
}
public List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(int[] states) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(states);
- return devices;
+ HealthService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice> (0);
+ return service.getHealthDevicesMatchingConnectionStates(states);
}
};
+ boolean registerAppConfiguration(BluetoothHealthAppConfiguration config,
+ IBluetoothHealthCallback callback) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM,
+ "Need BLUETOOTH permission");
+ if (mApps.get(config) != null) {
+ if (DBG) Log.d(TAG, "Config has already been registered");
+ return false;
+ }
+ mApps.put(config, new AppInfo(callback));
+ Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_APPLICATION,config);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean unregisterAppConfiguration(BluetoothHealthAppConfiguration config) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (mApps.get(config) == null) {
+ if (DBG) Log.d(TAG,"unregisterAppConfiguration: no app found");
+ return false;
+ }
+
+ Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_APPLICATION,config);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean connectChannelToSource(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return connectChannel(device, config, BluetoothHealth.CHANNEL_TYPE_ANY);
+ }
+
+ boolean connectChannelToSink(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, int channelType) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return connectChannel(device, config, channelType);
+ }
+
+ boolean disconnectChannel(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config, int channelId) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ HealthChannel chan = findChannelById(channelId);
+ if (chan == null) {
+ if (DBG) Log.d(TAG,"disconnectChannel: no channel found");
+ return false;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT_CHANNEL,chan);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ ParcelFileDescriptor getMainChannelFd(BluetoothDevice device,
+ BluetoothHealthAppConfiguration config) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ HealthChannel healthChan = null;
+ for (HealthChannel chan: mHealthChannels) {
+ if (chan.mDevice.equals(device) && chan.mConfig.equals(config)) {
+ healthChan = chan;
+ }
+ }
+ if (healthChan == null) {
+ Log.e(TAG, "No channel found for device: " + device + " config: " + config);
+ return null;
+ }
+ return healthChan.mChannelFd;
+ }
+
+ int getHealthDeviceConnectionState(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return getConnectionState(device);
+ }
+
+ List<BluetoothDevice> getConnectedHealthDevices() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(
+ new int[] {BluetoothHealth.STATE_CONNECTED});
+ return devices;
+ }
+
+ List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(int[] states) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ List<BluetoothDevice> devices = lookupHealthDevicesMatchingStates(states);
+ return devices;
+ }
+
private void onAppRegistrationState(int appId, int state) {
Message msg = mHandler.obtainMessage(MESSAGE_APP_REGISTRATION_CALLBACK);
msg.arg1 = appId;
@@ -568,10 +625,7 @@ public class HealthService extends ProfileService {
} else {
mHealthDevices.put(device, newDeviceState);
}
- AdapterService svc = AdapterService.getAdapterService();
- if (svc != null) {
- svc.onProfileConnectionStateChanged(device, BluetoothProfile.HEALTH, newDeviceState, prevDeviceState);
- }
+ notifyProfileConnectionStateChanged(device, BluetoothProfile.HEALTH, newDeviceState, prevDeviceState);
}
/**
@@ -632,14 +686,6 @@ public class HealthService extends ProfileService {
return channels;
}
- private BluetoothDevice getDevice(byte[] address) {
- return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
- }
-
- private byte[] getByteAddress(BluetoothDevice device) {
- return Utils.getBytesFromAddress(device.getAddress());
- }
-
private int getConnectionState(BluetoothDevice device) {
if (mHealthDevices.get(device) == null) {
return BluetoothHealth.STATE_DISCONNECTED;
@@ -662,7 +708,7 @@ public class HealthService extends ProfileService {
return healthDevices;
}
- private class AppInfo {
+ private static class AppInfo {
private IBluetoothHealthCallback mCallback;
private int mAppId;
@@ -742,4 +788,5 @@ public class HealthService extends ProfileService {
private native boolean unregisterHealthAppNative(int appId);
private native int connectChannelNative(byte[] btAddress, int appId);
private native boolean disconnectChannelNative(int channelId);
+
}
diff --git a/src/com/android/bluetooth/hfp/AtPhonebook.java b/src/com/android/bluetooth/hfp/AtPhonebook.java
index ef76dd773..dea20100f 100755
--- a/src/com/android/bluetooth/hfp/AtPhonebook.java
+++ b/src/com/android/bluetooth/hfp/AtPhonebook.java
@@ -21,6 +21,7 @@ import com.android.bluetooth.R;
import com.android.internal.telephony.GsmAlphabet;
import android.bluetooth.BluetoothDevice;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -72,10 +73,9 @@ public class AtPhonebook {
public int nameColumn;
};
+ private Context mContext;
+ private ContentResolver mContentResolver;
private HeadsetStateMachine mStateMachine;
-
- private final Context mContext;
-
private String mCurrentPhonebook;
private String mCharacterSet = "UTF-8";
@@ -98,6 +98,7 @@ public class AtPhonebook {
public AtPhonebook(Context context, HeadsetStateMachine headsetState) {
mContext = context;
+ mContentResolver = context.getContentResolver();
mStateMachine = headsetState;
mPhonebooks.put("DC", new PhonebookResult()); // dialled calls
mPhonebooks.put("RC", new PhonebookResult()); // received calls
@@ -110,10 +111,17 @@ public class AtPhonebook {
mCheckingAccessPermission = false;
}
+ public void cleanup() {
+ mPhonebooks.clear();
+ mContentResolver = null;
+ mContext = null;
+ mStateMachine = null;
+ }
+
/** Returns the last dialled number, or null if no numbers have been called */
public String getLastDialledNumber() {
String[] projection = {Calls.NUMBER};
- Cursor cursor = mContext.getContentResolver().query(Calls.CONTENT_URI, projection,
+ Cursor cursor = mContentResolver.query(Calls.CONTENT_URI, projection,
Calls.TYPE + "=" + Calls.OUTGOING_TYPE, null, Calls.DEFAULT_SORT_ORDER +
" LIMIT 1");
if (cursor == null) return null;
@@ -387,7 +395,7 @@ public class AtPhonebook {
}
if (ancillaryPhonebook) {
- pbr.cursor = mContext.getContentResolver().query(
+ pbr.cursor = mContentResolver.query(
Calls.CONTENT_URI, CALLS_PROJECTION, where, null,
Calls.DEFAULT_SORT_ORDER + " LIMIT " + MAX_PHONEBOOK_SIZE);
if (pbr.cursor == null) return false;
@@ -396,7 +404,7 @@ public class AtPhonebook {
pbr.typeColumn = -1;
pbr.nameColumn = -1;
} else {
- pbr.cursor = mContext.getContentResolver().query(Phone.CONTENT_URI, PHONES_PROJECTION,
+ pbr.cursor = mContentResolver.query(Phone.CONTENT_URI, PHONES_PROJECTION,
where, null, Phone.NUMBER + " LIMIT " + MAX_PHONEBOOK_SIZE);
if (pbr.cursor == null) return false;
@@ -482,7 +490,7 @@ public class AtPhonebook {
// try caller id lookup
// TODO: This code is horribly inefficient. I saw it
// take 7 seconds to process 100 missed calls.
- Cursor c = mContext.getContentResolver().
+ Cursor c = mContentResolver.
query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
new String[] {PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE},
null, null, null);
diff --git a/src/com/android/bluetooth/hfp/HeadsetPhoneState.java b/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
index f549a9a89..874489670 100644
--- a/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
+++ b/src/com/android/bluetooth/hfp/HeadsetPhoneState.java
@@ -19,7 +19,6 @@ import com.android.internal.telephony.Call;
class HeadsetPhoneState {
private static final String TAG = "HeadsetPhoneState";
- private Context mContext;
private HeadsetStateMachine mStateMachine;
private TelephonyManager mTelephonyManager;
private ServiceState mServiceState;
@@ -52,9 +51,14 @@ class HeadsetPhoneState {
private boolean mListening = false;
HeadsetPhoneState(Context context, HeadsetStateMachine stateMachine) {
- mContext = context;
mStateMachine = stateMachine;
- mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
+ public void cleanup() {
+ listenForPhoneState(false);
+ mTelephonyManager = null;
+ mStateMachine = null;
}
void listenForPhoneState(boolean start) {
@@ -116,8 +120,11 @@ class HeadsetPhoneState {
void setBatteryCharge(int batteryLevel) {
if (mBatteryCharge != batteryLevel) {
mBatteryCharge = batteryLevel;
- mStateMachine.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED,
+ HeadsetStateMachine sm = mStateMachine;
+ if (sm != null) {
+ sm.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED,
new HeadsetDeviceState(mService, mRoam, mSignal, mBatteryCharge));
+ }
}
}
@@ -145,7 +152,6 @@ class HeadsetPhoneState {
return (mNumActive >= 1);
}
-
private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
@@ -153,8 +159,11 @@ class HeadsetPhoneState {
mService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ?
HeadsetHalConstants.NETWORK_STATE_AVAILABLE :
HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE;
- mStateMachine.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED,
+ HeadsetStateMachine sm = mStateMachine;
+ if (sm != null) {
+ sm.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED,
new HeadsetDeviceState(mService, mRoam, mSignal, mBatteryCharge));
+ }
}
@Override
diff --git a/src/com/android/bluetooth/hfp/HeadsetService.java b/src/com/android/bluetooth/hfp/HeadsetService.java
index 817f05379..1bf9ee9aa 100755
--- a/src/com/android/bluetooth/hfp/HeadsetService.java
+++ b/src/com/android/bluetooth/hfp/HeadsetService.java
@@ -4,9 +4,8 @@
package com.android.bluetooth.hfp;
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.IBluetoothHeadset;
import android.content.BroadcastReceiver;
@@ -14,17 +13,16 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
-import android.os.AsyncResult;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Message;
import android.provider.Settings;
import android.util.Log;
+
+import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Map;
import android.content.pm.PackageManager;
-import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
/**
@@ -35,18 +33,14 @@ import com.android.bluetooth.btservice.ProfileService;
public class HeadsetService extends ProfileService {
private static final boolean DBG = true;
private static final String TAG = "HeadsetService";
-
private HeadsetStateMachine mStateMachine;
- private boolean mReceiverRegistered;
protected String getName() {
return TAG;
}
- @Override
- public IBinder onBind(Intent intent) {
- log("onBind");
- return mBinder;
+ public IProfileServiceBinder initBinder() {
+ return new BluetoothHeadsetBinder(this);
}
protected boolean start() {
@@ -55,25 +49,26 @@ public class HeadsetService extends ProfileService {
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
-
- registerReceiver(mHeadsetReceiver, filter);
- mReceiverRegistered=true;
+ try {
+ registerReceiver(mHeadsetReceiver, filter);
+ } catch (Exception e) {
+ Log.w(TAG,"Unable to register headset receiver",e);
+ }
return true;
}
protected boolean stop() {
- if (DBG) log("stopService()");
- if (mReceiverRegistered) {
- try {
- unregisterReceiver(mHeadsetReceiver);
- } catch (Exception e) {
- Log.w(TAG,"Unable to unregister headset receiver",e);
- }
- mReceiverRegistered = false;
+ try {
+ unregisterReceiver(mHeadsetReceiver);
+ } catch (Exception e) {
+ Log.w(TAG,"Unable to unregister headset receiver",e);
}
+ mStateMachine.quit();
+ return true;
+ }
- if (mStateMachine!= null) {
- mStateMachine.quit();
+ protected boolean cleanup() {
+ if (mStateMachine != null) {
mStateMachine.cleanup();
mStateMachine=null;
}
@@ -84,7 +79,6 @@ public class HeadsetService extends ProfileService {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
-
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
mStateMachine.sendMessage(HeadsetStateMachine.INTENT_BATTERY_CHANGED, intent);
} else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
@@ -104,178 +98,329 @@ public class HeadsetService extends ProfileService {
/**
* Handlers for incoming service calls
*/
- private final IBluetoothHeadset.Stub mBinder = new IBluetoothHeadset.Stub() {
-
- public boolean connect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
+ private static class BluetoothHeadsetBinder extends IBluetoothHeadset.Stub implements IProfileServiceBinder {
+ private HeadsetService mService;
- if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
- return false;
- }
+ public BluetoothHeadsetBinder(HeadsetService svc) {
+ mService = svc;
+ }
+ public boolean cleanup() {
+ mService = null;
+ return true;
+ }
- int connectionState = mStateMachine.getConnectionState(device);
- if (connectionState == BluetoothProfile.STATE_CONNECTED ||
- connectionState == BluetoothProfile.STATE_CONNECTING) {
- return false;
+ private HeadsetService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
}
+ return null;
+ }
- mStateMachine.sendMessage(HeadsetStateMachine.CONNECT, device);
- return true;
+ public boolean connect(BluetoothDevice device) {
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.connect(device);
}
public boolean disconnect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH ADMIN permission");
- int connectionState = mStateMachine.getConnectionState(device);
- if (connectionState != BluetoothProfile.STATE_CONNECTED &&
- connectionState != BluetoothProfile.STATE_CONNECTING) {
- return false;
- }
-
- mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, device);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.disconnect(device);
}
public List<BluetoothDevice> getConnectedDevices() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.getConnectedDevices();
+ HeadsetService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getConnectedDevices();
}
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.getDevicesMatchingConnectionStates(states);
+ HeadsetService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getDevicesMatchingConnectionStates(states);
}
public int getConnectionState(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.getConnectionState(device);
+ HeadsetService service = getService();
+ if (service == null) return BluetoothProfile.STATE_DISCONNECTED;
+ return service.getConnectionState(device);
}
public boolean setPriority(BluetoothDevice device, int priority) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- Settings.Secure.putInt(getContentResolver(),
- Settings.Secure.getBluetoothHeadsetPriorityKey(device.getAddress()),
- priority);
- if (DBG) log("Saved priority " + device + " = " + priority);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.setPriority(device, priority);
}
public int getPriority(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int priority = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.getBluetoothHeadsetPriorityKey(device.getAddress()),
- BluetoothProfile.PRIORITY_UNDEFINED);
- return priority;
+ HeadsetService service = getService();
+ if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
+ return service.getPriority(device);
}
public boolean startVoiceRecognition(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- int connectionState = mStateMachine.getConnectionState(device);
- if (connectionState != BluetoothProfile.STATE_CONNECTED &&
- connectionState != BluetoothProfile.STATE_CONNECTING) {
- return false;
- }
- mStateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_START);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.startVoiceRecognition(device);
}
public boolean stopVoiceRecognition(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- // It seem that we really need to check the AudioOn state.
- // But since we allow startVoiceRecognition in STATE_CONNECTED and
- // STATE_CONNECTING state, we do these 2 in this method
- int connectionState = mStateMachine.getConnectionState(device);
- if (connectionState != BluetoothProfile.STATE_CONNECTED &&
- connectionState != BluetoothProfile.STATE_CONNECTING) {
- return false;
- }
- mStateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP);
- // TODO is this return correct when the voice recognition is not on?
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.stopVoiceRecognition(device);
}
public boolean isAudioOn() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.isAudioOn();
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.isAudioOn();
}
public boolean isAudioConnected(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mStateMachine.isAudioConnected(device);
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.isAudioConnected(device);
}
public int getBatteryUsageHint(BluetoothDevice device) {
- // TODO(BT) ask for BT stack support?
- return 0;
+ HeadsetService service = getService();
+ if (service == null) return 0;
+ return service.getBatteryUsageHint(device);
}
public boolean acceptIncomingConnect(BluetoothDevice device) {
- // TODO(BT) remove it if stack does access control
- return false;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.acceptIncomingConnect(device);
}
public boolean rejectIncomingConnect(BluetoothDevice device) {
- // TODO(BT) remove it if stack does access control
- return false;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.rejectIncomingConnect(device);
}
public int getAudioState(BluetoothDevice device) {
- return mStateMachine.getAudioState(device);
+ HeadsetService service = getService();
+ if (service == null) return BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
+ return service.getAudioState(device);
}
public boolean connectAudio() {
- // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!mStateMachine.isConnected()) {
- return false;
- }
- if (mStateMachine.isAudioOn()) {
- return false;
- }
- mStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.connectAudio();
}
public boolean disconnectAudio() {
- // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!mStateMachine.isAudioOn()) {
- return false;
- }
- mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.disconnectAudio();
}
public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
- // TODO(BT) Is this right?
- mStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.startScoUsingVirtualVoiceCall(device);
}
public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
- // TODO(BT) Is this right?
- mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device);
- return true;
+ HeadsetService service = getService();
+ if (service == null) return false;
+ return service.stopScoUsingVirtualVoiceCall(device);
}
public void phoneStateChanged(int numActive, int numHeld, int callState,
String number, int type) {
- mStateMachine.sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
- new HeadsetCallState(numActive, numHeld, callState, number, type));
+ HeadsetService service = getService();
+ if (service == null) return;
+ service.phoneStateChanged(numActive, numHeld, callState, number, type);
}
public void roamChanged(boolean roam) {
- mStateMachine.sendMessage(HeadsetStateMachine.ROAM_CHANGED, roam);
+ HeadsetService service = getService();
+ if (service == null) return;
+ service.roamChanged(roam);
}
public void clccResponse(int index, int direction, int status, int mode, boolean mpty,
String number, int type) {
- mStateMachine.sendMessage(HeadsetStateMachine.SEND_CCLC_RESPONSE,
- new HeadsetClccResponse(index, direction, status, mode, mpty, number, type));
+ HeadsetService service = getService();
+ if (service == null) return;
+ service.clccResponse(index, direction, status, mode, mpty, number, type);
}
};
+ //API methods
+ boolean connect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+
+ if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
+ return false;
+ }
+
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState == BluetoothProfile.STATE_CONNECTED ||
+ connectionState == BluetoothProfile.STATE_CONNECTING) {
+ return false;
+ }
+
+ mStateMachine.sendMessage(HeadsetStateMachine.CONNECT, device);
+ return true;
+ }
+
+ boolean disconnect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState != BluetoothProfile.STATE_CONNECTED &&
+ connectionState != BluetoothProfile.STATE_CONNECTING) {
+ return false;
+ }
+
+ mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, device);
+ return true;
+ }
+
+ List<BluetoothDevice> getConnectedDevices() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.getConnectedDevices();
+ }
+
+ private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.getDevicesMatchingConnectionStates(states);
+ }
+
+ int getConnectionState(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.getConnectionState(device);
+ }
+
+ boolean setPriority(BluetoothDevice device, int priority) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.getBluetoothHeadsetPriorityKey(device.getAddress()),
+ priority);
+ if (DBG) Log.d(TAG, "Saved priority " + device + " = " + priority);
+ return true;
+ }
+
+ int getPriority(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int priority = Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.getBluetoothHeadsetPriorityKey(device.getAddress()),
+ BluetoothProfile.PRIORITY_UNDEFINED);
+ return priority;
+ }
+
+ boolean startVoiceRecognition(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState != BluetoothProfile.STATE_CONNECTED &&
+ connectionState != BluetoothProfile.STATE_CONNECTING) {
+ return false;
+ }
+ mStateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_START);
+ return true;
+ }
+
+ boolean stopVoiceRecognition(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ // It seem that we really need to check the AudioOn state.
+ // But since we allow startVoiceRecognition in STATE_CONNECTED and
+ // STATE_CONNECTING state, we do these 2 in this method
+ int connectionState = mStateMachine.getConnectionState(device);
+ if (connectionState != BluetoothProfile.STATE_CONNECTED &&
+ connectionState != BluetoothProfile.STATE_CONNECTING) {
+ return false;
+ }
+ mStateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP);
+ // TODO is this return correct when the voice recognition is not on?
+ return true;
+ }
+
+ boolean isAudioOn() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.isAudioOn();
+ }
+
+ boolean isAudioConnected(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return mStateMachine.isAudioConnected(device);
+ }
+
+ int getBatteryUsageHint(BluetoothDevice device) {
+ // TODO(BT) ask for BT stack support?
+ return 0;
+ }
+
+ boolean acceptIncomingConnect(BluetoothDevice device) {
+ // TODO(BT) remove it if stack does access control
+ return false;
+ }
+
+ boolean rejectIncomingConnect(BluetoothDevice device) {
+ // TODO(BT) remove it if stack does access control
+ return false;
+ }
+
+ int getAudioState(BluetoothDevice device) {
+ return mStateMachine.getAudioState(device);
+ }
+
+ boolean connectAudio() {
+ // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (!mStateMachine.isConnected()) {
+ return false;
+ }
+ if (mStateMachine.isAudioOn()) {
+ return false;
+ }
+ mStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO);
+ return true;
+ }
+
+ boolean disconnectAudio() {
+ // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (!mStateMachine.isAudioOn()) {
+ return false;
+ }
+ mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO);
+ return true;
+ }
+
+ boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) {
+ // TODO(BT) Is this right?
+ mStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device);
+ return true;
+ }
+
+ boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) {
+ // TODO(BT) Is this right?
+ mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device);
+ return true;
+ }
+
+ private void phoneStateChanged(int numActive, int numHeld, int callState,
+ String number, int type) {
+ mStateMachine.sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED,
+ new HeadsetCallState(numActive, numHeld, callState, number, type));
+ }
+
+ private void roamChanged(boolean roam) {
+ mStateMachine.sendMessage(HeadsetStateMachine.ROAM_CHANGED, roam);
+ }
+
+ private void clccResponse(int index, int direction, int status, int mode, boolean mpty,
+ String number, int type) {
+ mStateMachine.sendMessage(HeadsetStateMachine.SEND_CCLC_RESPONSE,
+ new HeadsetClccResponse(index, direction, status, mode, mpty, number, type));
+ }
+
}
diff --git a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
index 94452fa2e..974808b9e 100755
--- a/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
+++ b/src/com/android/bluetooth/hfp/HeadsetStateMachine.java
@@ -55,6 +55,8 @@ import java.util.Set;
final class HeadsetStateMachine extends StateMachine {
private static final String TAG = "HeadsetStateMachine";
private static final boolean DBG = true;
+ //For Debugging only
+ private static int sRefCount=0;
private static final String HEADSET_NAME = "bt_headset_name";
private static final String HEADSET_NREC = "bt_headset_nrec";
@@ -95,9 +97,8 @@ final class HeadsetStateMachine extends StateMachine {
private Connected mConnected;
private AudioOn mAudioOn;
- private Context mContext;
+ private HeadsetService mService;
private PowerManager mPowerManager;
-
private boolean mVoiceRecognitionStarted = false;
private boolean mWaitingForVoiceRecognition = false;
private WakeLock mStartVoiceRecognitionWakeLock; // held while waiting for voice recognition
@@ -112,6 +113,7 @@ final class HeadsetStateMachine extends StateMachine {
private int mAudioState;
private BluetoothAdapter mAdapter;
private IBluetoothHeadsetPhone mPhoneProxy;
+ private boolean mNativeAvailable;
// mCurrentDevice is the device connected before the state changes
// mTargetDevice is the device to be connected
@@ -143,10 +145,9 @@ final class HeadsetStateMachine extends StateMachine {
classInitNative();
}
- HeadsetStateMachine(Context context) {
+ HeadsetStateMachine(HeadsetService context) {
super(TAG);
-
- mContext = context;
+ mService = context;
mVoiceRecognitionStarted = false;
mWaitingForVoiceRecognition = false;
@@ -157,7 +158,7 @@ final class HeadsetStateMachine extends StateMachine {
mDialingOut = false;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
- mPhonebook = new AtPhonebook(mContext, this);
+ mPhonebook = new AtPhonebook(mService, this);
mPhoneState = new HeadsetPhoneState(context, this);
mAudioState = BluetoothHeadset.STATE_AUDIO_DISCONNECTED;
mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -167,6 +168,7 @@ final class HeadsetStateMachine extends StateMachine {
}
initializeNative();
+ mNativeAvailable=true;
mDisconnected = new Disconnected();
mPending = new Pending();
@@ -187,20 +189,32 @@ final class HeadsetStateMachine extends StateMachine {
}
public void cleanup() {
- cleanupNative();
if (mPhoneProxy != null) {
if (DBG) Log.d(TAG,"Unbinding service...");
synchronized (mConnection) {
try {
mPhoneProxy = null;
- mContext.unbindService(mConnection);
+ mService.unbindService(mConnection);
} catch (Exception re) {
- Log.e(TAG,"",re);
+ Log.e(TAG,"Error unbinding from IBluetoothHeadsetPhone",re);
}
+ }
}
+ if (mPhoneState != null) {
+ mPhoneState.listenForPhoneState(false);
+ mPhoneState.cleanup();
+ mPhoneState=null;
}
- if(mContext != null)
- mContext = null;
+ if (mPhonebook != null) {
+ mPhonebook.cleanup();
+ mPhonebook = null;
+ }
+ if (mNativeAvailable) {
+ cleanupNative();
+ mNativeAvailable = false;
+ }
+ mService = null;
+ mAdapter = null;
}
private class Disconnected extends State {
@@ -1025,7 +1039,7 @@ final class HeadsetStateMachine extends StateMachine {
!isInCall())
{
try {
- mContext.startActivity(sVoiceCommandIntent);
+ mService.startActivity(sVoiceCommandIntent);
} catch (ActivityNotFoundException e) {
atResponseCodeNative(HeadsetHalConstants.AT_RESPONSE_ERROR, 0);
return;
@@ -1136,12 +1150,9 @@ final class HeadsetStateMachine extends StateMachine {
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- mContext.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
if (DBG) log("Connection state " + device + ": " + prevState + "->" + newState);
- AdapterService svc = AdapterService.getAdapterService();
- if (svc != null) {
- svc.onProfileConnectionStateChanged(device, BluetoothProfile.HEADSET, newState, prevState);
- }
+ mService.notifyProfileConnectionStateChanged(device, BluetoothProfile.HEADSET, newState, prevState);
}
private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) {
@@ -1149,7 +1160,7 @@ final class HeadsetStateMachine extends StateMachine {
intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
- mContext.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
+ mService.sendBroadcast(intent, HeadsetService.BLUETOOTH_PERM);
if (DBG) log("Audio state " + device + ": " + prevState + "->" + newState);
}
@@ -1265,7 +1276,7 @@ final class HeadsetStateMachine extends StateMachine {
Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
Uri.fromParts(SCHEME_TEL, dialNumber, null));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ mService.startActivity(intent);
// TODO(BT) continue send OK reults code after call starts
// hold wait lock, start a timer, set wait call flag
// Get call started indication from bluetooth phone
@@ -1487,7 +1498,7 @@ final class HeadsetStateMachine extends StateMachine {
Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED,
Uri.fromParts(SCHEME_TEL, dialNumber, null));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ mService.startActivity(intent);
}
}
diff --git a/src/com/android/bluetooth/hid/HidService.java b/src/com/android/bluetooth/hid/HidService.java
index 1f76a2ccb..c522c66cc 100755
--- a/src/com/android/bluetooth/hid/HidService.java
+++ b/src/com/android/bluetooth/hid/HidService.java
@@ -4,8 +4,6 @@
package com.android.bluetooth.hid;
-import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothProfile;
@@ -27,7 +25,6 @@ import java.util.List;
import java.util.Map;
import com.android.bluetooth.Utils;
import android.content.pm.PackageManager;
-import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
/**
@@ -38,7 +35,9 @@ import com.android.bluetooth.btservice.ProfileService;
public class HidService extends ProfileService {
private static final boolean DBG = true;
private static final String TAG = "HidService";
+
private Map<BluetoothDevice, Integer> mInputDevices;
+ private boolean mNativeAvailable;
private static final int MESSAGE_CONNECT = 1;
private static final int MESSAGE_DISCONNECT = 2;
@@ -61,38 +60,35 @@ public class HidService extends ProfileService {
return TAG;
}
- @Override
- public IBinder onBind(Intent intent) {
- log("onBind");
- return mBinder;
+ public IProfileServiceBinder initBinder() {
+ return new BluetoothInputDeviceBinder(this);
}
-
protected boolean start() {
- if(mInputDevices != null) {
- mInputDevices.clear();
- mInputDevices = null;
- }
mInputDevices = Collections.synchronizedMap(new HashMap<BluetoothDevice, Integer>());
initializeNative();
-
+ mNativeAvailable=true;
return true;
}
protected boolean stop() {
if (DBG) log("Stopping Bluetooth HidService");
- cleanupNative();
+ return true;
+ }
+
+ protected boolean cleanup() {
+ if (mNativeAvailable) {
+ cleanupNative();
+ mNativeAvailable=false;
+ }
if(mInputDevices != null) {
mInputDevices.clear();
mInputDevices = null;
}
-
return true;
}
-
-
private final Handler mHandler = new Handler() {
@Override
@@ -101,7 +97,7 @@ public class HidService extends ProfileService {
case MESSAGE_CONNECT:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
- if (!connectHidNative(getByteAddress(device)) ) {
+ if (!connectHidNative(Utils.getByteAddress(device)) ) {
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
break;
@@ -111,7 +107,7 @@ public class HidService extends ProfileService {
case MESSAGE_DISCONNECT:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
- if (!disconnectHidNative(getByteAddress(device)) ) {
+ if (!disconnectHidNative(Utils.getByteAddress(device)) ) {
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTING);
broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED);
break;
@@ -128,7 +124,7 @@ public class HidService extends ProfileService {
case MESSAGE_GET_PROTOCOL_MODE:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
- if(!getProtocolModeNative(getByteAddress(device)) ) {
+ if(!getProtocolModeNative(Utils.getByteAddress(device)) ) {
Log.e(TAG, "Error: get protocol mode native returns false");
}
}
@@ -144,7 +140,7 @@ public class HidService extends ProfileService {
case MESSAGE_VIRTUAL_UNPLUG:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
- if(!virtualUnPlugNative(getByteAddress(device))) {
+ if(!virtualUnPlugNative(Utils.getByteAddress(device))) {
Log.e(TAG, "Error: virtual unplug native returns false");
}
}
@@ -154,7 +150,7 @@ public class HidService extends ProfileService {
BluetoothDevice device = (BluetoothDevice) msg.obj;
byte protocolMode = (byte) msg.arg1;
log("sending set protocol mode(" + protocolMode + ")");
- if(!setProtocolModeNative(getByteAddress(device), protocolMode)) {
+ if(!setProtocolModeNative(Utils.getByteAddress(device), protocolMode)) {
Log.e(TAG, "Error: set protocol mode native returns false");
}
}
@@ -166,7 +162,7 @@ public class HidService extends ProfileService {
byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE);
byte reportId = data.getByte(BluetoothInputDevice.EXTRA_REPORT_ID);
int bufferSize = data.getInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE);
- if(!getReportNative(getByteAddress(device), reportType, reportId, bufferSize)) {
+ if(!getReportNative(Utils.getByteAddress(device), reportType, reportId, bufferSize)) {
Log.e(TAG, "Error: get report native returns false");
}
}
@@ -177,7 +173,7 @@ public class HidService extends ProfileService {
Bundle data = msg.getData();
byte reportType = data.getByte(BluetoothInputDevice.EXTRA_REPORT_TYPE);
String report = data.getString(BluetoothInputDevice.EXTRA_REPORT);
- if(!setReportNative(getByteAddress(device), reportType, report)) {
+ if(!setReportNative(Utils.getByteAddress(device), reportType, report)) {
Log.e(TAG, "Error: set report native returns false");
}
}
@@ -187,7 +183,7 @@ public class HidService extends ProfileService {
BluetoothDevice device = (BluetoothDevice) msg.obj;
Bundle data = msg.getData();
String report = data.getString(BluetoothInputDevice.EXTRA_REPORT);
- if(!sendDataNative(getByteAddress(device), report)) {
+ if(!sendDataNative(Utils.getByteAddress(device), report)) {
Log.e(TAG, "Error: send data native returns false");
}
}
@@ -206,179 +202,264 @@ public class HidService extends ProfileService {
/**
* Handlers for incoming service calls
*/
- private final IBluetoothInputDevice.Stub mBinder = new IBluetoothInputDevice.Stub() {
- public boolean connect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) {
- Log.e(TAG, "Hid Device not disconnected: " + device);
- return false;
- }
- if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
- Log.e(TAG, "Hid Device PRIORITY_OFF: " + device);
- return false;
- }
+ private static class BluetoothInputDeviceBinder extends IBluetoothInputDevice.Stub implements IProfileServiceBinder{
+ private HidService mService;
+ public BluetoothInputDeviceBinder(HidService svc) {
+ mService = svc;
+ }
- Message msg = mHandler.obtainMessage(MESSAGE_CONNECT);
- msg.obj = device;
- mHandler.sendMessage(msg);
+ public boolean cleanup() {
+ mService = null;
return true;
}
+ private HidService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
+ }
+ return null;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ HidService service = getService();
+ if (service == null) return false;
+ return service.connect(device);
+ }
+
public boolean disconnect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT);
- msg.obj = device;
- mHandler.sendMessage(msg);
- return true;
+ HidService service = getService();
+ if (service == null) return false;
+ return service.disconnect(device);
}
public int getConnectionState(BluetoothDevice device) {
- if (mInputDevices.get(device) == null) {
- return BluetoothInputDevice.STATE_DISCONNECTED;
- }
- return mInputDevices.get(device);
+ HidService service = getService();
+ if (service == null) return BluetoothInputDevice.STATE_DISCONNECTED;
+ return service.getConnectionState(device);
}
public List<BluetoothDevice> getConnectedDevices() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<BluetoothDevice> devices = getDevicesMatchingConnectionStates(
+ return getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED});
- return devices;
}
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
-
- for (BluetoothDevice device: mInputDevices.keySet()) {
- int inputDeviceState = getConnectionState(device);
- for (int state : states) {
- if (state == inputDeviceState) {
- inputDevices.add(device);
- break;
- }
- }
- }
- return inputDevices;
+ HidService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getDevicesMatchingConnectionStates(states);
}
public boolean setPriority(BluetoothDevice device, int priority) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- Settings.Secure.putInt(getContentResolver(),
- Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
- priority);
- if (DBG) log("Saved priority " + device + " = " + priority);
- return true;
+ HidService service = getService();
+ if (service == null) return false;
+ return service.setPriority(device, priority);
}
public int getPriority(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int priority = Settings.Secure.getInt(getContentResolver(),
- Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
- BluetoothProfile.PRIORITY_UNDEFINED);
- return priority;
+ HidService service = getService();
+ if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED;
+ return service.getPriority(device);
}
+
/* The following APIs regarding test app for compliance */
public boolean getProtocolMode(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int state = this.getConnectionState(device);
- if (state != BluetoothInputDevice.STATE_CONNECTED) {
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_GET_PROTOCOL_MODE);
- msg.obj = device;
- mHandler.sendMessage(msg);
- return true;
- /* String objectPath = getObjectPathFromAddress(device.getAddress());
- return getProtocolModeInputDeviceNative(objectPath);*/
+ HidService service = getService();
+ if (service == null) return false;
+ return service.getProtocolMode(device);
}
public boolean virtualUnplug(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int state = this.getConnectionState(device);
- if (state != BluetoothInputDevice.STATE_CONNECTED) {
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_VIRTUAL_UNPLUG);
- msg.obj = device;
- mHandler.sendMessage(msg);
-
- return true;
+ HidService service = getService();
+ if (service == null) return false;
+ return service.virtualUnplug(device);
}
public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int state = this.getConnectionState(device);
- if (state != BluetoothInputDevice.STATE_CONNECTED) {
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_SET_PROTOCOL_MODE);
- msg.obj = device;
- msg.arg1 = protocolMode;
- mHandler.sendMessage(msg);
- return true ;
+ HidService service = getService();
+ if (service == null) return false;
+ return service.setProtocolMode(device, protocolMode);
}
-
+
public boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int state = this.getConnectionState(device);
- if (state != BluetoothInputDevice.STATE_CONNECTED) {
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_GET_REPORT);
- msg.obj = device;
- Bundle data = new Bundle();
- data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType);
- data.putByte(BluetoothInputDevice.EXTRA_REPORT_ID, reportId);
- data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, bufferSize);
- msg.setData(data);
- mHandler.sendMessage(msg);
- return true ;
+ HidService service = getService();
+ if (service == null) return false;
+ return service.getReport(device, reportType, reportId, bufferSize) ;
}
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int state = this.getConnectionState(device);
- if (state != BluetoothInputDevice.STATE_CONNECTED) {
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_SET_REPORT);
- msg.obj = device;
- Bundle data = new Bundle();
- data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType);
- data.putString(BluetoothInputDevice.EXTRA_REPORT, report);
- msg.setData(data);
- mHandler.sendMessage(msg);
- return true ;
-
+ HidService service = getService();
+ if (service == null) return false;
+ return service.setReport(device, reportType, report);
}
public boolean sendData(BluetoothDevice device, String report) {
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
- "Need BLUETOOTH_ADMIN permission");
- int state = this.getConnectionState(device);
- if (state != BluetoothInputDevice.STATE_CONNECTED) {
- return false;
+ HidService service = getService();
+ if (service == null) return false;
+ return service.sendData(device, report);
+ }
+ };
+
+ //APIs
+ boolean connect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (getConnectionState(device) != BluetoothInputDevice.STATE_DISCONNECTED) {
+ Log.e(TAG, "Hid Device not disconnected: " + device);
+ return false;
+ }
+ if (getPriority(device) == BluetoothInputDevice.PRIORITY_OFF) {
+ Log.e(TAG, "Hid Device PRIORITY_OFF: " + device);
+ return false;
+ }
+
+ Message msg = mHandler.obtainMessage(MESSAGE_CONNECT, device);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean disconnect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ int getConnectionState(BluetoothDevice device) {
+ if (mInputDevices.get(device) == null) {
+ return BluetoothInputDevice.STATE_DISCONNECTED;
+ }
+ return mInputDevices.get(device);
+ }
+
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
+
+ for (BluetoothDevice device: mInputDevices.keySet()) {
+ int inputDeviceState = getConnectionState(device);
+ for (int state : states) {
+ if (state == inputDeviceState) {
+ inputDevices.add(device);
+ break;
+ }
}
+ }
+ return inputDevices;
+ }
- return sendDataNative(getByteAddress(device), report);
- /*Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA);
- msg.obj = device;
- Bundle data = new Bundle();
- data.putString(BluetoothInputDevice.EXTRA_REPORT, report);
- msg.setData(data);
- mHandler.sendMessage(msg);
- return true ;*/
+ boolean setPriority(BluetoothDevice device, int priority) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
+ priority);
+ if (DBG) Log.d(TAG,"Saved priority " + device + " = " + priority);
+ return true;
+ }
+
+ int getPriority(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int priority = Settings.Secure.getInt(getContentResolver(),
+ Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
+ BluetoothProfile.PRIORITY_UNDEFINED);
+ return priority;
+ }
+
+ /* The following APIs regarding test app for compliance */
+ boolean getProtocolMode(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int state = this.getConnectionState(device);
+ if (state != BluetoothInputDevice.STATE_CONNECTED) {
+ return false;
}
- };
+ Message msg = mHandler.obtainMessage(MESSAGE_GET_PROTOCOL_MODE,device);
+ mHandler.sendMessage(msg);
+ return true;
+ /* String objectPath = getObjectPathFromAddress(device.getAddress());
+ return getProtocolModeInputDeviceNative(objectPath);*/
+ }
+ boolean virtualUnplug(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int state = this.getConnectionState(device);
+ if (state != BluetoothInputDevice.STATE_CONNECTED) {
+ return false;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_VIRTUAL_UNPLUG,device);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int state = this.getConnectionState(device);
+ if (state != BluetoothInputDevice.STATE_CONNECTED) {
+ return false;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_SET_PROTOCOL_MODE);
+ msg.obj = device;
+ msg.arg1 = protocolMode;
+ mHandler.sendMessage(msg);
+ return true ;
+ }
+
+ boolean getReport(BluetoothDevice device, byte reportType, byte reportId, int bufferSize) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int state = this.getConnectionState(device);
+ if (state != BluetoothInputDevice.STATE_CONNECTED) {
+ return false;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_GET_REPORT);
+ msg.obj = device;
+ Bundle data = new Bundle();
+ data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType);
+ data.putByte(BluetoothInputDevice.EXTRA_REPORT_ID, reportId);
+ data.putInt(BluetoothInputDevice.EXTRA_REPORT_BUFFER_SIZE, bufferSize);
+ msg.setData(data);
+ mHandler.sendMessage(msg);
+ return true ;
+ }
+
+ boolean setReport(BluetoothDevice device, byte reportType, String report) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int state = this.getConnectionState(device);
+ if (state != BluetoothInputDevice.STATE_CONNECTED) {
+ return false;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_SET_REPORT);
+ msg.obj = device;
+ Bundle data = new Bundle();
+ data.putByte(BluetoothInputDevice.EXTRA_REPORT_TYPE, reportType);
+ data.putString(BluetoothInputDevice.EXTRA_REPORT, report);
+ msg.setData(data);
+ mHandler.sendMessage(msg);
+ return true ;
+
+ }
+
+ boolean sendData(BluetoothDevice device, String report) {
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ int state = this.getConnectionState(device);
+ if (state != BluetoothInputDevice.STATE_CONNECTED) {
+ return false;
+ }
+
+ return sendDataNative(Utils.getByteAddress(device), report);
+ /*Message msg = mHandler.obtainMessage(MESSAGE_SEND_DATA);
+ msg.obj = device;
+ Bundle data = new Bundle();
+ data.putString(BluetoothInputDevice.EXTRA_REPORT, report);
+ msg.setData(data);
+ mHandler.sendMessage(msg);
+ return true ;*/
+ }
+
private void onGetProtocolMode(byte[] address, int mode) {
Message msg = mHandler.obtainMessage(MESSAGE_ON_GET_PROTOCOL_MODE);
msg.obj = address;
@@ -418,10 +499,7 @@ public class HidService extends ProfileService {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
sendBroadcast(intent, BLUETOOTH_PERM);
if (DBG) log("Connection state " + device + ": " + prevState + "->" + newState);
- AdapterService svc = AdapterService.getAdapterService();
- if (svc != null) {
- svc.onProfileConnectionStateChanged(device, BluetoothProfile.INPUT_DEVICE, newState, prevState);
- }
+ notifyProfileConnectionStateChanged(device, BluetoothProfile.INPUT_DEVICE, newState, prevState);
}
private void broadcastProtocolMode(BluetoothDevice device, int protocolMode) {
@@ -441,15 +519,7 @@ public class HidService extends ProfileService {
sendBroadcast(intent, BLUETOOTH_PERM);
}
- private BluetoothDevice getDevice(byte[] address) {
- return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
- }
-
- private byte[] getByteAddress(BluetoothDevice device) {
- return Utils.getBytesFromAddress(device.getAddress());
- }
-
- private int convertHalState(int halState) {
+ private static int convertHalState(int halState) {
switch (halState) {
case CONN_STATE_CONNECTED:
return BluetoothProfile.STATE_CONNECTED;
@@ -465,7 +535,6 @@ public class HidService extends ProfileService {
}
}
-
// Constants matching Hal header file bt_hh.h
// bthh_connection_state_t
private final static int CONN_STATE_CONNECTED = 0;
diff --git a/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java b/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
index ec0f8b26e..0bdc6df60 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppIncomingFileConfirmActivity.java
@@ -91,6 +91,7 @@ public class BluetoothOppIncomingFileConfirmActivity extends AlertActivity imple
@Override
protected void onCreate(Bundle savedInstanceState) {
+ if (V) Log.d(TAG, "onCreate(): action = " + getIntent().getAction());
super.onCreate(savedInstanceState);
Intent intent = getIntent();
diff --git a/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
index 8f2b9107f..f9e96f558 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java
@@ -151,7 +151,7 @@ public class BluetoothOppLauncherActivity extends Activity {
Constants.THIS_PACKAGE_NAME);
in1.putExtra(BluetoothDevicePicker.EXTRA_LAUNCH_CLASS,
BluetoothOppReceiver.class.getName());
-
+ if (V) {Log.d(TAG,"Launching " +BluetoothDevicePicker.ACTION_LAUNCH );}
this.startActivity(in1);
}
} else if (action.equals(Constants.ACTION_OPEN)) {
diff --git a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
index ea7e4b20a..f234203ce 100644
--- a/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
+++ b/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java
@@ -59,7 +59,7 @@ import java.lang.Thread;
*/
public class BluetoothOppObexClientSession implements BluetoothOppObexSession {
- private static final String TAG = "BtOpp ObexClient";
+ private static final String TAG = "BtOppObexClient";
private static final boolean D = Constants.DEBUG;
private static final boolean V = Constants.VERBOSE;
diff --git a/src/com/android/bluetooth/pan/PanService.java b/src/com/android/bluetooth/pan/PanService.java
index 1d21e7c80..97fe37b82 100755
--- a/src/com/android/bluetooth/pan/PanService.java
+++ b/src/com/android/bluetooth/pan/PanService.java
@@ -5,7 +5,6 @@
package com.android.bluetooth.pan;
import android.app.Service;
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
@@ -36,7 +35,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.android.bluetooth.Utils;
-import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
/**
@@ -56,6 +54,7 @@ public class PanService extends ProfileService {
private ArrayList<String> mBluetoothIfaceAddresses;
private int mMaxPanDevices;
private String mPanIfName;
+ private boolean mNativeAvailable;
private static final int MESSAGE_CONNECT = 1;
private static final int MESSAGE_DISCONNECT = 2;
@@ -71,30 +70,11 @@ public class PanService extends ProfileService {
return TAG;
}
- @Override
- public IBinder onBind(Intent intent) {
- log("onBind");
- return mBinder;
+ public IProfileServiceBinder initBinder() {
+ return new BluetoothPanBinder(this);
}
protected boolean start() {
-
- //Cleanup referenced objects here
-
- if(mPanDevices != null) {
- mPanDevices.clear();
- mPanDevices = null;
- }
- if(mBluetoothIfaceAddresses != null) {
- mBluetoothIfaceAddresses.clear();
- mBluetoothIfaceAddresses = null;
- }
- if(mPanIfName != null)
- mPanIfName = null;
- if(mHandler != null)
- mHandler.removeCallbacksAndMessages(null);
-
- if (DBG) log("start");
mPanDevices = new HashMap<BluetoothDevice, BluetoothPanDevice>();
mBluetoothIfaceAddresses = new ArrayList<String>();
try {
@@ -103,17 +83,22 @@ public class PanService extends ProfileService {
} catch (NotFoundException e) {
mMaxPanDevices = BLUETOOTH_MAX_PAN_CONNECTIONS;
}
-
initializeNative();
+ mNativeAvailable=true;
return true;
}
protected boolean stop() {
if (DBG) log("stop");
+ mHandler.removeCallbacksAndMessages(null);
+ return true;
+ }
- //Cleanup native
- cleanupNative();
-
+ protected boolean cleanup() {
+ if (mNativeAvailable) {
+ cleanupNative();
+ mNativeAvailable=false;
+ }
if(mPanDevices != null) {
mPanDevices.clear();
mPanDevices = null;
@@ -124,20 +109,17 @@ public class PanService extends ProfileService {
}
if(mPanIfName != null)
mPanIfName = null;
- if(mHandler != null)
- mHandler.removeCallbacksAndMessages(null);
return true;
}
private final Handler mHandler = new Handler() {
-
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_CONNECT:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
- if (!connectPanNative(getByteAddress(device), BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE)) {
+ if (!connectPanNative(Utils.getByteAddress(device), BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE)) {
handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_CONNECTING,
BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
handlePanDeviceStateChange(device, null, BluetoothProfile.STATE_DISCONNECTED,
@@ -149,7 +131,7 @@ public class PanService extends ProfileService {
case MESSAGE_DISCONNECT:
{
BluetoothDevice device = (BluetoothDevice) msg.obj;
- if (!disconnectPanNative(getByteAddress(device)) ) {
+ if (!disconnectPanNative(Utils.getByteAddress(device)) ) {
handlePanDeviceStateChange(device, mPanIfName, BluetoothProfile.STATE_DISCONNECTING,
BluetoothPan.LOCAL_PANU_ROLE, BluetoothPan.REMOTE_NAP_ROLE);
handlePanDeviceStateChange(device, mPanIfName, BluetoothProfile.STATE_DISCONNECTED,
@@ -175,82 +157,146 @@ public class PanService extends ProfileService {
/**
* Handlers for incoming service calls
*/
- private final IBluetoothPan.Stub mBinder = new IBluetoothPan.Stub() {
- public boolean connect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (getConnectionState(device) != BluetoothProfile.STATE_DISCONNECTED) {
- Log.e(TAG, "Pan Device not disconnected: " + device);
- return false;
- }
- Message msg = mHandler.obtainMessage(MESSAGE_CONNECT);
- msg.obj = device;
- mHandler.sendMessage(msg);
+ private static class BluetoothPanBinder extends IBluetoothPan.Stub implements IProfileServiceBinder {
+ private PanService mService;
+ public BluetoothPanBinder(PanService svc) {
+ mService = svc;
+ }
+ public boolean cleanup() {
+ mService = null;
return true;
}
-
+ private PanService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
+ }
+ return null;
+ }
+ public boolean connect(BluetoothDevice device) {
+ PanService service = getService();
+ if (service == null) return false;
+ return service.connect(device);
+ }
public boolean disconnect(BluetoothDevice device) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT);
- msg.obj = device;
- mHandler.sendMessage(msg);
- return true;
+ PanService service = getService();
+ if (service == null) return false;
+ return service.disconnect(device);
}
-
public int getConnectionState(BluetoothDevice device) {
- BluetoothPanDevice panDevice = mPanDevices.get(device);
- if (panDevice == null) {
- return BluetoothPan.STATE_DISCONNECTED;
- }
- return panDevice.mState;
+ PanService service = getService();
+ if (service == null) return BluetoothPan.STATE_DISCONNECTED;
+ return service.getConnectionState(device);
}
private boolean isPanNapOn() {
- if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
- return (getPanLocalRoleNative() & BluetoothPan.LOCAL_NAP_ROLE) != 0;
+ PanService service = getService();
+ if (service == null) return false;
+ return service.isPanNapOn();
}
private boolean isPanUOn() {
if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
- return (getPanLocalRoleNative() & BluetoothPan.LOCAL_PANU_ROLE) != 0;
+ PanService service = getService();
+ return service.isPanUOn();
}
public boolean isTetheringOn() {
// TODO(BT) have a variable marking the on/off state
- return mTetherOn;
+ PanService service = getService();
+ if (service == null) return false;
+ return service.isTetheringOn();
}
-
public void setBluetoothTethering(boolean value) {
- if(DBG) Log.d(TAG, "setBluetoothTethering: " + value +", mTetherOn: " + mTetherOn);
- enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
- if(mTetherOn != value) {
- //drop any existing panu or pan-nap connection when changing the tethering state
- mTetherOn = value;
- List<BluetoothDevice> DevList = getConnectedDevices();
- for(BluetoothDevice dev : DevList)
- disconnect(dev);
- }
+ PanService service = getService();
+ if (service == null) return;
+ if(DBG) Log.d(TAG, "setBluetoothTethering: " + value +", mTetherOn: " + service.mTetherOn);
+ service.setBluetoothTethering(value);
}
public List<BluetoothDevice> getConnectedDevices() {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<BluetoothDevice> devices = getDevicesMatchingConnectionStates(
- new int[] {BluetoothProfile.STATE_CONNECTED});
- return devices;
+ PanService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getConnectedDevices();
}
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- List<BluetoothDevice> panDevices = new ArrayList<BluetoothDevice>();
-
- for (BluetoothDevice device: mPanDevices.keySet()) {
- int panDeviceState = getConnectionState(device);
- for (int state : states) {
- if (state == panDeviceState) {
- panDevices.add(device);
- break;
- }
+ PanService service = getService();
+ if (service == null) return new ArrayList<BluetoothDevice>(0);
+ return service.getDevicesMatchingConnectionStates(states);
+ }
+ };
+
+ boolean connect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ if (getConnectionState(device) != BluetoothProfile.STATE_DISCONNECTED) {
+ Log.e(TAG, "Pan Device not disconnected: " + device);
+ return false;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_CONNECT,device);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ boolean disconnect(BluetoothDevice device) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ Message msg = mHandler.obtainMessage(MESSAGE_DISCONNECT,device);
+ mHandler.sendMessage(msg);
+ return true;
+ }
+
+ int getConnectionState(BluetoothDevice device) {
+ BluetoothPanDevice panDevice = mPanDevices.get(device);
+ if (panDevice == null) {
+ return BluetoothPan.STATE_DISCONNECTED;
+ }
+ return panDevice.mState;
+ }
+
+ boolean isPanNapOn() {
+ if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
+ return (getPanLocalRoleNative() & BluetoothPan.LOCAL_NAP_ROLE) != 0;
+ }
+ boolean isPanUOn() {
+ if(DBG) Log.d(TAG, "isTetheringOn call getPanLocalRoleNative");
+ return (getPanLocalRoleNative() & BluetoothPan.LOCAL_PANU_ROLE) != 0;
+ }
+ boolean isTetheringOn() {
+ // TODO(BT) have a variable marking the on/off state
+ return mTetherOn;
+ }
+
+ void setBluetoothTethering(boolean value) {
+ if(DBG) Log.d(TAG, "setBluetoothTethering: " + value +", mTetherOn: " + mTetherOn);
+ enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
+ if(mTetherOn != value) {
+ //drop any existing panu or pan-nap connection when changing the tethering state
+ mTetherOn = value;
+ List<BluetoothDevice> DevList = getConnectedDevices();
+ for(BluetoothDevice dev : DevList)
+ disconnect(dev);
+ }
+ }
+
+ List<BluetoothDevice> getConnectedDevices() {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ List<BluetoothDevice> devices = getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED});
+ return devices;
+ }
+
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ List<BluetoothDevice> panDevices = new ArrayList<BluetoothDevice>();
+
+ for (BluetoothDevice device: mPanDevices.keySet()) {
+ int panDeviceState = getConnectionState(device);
+ for (int state : states) {
+ if (state == panDeviceState) {
+ panDevices.add(device);
+ break;
}
}
- return panDevices;
}
- };
+ return panDevices;
+ }
+
static protected class ConnectState {
public ConnectState(byte[] address, int state, int error, int local_role, int remote_role) {
this.addr = address;
@@ -277,15 +323,8 @@ public class PanService extends ProfileService {
if(error == 0)
mPanIfName = ifname;
}
- private BluetoothDevice getDevice(byte[] address) {
- return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
- }
- private byte[] getByteAddress(BluetoothDevice device) {
- return Utils.getBytesFromAddress(device.getAddress());
- }
-
- private int convertHalState(int halState) {
+ private static int convertHalState(int halState) {
switch (halState) {
case CONN_STATE_CONNECTED:
return BluetoothProfile.STATE_CONNECTED;
@@ -321,7 +360,7 @@ public class PanService extends ProfileService {
if (state == BluetoothProfile.STATE_CONNECTED) {
if(!mTetherOn) {
Log.d(TAG, "handlePanDeviceStateChange bluetooth tethering is off, drop the connection");
- disconnectPanNative(getByteAddress(device));
+ disconnectPanNative(Utils.getByteAddress(device));
return;
}
ifaceAddr = enableTethering(iface);
@@ -382,10 +421,7 @@ public class PanService extends ProfileService {
if (DBG) Log.d(TAG, "Pan Device state : device: " + device + " State:" +
prevState + "->" + state);
- AdapterService svc = AdapterService.getAdapterService();
- if (svc != null) {
- svc.onProfileConnectionStateChanged(device, BluetoothProfile.PAN, state, prevState);
- }
+ notifyProfileConnectionStateChanged(device, BluetoothProfile.PAN, state, prevState);
}
// configured when we start tethering
@@ -512,4 +548,5 @@ public class PanService extends ProfileService {
private native boolean disconnectPanNative(byte[] btAddress);
private native boolean enablePanNative(int local_role);
private native int getPanLocalRoleNative();
+
}
diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
index 5d7be8462..982a32271 100755
--- a/src/com/android/bluetooth/pbap/BluetoothPbapService.java
+++ b/src/com/android/bluetooth/pbap/BluetoothPbapService.java
@@ -641,16 +641,11 @@ public class BluetoothPbapService extends Service {
intent.putExtra(BluetoothPbap.PBAP_STATE, mState);
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, mRemoteDevice);
sendBroadcast(intent, BLUETOOTH_PERM);
- //if (mBluetoothService != null) {
AdapterService s = AdapterService.getAdapterService();
if (s != null) {
s.onProfileConnectionStateChanged(mRemoteDevice, BluetoothProfile.PBAP,
mState, prevState);
}
- /*
- } else {
- Log.e(TAG, "null mBluetoothService");
- }*/
}
}