diff options
author | Dan Pasanen <invisiblek@cyanogenmod.org> | 2016-12-05 21:27:31 -0600 |
---|---|---|
committer | Dan Pasanen <invisiblek@cyanogenmod.org> | 2016-12-06 18:59:23 -0600 |
commit | 18e387abcb404900842e977f30e7829ee7835ced (patch) | |
tree | 36cdbdab7306e1fe1565555ba7562a4c598995d5 | |
parent | ef49a42ed6a5b28743fdc04db7cddac2a85eef0a (diff) | |
parent | 1c40f9218d815e4e67482fb8913fce6850e4fb1c (diff) | |
download | android_packages_apps_Bluetooth-18e387abcb404900842e977f30e7829ee7835ced.tar.gz android_packages_apps_Bluetooth-18e387abcb404900842e977f30e7829ee7835ced.tar.bz2 android_packages_apps_Bluetooth-18e387abcb404900842e977f30e7829ee7835ced.zip |
Merge tag 'android-7.1.1_r4' into cm-14.1
Android 7.1.1 release 4
Change-Id: Ia693c9be65c8662f565d79bb20f9788dae1b7d2d
9 files changed, 106 insertions, 31 deletions
diff --git a/jni/com_android_bluetooth_a2dp.cpp b/jni/com_android_bluetooth_a2dp.cpp index fd286ffcc..7be8f538a 100644 --- a/jni/com_android_bluetooth_a2dp.cpp +++ b/jni/com_android_bluetooth_a2dp.cpp @@ -252,7 +252,11 @@ static void initNative(JNIEnv *env, jobject object, jint maxA2dpConnections, env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = NULL; } - mCallbacksObj = env->NewGlobalRef(object); + + if ((mCallbacksObj = env->NewGlobalRef(object)) == NULL) { + ALOGE("Failed to allocate Global Ref for A2DP Callbacks"); + return; + } pthread_mutex_unlock(&mMutex); if ( (status = sBluetoothA2dpInterface->init(&sBluetoothA2dpCallbacks, @@ -269,7 +273,6 @@ static void initNative(JNIEnv *env, jobject object, jint maxA2dpConnections, pthread_mutex_unlock(&mMutex); return; } - } static void cleanupNative(JNIEnv *env, jobject object) { diff --git a/src/com/android/bluetooth/btservice/AdapterService.java b/src/com/android/bluetooth/btservice/AdapterService.java index 7299fbe00..aca94b2af 100644 --- a/src/com/android/bluetooth/btservice/AdapterService.java +++ b/src/com/android/bluetooth/btservice/AdapterService.java @@ -89,7 +89,8 @@ import android.os.SystemProperties; public class AdapterService extends Service { private static final String TAG = "BluetoothAdapterService"; - private static final boolean DBG = false; + private static final boolean DBG = true; + private static final boolean VERBOSE = false; private static final boolean TRACE_REF = false; private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; private static final int MIN_OFFLOADED_FILTERS = 10; @@ -2665,11 +2666,12 @@ public class AdapterService extends Service { } } - debugLog("energyInfoCallback() status = " + status + - "tx_time = " + tx_time + "rx_time = " + rx_time + - "idle_time = " + idle_time + "energy_used = " + energy_used + - "ctrl_state = " + ctrl_state + - "traffic = " + Arrays.toString(data)); + verboseLog("energyInfoCallback() status = " + status + + "tx_time = " + tx_time + "rx_time = " + rx_time + + "idle_time = " + idle_time + + "energy_used = " + energy_used + + "ctrl_state = " + ctrl_state + + "traffic = " + Arrays.toString(data)); } private int getIdleCurrentMa() { @@ -2715,8 +2717,8 @@ public class AdapterService extends Service { enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); if (args.length > 0) { - debugLog("dumpsys arguments, check for protobuf output: " + - TextUtils.join(" ", args)); + verboseLog("dumpsys arguments, check for protobuf output: " + + TextUtils.join(" ", args)); if (args[0].startsWith("--proto")) { if (args[0].equals("--proto-java-bin")) { dumpJava(fd); @@ -2764,6 +2766,7 @@ public class AdapterService extends Service { private void dumpJava(FileDescriptor fd) { BluetoothProto.BluetoothLog log = new BluetoothProto.BluetoothLog(); + log.setNumBondedDevices(getBondedDevices().length); for (ProfileService profile : mProfiles) { profile.dumpProto(log); @@ -2791,6 +2794,10 @@ public class AdapterService extends Service { if (DBG) Log.d(TAG, msg); } + private void verboseLog(String msg) { + if (VERBOSE) Log.v(TAG, msg); + } + private void errorLog(String msg) { Log.e(TAG, msg); } diff --git a/src/com/android/bluetooth/btservice/RemoteDevices.java b/src/com/android/bluetooth/btservice/RemoteDevices.java index 2545bd493..91df13bcb 100644 --- a/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -30,12 +30,15 @@ import com.android.bluetooth.Utils; import java.util.concurrent.atomic.AtomicInteger; import java.util.ArrayList; import java.util.HashMap; - +import java.util.LinkedList; +import java.util.Queue; final class RemoteDevices { private static final boolean DBG = false; private static final String TAG = "BluetoothRemoteDevices"; + // Maximum number of device properties to remember + private static final int MAX_DEVICE_QUEUE_SIZE = 200; private static BluetoothAdapter mAdapter; private static AdapterService mAdapterService; @@ -46,12 +49,14 @@ final class RemoteDevices { private static final int MESSAGE_UUID_INTENT = 1; private HashMap<String, DeviceProperties> mDevices; + private Queue<String> mDeviceQueue; RemoteDevices(AdapterService service) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mAdapterService = service; mSdpTracker = new ArrayList<BluetoothDevice>(); mDevices = new HashMap<String, DeviceProperties>(); + mDeviceQueue = new LinkedList<String>(); } @@ -61,6 +66,9 @@ final class RemoteDevices { if (mDevices != null) mDevices.clear(); + + if (mDeviceQueue != null) + mDeviceQueue.clear(); } @Override @@ -89,7 +97,20 @@ final class RemoteDevices { DeviceProperties prop = new DeviceProperties(); prop.mDevice = mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address)); prop.mAddress = address; - mDevices.put(Utils.getAddressStringFromByte(address), prop); + String key = Utils.getAddressStringFromByte(address); + DeviceProperties pv = mDevices.put(key, prop); + + if (pv == null) { + mDeviceQueue.offer(key); + if (mDeviceQueue.size() > MAX_DEVICE_QUEUE_SIZE) { + String deleteKey = mDeviceQueue.poll(); + for (BluetoothDevice device : mAdapterService.getBondedDevices()) { + if (device.getAddress().equals(deleteKey)) return prop; + } + debugLog("Removing device " + deleteKey + " from property map"); + mDevices.remove(deleteKey); + } + } return prop; } } @@ -243,20 +264,27 @@ final class RemoteDevices { BluetoothDevice bdDevice = getDevice(address); DeviceProperties device; if (bdDevice == null) { + debugLog("Added new device property"); device = addDeviceProperties(address); bdDevice = getDevice(address); } else { device = getDeviceProperties(bdDevice); } + if (types.length <= 0) { + errorLog("No properties to update"); + return; + } + for (int j = 0; j < types.length && device != null; j++) { type = types[j]; val = values[j]; - if(val.length <= 0) + if (val.length <= 0) errorLog("devicePropertyChangedCallback: bdDevice: " + bdDevice + ", value is empty for type: " + type); else { synchronized(mObject) { + debugLog("Property type: " + type); switch (type) { case AbstractionLayer.BT_PROPERTY_BDNAME: device.mName = new String(val); diff --git a/src/com/android/bluetooth/btservice/bluetooth.proto b/src/com/android/bluetooth/btservice/bluetooth.proto index 11311ea58..77ded7807 100644 --- a/src/com/android/bluetooth/btservice/bluetooth.proto +++ b/src/com/android/bluetooth/btservice/bluetooth.proto @@ -25,6 +25,9 @@ message BluetoothLog { // Scan event information. repeated ScanEvent scan_event = 4; + + // Number of bonded devices. + optional int32 num_bonded_devices = 5; } // The information about the device. diff --git a/src/com/android/bluetooth/gatt/ContextMap.java b/src/com/android/bluetooth/gatt/ContextMap.java index e3044d586..024572792 100644 --- a/src/com/android/bluetooth/gatt/ContextMap.java +++ b/src/com/android/bluetooth/gatt/ContextMap.java @@ -190,6 +190,7 @@ import com.android.bluetooth.btservice.BluetoothProto; while (i.hasNext()) { App entry = i.next(); if (entry.id == id) { + removeConnectionsByAppId(id); entry.unlinkToDeath(); entry.appScanStats.isRegistered = false; i.remove(); @@ -205,7 +206,7 @@ import com.android.bluetooth.btservice.BluetoothProto; void addConnection(int id, int connId, String address) { synchronized (mConnections) { App entry = getById(id); - if (entry != null){ + if (entry != null) { mConnections.add(new Connection(connId, address, id)); } } @@ -228,6 +229,19 @@ import com.android.bluetooth.btservice.BluetoothProto; } /** + * Remove all connections for a given application ID. + */ + void removeConnectionsByAppId(int appId) { + Iterator<Connection> i = mConnections.iterator(); + while (i.hasNext()) { + Connection connection = i.next(); + if (connection.appId == appId) { + i.remove(); + } + } + } + + /** * Get an application context by ID. */ App getById(int id) { diff --git a/src/com/android/bluetooth/gatt/GattService.java b/src/com/android/bluetooth/gatt/GattService.java index 0316b42b2..07cbbd56b 100644 --- a/src/com/android/bluetooth/gatt/GattService.java +++ b/src/com/android/bluetooth/gatt/GattService.java @@ -237,6 +237,7 @@ public class GattService extends ProfileService { boolean permissionCheck(int connId, int handle) { List<BluetoothGattService> db = gattClientDatabases.get(connId); + if (db == null) return true; for (BluetoothGattService service : db) { for (BluetoothGattCharacteristic characteristic: service.getCharacteristics()) { @@ -759,7 +760,15 @@ public class GattService extends ProfileService { void onSearchCompleted(int connId, int status) throws RemoteException { if (DBG) Log.d(TAG, "onSearchCompleted() - connId=" + connId+ ", status=" + status); // Gatt DB is ready! - gattClientGetGattDbNative(connId); + + // This callback was called from the jni_workqueue thread. If we make request to the stack + // on the same thread, it might cause deadlock. Schedule request on a new thread instead. + Thread t = new Thread(new Runnable() { + public void run() { + gattClientGetGattDbNative(connId); + } + }); + t.start(); } GattDbElement GetSampleGattDbElement() { diff --git a/src/com/android/bluetooth/gatt/ScanManager.java b/src/com/android/bluetooth/gatt/ScanManager.java index bb45bf7c9..621359724 100644 --- a/src/com/android/bluetooth/gatt/ScanManager.java +++ b/src/com/android/bluetooth/gatt/ScanManager.java @@ -40,11 +40,13 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.internal.app.IBatteryStats; import java.util.ArrayDeque; +import java.util.Collections; import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -95,8 +97,8 @@ public class ScanManager { private CountDownLatch mLatch; ScanManager(GattService service) { - mRegularScanClients = new HashSet<ScanClient>(); - mBatchClients = new HashSet<ScanClient>(); + mRegularScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); + mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mService = service; mScanNative = new ScanNative(); curUsedTrackableAdvertisements = 0; @@ -238,7 +240,7 @@ public class ScanManager { if (!mScanNative.isOpportunisticScanClient(client)) { mScanNative.configureRegularScanParams(); - if (!mScanNative.isFirstMatchScanClient(client)) { + if (!mScanNative.isExemptFromScanDowngrade(client)) { Message msg = mHandler.obtainMessage(MSG_SCAN_TIMEOUT); msg.obj = client; // Only one timeout message should exist at any time @@ -261,10 +263,6 @@ public class ScanManager { if (client == null) return; if (mRegularScanClients.contains(client)) { - // The ScanClient passed in just holds the clientIf. We retrieve the real client, - // which may have workSource set. - client = mScanNative.getRegularScanClient(client.clientIf); - if (client == null) return; mScanNative.stopRegularScan(client); @@ -278,7 +276,11 @@ public class ScanManager { // Update BatteryStats with this workload. try { - mBatteryStats.noteBleScanStopped(client.workSource); + // The ScanClient passed in just holds the clientIf. We retrieve the real client, + // which may have workSource set. + ScanClient workClient = mScanNative.getRegularScanClient(client.clientIf); + if (workClient != null) + mBatteryStats.noteBleScanStopped(workClient.workSource); } catch (RemoteException e) { /* ignore */ } @@ -534,6 +536,12 @@ public class ScanManager { } } + private boolean isExemptFromScanDowngrade(ScanClient client) { + return isOpportunisticScanClient(client) + || isFirstMatchScanClient(client) + || !shouldUseAllPassFilter(client); + } + private boolean isOpportunisticScanClient(ScanClient client) { return client.settings.getScanMode() == ScanSettings.SCAN_MODE_OPPORTUNISTIC; } @@ -683,8 +691,9 @@ public class ScanManager { void regularScanTimeout() { for (ScanClient client : mRegularScanClients) { - if (!isOpportunisticScanClient(client) && !isFirstMatchScanClient(client)) { - logd("clientIf set to scan opportunisticly: " + client.clientIf); + if (!isExemptFromScanDowngrade(client)) { + Log.w(TAG, "Moving scan client to opportunistic (clientIf " + + client.clientIf + ")"); setOpportunisticScanClient(client); client.stats.setScanTimeout(); } diff --git a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java index 8465274a8..c70408ccb 100755 --- a/src/com/android/bluetooth/map/BluetoothMapContentObserver.java +++ b/src/com/android/bluetooth/map/BluetoothMapContentObserver.java @@ -1194,7 +1194,7 @@ public class BluetoothMapContentObserver { private void initMsgList() throws RemoteException { if (V) Log.d(TAG, "initMsgList"); UserManager manager = UserManager.get(mContext); - if (manager == null || manager.isUserUnlocked()) return; + if (manager == null || !manager.isUserUnlocked()) return; if (mEnableSmsMms) { HashMap<Long, Msg> msgListSms = new HashMap<Long, Msg>(); diff --git a/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java b/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java index a35ae5659..fbf3778ed 100644 --- a/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java +++ b/src/com/android/bluetooth/pbap/BluetoothPbapReceiver.java @@ -42,22 +42,22 @@ public class BluetoothPbapReceiver extends BroadcastReceiver { private static final String TAG = "BluetoothPbapReceiver"; - private static final boolean V = Log.isLoggable(BluetoothPbapService.LOG_TAG, Log.VERBOSE); + private static final boolean D = BluetoothPbapService.DEBUG; @Override public void onReceive(Context context, Intent intent) { - if (V) Log.v(TAG, "PbapReceiver onReceive "); Intent in = new Intent(); in.putExtras(intent); in.setClass(context, BluetoothPbapService.class); String action = intent.getAction(); in.putExtra("action", action); - Log.i(TAG, "Enter - onReceive for intent:" + action); + if (D) Log.d(TAG, "PbapReceiver onReceive action = " + action); + boolean startService = true; if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); in.putExtra(BluetoothAdapter.EXTRA_STATE, state); - Log.i(TAG, "State :" + state); + if (D) Log.d(TAG, "state = " + state); if ((state == BluetoothAdapter.STATE_TURNING_ON) || (state == BluetoothAdapter.STATE_OFF)) { //FIX: We turn on PBAP after BluetoothAdapter.STATE_ON, @@ -68,11 +68,13 @@ public class BluetoothPbapReceiver extends BroadcastReceiver { // Don't forward intent unless device has bluetooth and bluetooth is enabled. BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter == null || !adapter.isEnabled()) { + if (D) Log.d(TAG, "BluetoothAdapter is not enabled (" + + adapter + "). Would not start service."); startService = false; } } if (startService) { - if (V) Log.v(TAG, "Calling start service!!!! with action = " + in.getAction()); + if (D) Log.d(TAG, "Calling start service with action = " + in.getAction()); context.startService(in); } Log.i(TAG, "Exit - onReceive for intent:" + action); |