am fb967585: Merge "Change the routing path of bluetooth headset connections." into lmp-mr1-dev
* commit 'fb967585cc43937a88b0ed9a5e434a50b0a498b9': Change the routing path of bluetooth headset connections.
This commit is contained in:
@@ -100,6 +100,7 @@ LOCAL_SRC_FILES += \
|
|||||||
core/java/android/bluetooth/IBluetoothA2dpSink.aidl \
|
core/java/android/bluetooth/IBluetoothA2dpSink.aidl \
|
||||||
core/java/android/bluetooth/IBluetoothAvrcpController.aidl \
|
core/java/android/bluetooth/IBluetoothAvrcpController.aidl \
|
||||||
core/java/android/bluetooth/IBluetoothCallback.aidl \
|
core/java/android/bluetooth/IBluetoothCallback.aidl \
|
||||||
|
core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl \
|
||||||
core/java/android/bluetooth/IBluetoothHeadset.aidl \
|
core/java/android/bluetooth/IBluetoothHeadset.aidl \
|
||||||
core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \
|
core/java/android/bluetooth/IBluetoothHeadsetPhone.aidl \
|
||||||
core/java/android/bluetooth/IBluetoothHealth.aidl \
|
core/java/android/bluetooth/IBluetoothHealth.aidl \
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ import android.annotation.SdkConstant;
|
|||||||
import android.annotation.SdkConstant.SdkConstantType;
|
import android.annotation.SdkConstant.SdkConstantType;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.os.Handler;
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.os.Message;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -221,11 +222,14 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
*/
|
*/
|
||||||
public static final int STATE_AUDIO_CONNECTED = 12;
|
public static final int STATE_AUDIO_CONNECTED = 12;
|
||||||
|
|
||||||
|
private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100;
|
||||||
|
private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private ServiceListener mServiceListener;
|
private ServiceListener mServiceListener;
|
||||||
private IBluetoothHeadset mService;
|
private IBluetoothHeadset mService;
|
||||||
private BluetoothAdapter mAdapter;
|
private BluetoothAdapter mAdapter;
|
||||||
|
private boolean mIsClosed;
|
||||||
|
|
||||||
final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||||
new IBluetoothStateChangeCallback.Stub() {
|
new IBluetoothStateChangeCallback.Stub() {
|
||||||
@@ -233,14 +237,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||||
if (!up) {
|
if (!up) {
|
||||||
if (VDBG) Log.d(TAG,"Unbinding service...");
|
if (VDBG) Log.d(TAG,"Unbinding service...");
|
||||||
synchronized (mConnection) {
|
doUnbind();
|
||||||
try {
|
|
||||||
mService = null;
|
|
||||||
mContext.unbindService(mConnection);
|
|
||||||
} catch (Exception re) {
|
|
||||||
Log.e(TAG,"",re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
synchronized (mConnection) {
|
synchronized (mConnection) {
|
||||||
try {
|
try {
|
||||||
@@ -263,6 +260,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mServiceListener = l;
|
mServiceListener = l;
|
||||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
|
mIsClosed = false;
|
||||||
|
|
||||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||||
if (mgr != null) {
|
if (mgr != null) {
|
||||||
@@ -277,15 +275,26 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean doBind() {
|
boolean doBind() {
|
||||||
Intent intent = new Intent(IBluetoothHeadset.class.getName());
|
try {
|
||||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
return mAdapter.getBluetoothManager().bindBluetoothProfileService(
|
||||||
intent.setComponent(comp);
|
BluetoothProfile.HEADSET, mConnection);
|
||||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
} catch (RemoteException e) {
|
||||||
android.os.Process.myUserHandle())) {
|
Log.e(TAG, "Unable to bind HeadsetService", e);
|
||||||
Log.e(TAG, "Could not bind to Bluetooth Headset Service with " + intent);
|
}
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void doUnbind() {
|
||||||
|
synchronized (mConnection) {
|
||||||
|
if (mService != null) {
|
||||||
|
try {
|
||||||
|
mAdapter.getBluetoothManager().unbindBluetoothProfileService(
|
||||||
|
BluetoothProfile.HEADSET, mConnection);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG,"Unable to unbind HeadsetService", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -305,18 +314,8 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
Log.e(TAG,"",e);
|
Log.e(TAG,"",e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mIsClosed = true;
|
||||||
synchronized (mConnection) {
|
doUnbind();
|
||||||
if (mService != null) {
|
|
||||||
try {
|
|
||||||
mService = null;
|
|
||||||
mContext.unbindService(mConnection);
|
|
||||||
} catch (Exception re) {
|
|
||||||
Log.e(TAG,"",re);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mServiceListener = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -930,21 +929,21 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
private final IBluetoothProfileServiceConnection mConnection
|
||||||
|
= new IBluetoothProfileServiceConnection.Stub() {
|
||||||
|
@Override
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||||
mService = IBluetoothHeadset.Stub.asInterface(service);
|
mService = IBluetoothHeadset.Stub.asInterface(service);
|
||||||
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
if (mServiceListener != null) {
|
MESSAGE_HEADSET_SERVICE_CONNECTED));
|
||||||
mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, BluetoothHeadset.this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||||
mService = null;
|
mService = null;
|
||||||
if (mServiceListener != null) {
|
mHandler.sendMessage(mHandler.obtainMessage(
|
||||||
mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
|
MESSAGE_HEADSET_SERVICE_DISCONNECTED));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -968,4 +967,28 @@ public final class BluetoothHeadset implements BluetoothProfile {
|
|||||||
private static void log(String msg) {
|
private static void log(String msg) {
|
||||||
Log.d(TAG, msg);
|
Log.d(TAG, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
|
||||||
|
@Override
|
||||||
|
public void handleMessage(Message msg) {
|
||||||
|
switch (msg.what) {
|
||||||
|
case MESSAGE_HEADSET_SERVICE_CONNECTED: {
|
||||||
|
if (mServiceListener != null) {
|
||||||
|
mServiceListener.onServiceConnected(BluetoothProfile.HEADSET,
|
||||||
|
BluetoothHeadset.this);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MESSAGE_HEADSET_SERVICE_DISCONNECTED: {
|
||||||
|
if (mServiceListener != null) {
|
||||||
|
mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET);
|
||||||
|
}
|
||||||
|
if (mIsClosed){
|
||||||
|
mServiceListener = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package android.bluetooth;
|
|||||||
import android.bluetooth.IBluetooth;
|
import android.bluetooth.IBluetooth;
|
||||||
import android.bluetooth.IBluetoothGatt;
|
import android.bluetooth.IBluetoothGatt;
|
||||||
import android.bluetooth.IBluetoothManagerCallback;
|
import android.bluetooth.IBluetoothManagerCallback;
|
||||||
|
import android.bluetooth.IBluetoothProfileServiceConnection;
|
||||||
import android.bluetooth.IBluetoothStateChangeCallback;
|
import android.bluetooth.IBluetoothStateChangeCallback;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +39,9 @@ interface IBluetoothManager
|
|||||||
boolean disable(boolean persist);
|
boolean disable(boolean persist);
|
||||||
IBluetoothGatt getBluetoothGatt();
|
IBluetoothGatt getBluetoothGatt();
|
||||||
|
|
||||||
|
boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
|
||||||
|
void unbindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy);
|
||||||
|
|
||||||
String getAddress();
|
String getAddress();
|
||||||
String getName();
|
String getName();
|
||||||
}
|
}
|
||||||
|
|||||||
30
core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl
Executable file
30
core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.bluetooth;
|
||||||
|
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for bluetooth profile connections.
|
||||||
|
*
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
interface IBluetoothProfileServiceConnection {
|
||||||
|
void onServiceConnected(in ComponentName comp, in IBinder service);
|
||||||
|
void onServiceDisconnected(in ComponentName comp);
|
||||||
|
}
|
||||||
@@ -18,11 +18,14 @@ package com.android.server;
|
|||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
|
import android.bluetooth.BluetoothProfile;
|
||||||
import android.bluetooth.IBluetooth;
|
import android.bluetooth.IBluetooth;
|
||||||
import android.bluetooth.IBluetoothGatt;
|
import android.bluetooth.IBluetoothGatt;
|
||||||
import android.bluetooth.IBluetoothCallback;
|
import android.bluetooth.IBluetoothCallback;
|
||||||
|
import android.bluetooth.IBluetoothHeadset;
|
||||||
import android.bluetooth.IBluetoothManager;
|
import android.bluetooth.IBluetoothManager;
|
||||||
import android.bluetooth.IBluetoothManagerCallback;
|
import android.bluetooth.IBluetoothManagerCallback;
|
||||||
|
import android.bluetooth.IBluetoothProfileServiceConnection;
|
||||||
import android.bluetooth.IBluetoothStateChangeCallback;
|
import android.bluetooth.IBluetoothStateChangeCallback;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
@@ -32,6 +35,7 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -42,12 +46,18 @@ import android.os.RemoteCallbackList;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.os.UserManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
class BluetoothManagerService extends IBluetoothManager.Stub {
|
class BluetoothManagerService extends IBluetoothManager.Stub {
|
||||||
private static final String TAG = "BluetoothManagerService";
|
private static final String TAG = "BluetoothManagerService";
|
||||||
private static final boolean DBG = true;
|
private static final boolean DBG = true;
|
||||||
@@ -67,6 +77,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
private static final int ERROR_RESTART_TIME_MS = 3000;
|
private static final int ERROR_RESTART_TIME_MS = 3000;
|
||||||
//Maximum msec to delay MESSAGE_USER_SWITCHED
|
//Maximum msec to delay MESSAGE_USER_SWITCHED
|
||||||
private static final int USER_SWITCHED_TIME_MS = 200;
|
private static final int USER_SWITCHED_TIME_MS = 200;
|
||||||
|
// Delay for the addProxy function in msec
|
||||||
|
private static final int ADD_PROXY_DELAY_MS = 100;
|
||||||
|
|
||||||
private static final int MESSAGE_ENABLE = 1;
|
private static final int MESSAGE_ENABLE = 1;
|
||||||
private static final int MESSAGE_DISABLE = 2;
|
private static final int MESSAGE_DISABLE = 2;
|
||||||
@@ -83,6 +95,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
|
private static final int MESSAGE_GET_NAME_AND_ADDRESS=200;
|
||||||
private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
|
private static final int MESSAGE_SAVE_NAME_AND_ADDRESS=201;
|
||||||
private static final int MESSAGE_USER_SWITCHED = 300;
|
private static final int MESSAGE_USER_SWITCHED = 300;
|
||||||
|
private static final int MESSAGE_ADD_PROXY_DELAYED = 400;
|
||||||
|
private static final int MESSAGE_BIND_PROFILE_SERVICE = 401;
|
||||||
private static final int MAX_SAVE_RETRIES=3;
|
private static final int MAX_SAVE_RETRIES=3;
|
||||||
private static final int MAX_ERROR_RESTART_RETRIES=6;
|
private static final int MAX_ERROR_RESTART_RETRIES=6;
|
||||||
|
|
||||||
@@ -127,6 +141,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
private int mErrorRecoveryRetryCounter;
|
private int mErrorRecoveryRetryCounter;
|
||||||
private final int mSystemUiUid;
|
private final int mSystemUiUid;
|
||||||
|
|
||||||
|
// Save a ProfileServiceConnections object for each of the bound
|
||||||
|
// bluetooth profile services
|
||||||
|
private final Map <Integer, ProfileServiceConnections> mProfileServices =
|
||||||
|
new HashMap <Integer, ProfileServiceConnections>();
|
||||||
|
|
||||||
private void registerForAirplaneMode(IntentFilter filter) {
|
private void registerForAirplaneMode(IntentFilter filter) {
|
||||||
final ContentResolver resolver = mContext.getContentResolver();
|
final ContentResolver resolver = mContext.getContentResolver();
|
||||||
final String airplaneModeRadios = Settings.Global.getString(resolver,
|
final String airplaneModeRadios = Settings.Global.getString(resolver,
|
||||||
@@ -499,6 +518,187 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
return mBluetoothGatt;
|
return mBluetoothGatt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean bindBluetoothProfileService(int bluetoothProfile,
|
||||||
|
IBluetoothProfileServiceConnection proxy) {
|
||||||
|
if (!mEnable) {
|
||||||
|
if (DBG) {
|
||||||
|
Log.d(TAG, "Trying to bind to profile: " + bluetoothProfile +
|
||||||
|
", while Bluetooth was disabled");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
synchronized (mProfileServices) {
|
||||||
|
ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
|
||||||
|
if (psc == null) {
|
||||||
|
if (DBG) {
|
||||||
|
Log.d(TAG, "Creating new ProfileServiceConnections object for"
|
||||||
|
+ " profile: " + bluetoothProfile);
|
||||||
|
}
|
||||||
|
Intent intent = null;
|
||||||
|
if (bluetoothProfile == BluetoothProfile.HEADSET) {
|
||||||
|
intent = new Intent(IBluetoothHeadset.class.getName());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
psc = new ProfileServiceConnections(intent);
|
||||||
|
mProfileServices.put(new Integer(bluetoothProfile), psc);
|
||||||
|
psc.bindService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Introducing a delay to give the client app time to prepare
|
||||||
|
Message addProxyMsg = mHandler.obtainMessage(MESSAGE_ADD_PROXY_DELAYED);
|
||||||
|
addProxyMsg.arg1 = bluetoothProfile;
|
||||||
|
addProxyMsg.obj = proxy;
|
||||||
|
mHandler.sendMessageDelayed(addProxyMsg, ADD_PROXY_DELAY_MS);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unbindBluetoothProfileService(int bluetoothProfile,
|
||||||
|
IBluetoothProfileServiceConnection proxy) {
|
||||||
|
synchronized (mProfileServices) {
|
||||||
|
ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
|
||||||
|
if (psc == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
psc.removeProxy(proxy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unbindAllBluetoothProfileServices() {
|
||||||
|
synchronized (mProfileServices) {
|
||||||
|
for (Integer i : mProfileServices.keySet()) {
|
||||||
|
ProfileServiceConnections psc = mProfileServices.get(i);
|
||||||
|
mContext.unbindService(psc);
|
||||||
|
psc.removeAllProxies();
|
||||||
|
}
|
||||||
|
mProfileServices.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages the clients connected to a given ProfileService
|
||||||
|
* and maintains the connection with that service.
|
||||||
|
*/
|
||||||
|
final private class ProfileServiceConnections implements ServiceConnection,
|
||||||
|
IBinder.DeathRecipient {
|
||||||
|
final RemoteCallbackList<IBluetoothProfileServiceConnection> mProxies =
|
||||||
|
new RemoteCallbackList <IBluetoothProfileServiceConnection>();
|
||||||
|
IBinder mService;
|
||||||
|
ComponentName mClassName;
|
||||||
|
Intent mIntent;
|
||||||
|
|
||||||
|
ProfileServiceConnections(Intent intent) {
|
||||||
|
mService = null;
|
||||||
|
mClassName = null;
|
||||||
|
mIntent = intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindService() {
|
||||||
|
if (mIntent != null && mService == null) {
|
||||||
|
if (!doBind(mIntent, this, 0, UserHandle.CURRENT_OR_SELF)) {
|
||||||
|
Log.w(TAG, "Unable to bind with intent: " + mIntent
|
||||||
|
+ ". Triggering retry.");
|
||||||
|
}
|
||||||
|
Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
|
||||||
|
msg.obj = this;
|
||||||
|
mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addProxy(IBluetoothProfileServiceConnection proxy) {
|
||||||
|
mProxies.register(proxy);
|
||||||
|
if (mService != null) {
|
||||||
|
try{
|
||||||
|
proxy.onServiceConnected(mClassName, mService);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to connect to proxy", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!mHandler.hasMessages(MESSAGE_BIND_PROFILE_SERVICE, this)) {
|
||||||
|
Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
|
||||||
|
msg.obj = this;
|
||||||
|
mHandler.sendMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeProxy(IBluetoothProfileServiceConnection proxy) {
|
||||||
|
if (proxy != null) {
|
||||||
|
if (mProxies.unregister(proxy)) {
|
||||||
|
try {
|
||||||
|
proxy.onServiceDisconnected(mClassName);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to disconnect proxy", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Trying to remove a null proxy");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeAllProxies() {
|
||||||
|
onServiceDisconnected(mClassName);
|
||||||
|
mProxies.kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
// remove timeout message
|
||||||
|
mHandler.removeMessages(MESSAGE_BIND_PROFILE_SERVICE, this);
|
||||||
|
mService = service;
|
||||||
|
mClassName = className;
|
||||||
|
try {
|
||||||
|
mService.linkToDeath(this, 0);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to linkToDeath", e);
|
||||||
|
}
|
||||||
|
int n = mProxies.beginBroadcast();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
try {
|
||||||
|
mProxies.getBroadcastItem(i).onServiceConnected(className, service);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to connect to proxy", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mProxies.finishBroadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
if (mService == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mService.unlinkToDeath(this, 0);
|
||||||
|
mService = null;
|
||||||
|
mClassName = null;
|
||||||
|
int n = mProxies.beginBroadcast();
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
try {
|
||||||
|
mProxies.getBroadcastItem(i).onServiceDisconnected(className);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "Unable to disconnect from proxy", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mProxies.finishBroadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void binderDied() {
|
||||||
|
if (DBG) {
|
||||||
|
Log.w(TAG, "Profile service for profile: " + mClassName
|
||||||
|
+ " died.");
|
||||||
|
}
|
||||||
|
onServiceDisconnected(mClassName);
|
||||||
|
// Trigger rebind
|
||||||
|
Message msg = mHandler.obtainMessage(MESSAGE_BIND_PROFILE_SERVICE);
|
||||||
|
msg.obj = this;
|
||||||
|
mHandler.sendMessageDelayed(msg, TIMEOUT_BIND_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void sendBluetoothStateCallback(boolean isUp) {
|
private void sendBluetoothStateCallback(boolean isUp) {
|
||||||
int n = mStateChangeCallbacks.beginBroadcast();
|
int n = mStateChangeCallbacks.beginBroadcast();
|
||||||
if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
|
if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
|
||||||
@@ -803,6 +1003,28 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MESSAGE_ADD_PROXY_DELAYED:
|
||||||
|
{
|
||||||
|
ProfileServiceConnections psc = mProfileServices.get(
|
||||||
|
new Integer(msg.arg1));
|
||||||
|
if (psc == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
IBluetoothProfileServiceConnection proxy =
|
||||||
|
(IBluetoothProfileServiceConnection) msg.obj;
|
||||||
|
psc.addProxy(proxy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MESSAGE_BIND_PROFILE_SERVICE:
|
||||||
|
{
|
||||||
|
ProfileServiceConnections psc = (ProfileServiceConnections) msg.obj;
|
||||||
|
removeMessages(MESSAGE_BIND_PROFILE_SERVICE, msg.obj);
|
||||||
|
if (psc == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
psc.bindService();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
|
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
|
||||||
{
|
{
|
||||||
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
|
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
|
||||||
@@ -1005,6 +1227,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
|
bluetoothStateChangeHandler(mState, BluetoothAdapter.STATE_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unbindAllBluetoothProfileServices();
|
||||||
// disable
|
// disable
|
||||||
handleDisable();
|
handleDisable();
|
||||||
// Pbap service need receive STATE_TURNING_OFF intent to close
|
// Pbap service need receive STATE_TURNING_OFF intent to close
|
||||||
@@ -1129,16 +1352,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
int callingUser = UserHandle.getCallingUserId();
|
int callingUser = UserHandle.getCallingUserId();
|
||||||
int callingUid = Binder.getCallingUid();
|
int callingUid = Binder.getCallingUid();
|
||||||
long callingIdentity = Binder.clearCallingIdentity();
|
long callingIdentity = Binder.clearCallingIdentity();
|
||||||
|
UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||||
|
UserInfo ui = um.getProfileParent(callingUser);
|
||||||
|
int parentUser = (ui != null) ? ui.id : UserHandle.USER_NULL;
|
||||||
int callingAppId = UserHandle.getAppId(callingUid);
|
int callingAppId = UserHandle.getAppId(callingUid);
|
||||||
boolean valid = false;
|
boolean valid = false;
|
||||||
try {
|
try {
|
||||||
foregroundUser = ActivityManager.getCurrentUser();
|
foregroundUser = ActivityManager.getCurrentUser();
|
||||||
valid = (callingUser == foregroundUser) ||
|
valid = (callingUser == foregroundUser) ||
|
||||||
|
parentUser == foregroundUser ||
|
||||||
callingAppId == Process.NFC_UID ||
|
callingAppId == Process.NFC_UID ||
|
||||||
callingAppId == mSystemUiUid;
|
callingAppId == mSystemUiUid;
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
|
Log.d(TAG, "checkIfCallerIsForegroundUser: valid=" + valid
|
||||||
+ " callingUser=" + callingUser
|
+ " callingUser=" + callingUser
|
||||||
|
+ " parentUser=" + parentUser
|
||||||
+ " foregroundUser=" + foregroundUser);
|
+ " foregroundUser=" + foregroundUser);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1165,6 +1393,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
|||||||
} else {
|
} else {
|
||||||
//If Bluetooth is off, send service down event to proxy objects, and unbind
|
//If Bluetooth is off, send service down event to proxy objects, and unbind
|
||||||
if (!isUp && canUnbindBluetoothService()) {
|
if (!isUp && canUnbindBluetoothService()) {
|
||||||
|
unbindAllBluetoothProfileServices();
|
||||||
sendBluetoothServiceDownCallback();
|
sendBluetoothServiceDownCallback();
|
||||||
unbindAndFinish();
|
unbindAndFinish();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user