Merge changes from topic "GROUP_CLIENT" into r-keystone-qcom-dev
* changes:
DeviceGroup: Frameworks changes (for dual mode devices).
DeviceGroup: Framework changes for Group Device operations.
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index a54d077..a5dee0e 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -2355,6 +2355,48 @@
public BluetoothGatt connectGatt(Context context, boolean autoConnect,
BluetoothGattCallback callback, int transport,
boolean opportunistic, int phy, Handler handler) {
+ return connectGatt(context, autoConnect, callback, transport, opportunistic,
+ phy, handler, false);
+ }
+
+ /**
+ * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as any further GATT client operations.
+ * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+ * GATT client operations.
+ *
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param autoConnect Whether to directly connect to the remote device (false) or to
+ * automatically connect as soon as the remote device becomes available (true).
+ * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
+ * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
+ * BluetoothDevice#TRANSPORT_LE}
+ * @param opportunistic Whether this GATT client is opportunistic. An opportunistic GATT client
+ * does not hold a GATT connection. It automatically disconnects when no other GATT connections
+ * are active for the remote device.
+ * @param phy preferred PHY for connections to remote LE device. Bitwise OR of any of {@link
+ * BluetoothDevice#PHY_LE_1M_MASK}, {@link BluetoothDevice#PHY_LE_2M_MASK}, an d{@link
+ * BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect if {@code autoConnect}
+ * is set to true.
+ * @param handler The handler to use for the callback. If {@code null}, callbacks will happen on
+ * an un-specified background thread.
+ * @param eattSupport specifies whether client app needs EATT channel for client operations.
+ * If both local and remote devices support EATT and local app asks for EATT, GATT client
+ * operations will be performed using EATT channel.
+ * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
+ * client operations will be performed using unenhanced ATT channel.
+ *
+ * @return A BluetoothGatt instance. You can use BluetoothGatt to conduct GATT client
+ * operations.
+ *
+ * @throws NullPointerException if callback is null
+ *
+ * @hide
+ */
+ public BluetoothGatt connectGatt(Context context, boolean autoConnect,
+ BluetoothGattCallback callback, int transport, boolean opportunistic,
+ int phy, Handler handler, boolean eattSupport) {
if (callback == null) {
throw new NullPointerException("callback is null");
}
@@ -2370,7 +2412,7 @@
return null;
}
BluetoothGatt gatt = new BluetoothGatt(iGatt, this, transport, opportunistic, phy);
- gatt.connect(autoConnect, callback, handler);
+ gatt.connect(autoConnect, callback, handler, eattSupport);
return gatt;
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index f877f04..6fc1492 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -799,6 +799,28 @@
* error
*/
private boolean registerApp(BluetoothGattCallback callback, Handler handler) {
+ return registerApp(callback, handler, false);
+ }
+
+ /**
+ * Register an application callback to start using GATT.
+ *
+ * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
+ * is used to notify success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param eattSupport specifies whether client app needs EATT channel for client operations.
+ * If both local and remote devices support EATT and local app asks for EATT, GATT client
+ * operations will be performed using EATT channel.
+ * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
+ * client operations will be performed using unenhanced ATT channel.
+ * @return If true, the callback will be called to notify success or failure, false on immediate
+ * error
+ * @hide
+ */
+ private boolean registerApp(BluetoothGattCallback callback, Handler handler, boolean eattSupport) {
if (DBG) Log.d(TAG, "registerApp()");
if (mService == null) return false;
@@ -808,7 +830,7 @@
if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
try {
- mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
+ mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback, eattSupport);
} catch (RemoteException e) {
Log.e(TAG, "", e);
return false;
@@ -859,9 +881,45 @@
@UnsupportedAppUsage
/*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
Handler handler) {
+ return connect(autoConnect, callback, handler, false);
+ }
+
+ /**
+ * Initiate a connection to a Bluetooth GATT capable device.
+ *
+ * <p>The connection may not be established right away, but will be
+ * completed when the remote device is available. A
+ * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
+ * invoked when the connection state changes as a result of this function.
+ *
+ * <p>The autoConnect parameter determines whether to actively connect to
+ * the remote device, or rather passively scan and finalize the connection
+ * when the remote device is in range/available. Generally, the first ever
+ * connection to a device should be direct (autoConnect set to false) and
+ * subsequent connections to known devices should be invoked with the
+ * autoConnect parameter set to true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device Remote device to connect to
+ * @param autoConnect Whether to directly connect to the remote device (false) or to
+ * automatically connect as soon as the remote device becomes available (true).
+ * @param eattSupport specifies whether client app needs EATT channel for client operations.
+ * If both local and remote devices support EATT and local app asks for EATT, GATT client
+ * operations will be performed using EATT channel.
+ * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
+ * client operations will be performed using unenhanced ATT channel.
+ * @return true, if the connection attempt was initiated successfully
+ *
+ * @hide
+ */
+ @UnsupportedAppUsage
+ /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback,
+ Handler handler, boolean eattSupport) {
if (DBG) {
Log.d(TAG,
- "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
+ "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect
+ + ", eattSupport: " + eattSupport);
}
synchronized (mStateLock) {
if (mConnState != CONN_STATE_IDLE) {
@@ -872,7 +930,7 @@
mAutoConnect = autoConnect;
- if (!registerApp(callback, handler)) {
+ if (!registerApp(callback, handler, eattSupport)) {
synchronized (mStateLock) {
mConnState = CONN_STATE_IDLE;
}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 13b1b4f..00daa75 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -443,6 +443,24 @@
* error
*/
/*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
+ return registerCallback(callback, false);
+ }
+
+ /**
+ * Register an application callback to start using GattServer.
+ *
+ * <p>This is an asynchronous call. The callback is used to notify
+ * success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param eattSupport whether eattSupport is needed for Gatt server
+ * @return true, the callback will be called to notify success or failure, false on immediate
+ * error
+ * @hide
+ */
+ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback, boolean eattSupport) {
if (DBG) Log.d(TAG, "registerCallback()");
if (mService == null) {
Log.e(TAG, "GATT service not available");
@@ -459,7 +477,7 @@
mCallback = callback;
try {
- mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
+ mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback, eattSupport);
} catch (RemoteException e) {
Log.e(TAG, "", e);
mCallback = null;
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index 3b4fe0a..7f51664 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -233,6 +233,31 @@
*/
public BluetoothGattServer openGattServer(Context context,
BluetoothGattServerCallback callback, int transport) {
+ return (openGattServer(context, callback, transport, false));
+ }
+
+ /**
+ * Open a GATT Server
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as the results of any other GATT server operations.
+ * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
+ * to conduct GATT server operations.
+ *
+ * @param context App context
+ * @param callback GATT server callback handler that will receive asynchronous callbacks.
+ * @param transport preferred transport for GATT connections to remote dual-mode devices {@link
+ * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link
+ * BluetoothDevice#TRANSPORT_LE}
+ * @param eattSupport specifies whether server app needs EATT channel for server operations.
+ * If both local and remote devices support EATT, local app asks for EATT using this API and
+ * calls server connect, GATT server operations will be performed using EATT channel.
+ * If either local or remote device doesn't support EATT but local App asks for EATT, GATT
+ * server operations will be performed using unenhanced ATT channel.
+ * @return BluetoothGattServer instance
+ * @hide
+ */
+ public BluetoothGattServer openGattServer(Context context,
+ BluetoothGattServerCallback callback, int transport, boolean eattSupport) {
if (context == null || callback == null) {
throw new IllegalArgumentException("null parameter: " + context + " " + callback);
}
@@ -248,7 +273,7 @@
return null;
}
BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport);
- Boolean regStatus = mGattServer.registerCallback(callback);
+ Boolean regStatus = mGattServer.registerCallback(callback, eattSupport);
return regStatus ? mGattServer : null;
} catch (RemoteException e) {
Log.e(TAG, "", e);
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
index 14ac911..b3fd484 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingCallback.java
@@ -78,4 +78,13 @@
*/
public void onSyncLost(int syncHandle) {
}
+
+ /**
+ * Callback when periodic sync transfered.
+ *
+ * @param device
+ * @param status
+ */
+ public void onSyncTransfered(BluetoothDevice device, int status) {
+ }
}
diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
index 0f1a8e9..4930473 100644
--- a/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
+++ b/core/java/android/bluetooth/le/PeriodicAdvertisingManager.java
@@ -196,6 +196,62 @@
}
}
+ public void transferSync(BluetoothDevice bda, int service_data, int sync_handle) {
+ IBluetoothGatt gatt;
+ try {
+ gatt = mBluetoothManager.getBluetoothGatt();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+ PeriodicAdvertisingCallback callback = null;
+ for (PeriodicAdvertisingCallback cb : mCallbackWrappers.keySet()) {
+ callback = cb;
+ }
+ if (callback != null) {
+ callback.onSyncTransfered(bda,
+ PeriodicAdvertisingCallback.SYNC_NO_RESOURCES);
+ }
+ return;
+ }
+ try {
+ gatt.transferSync(bda, service_data , sync_handle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register sync - ", e);
+ return;
+ }
+ }
+
+ public void transferSetInfo(BluetoothDevice bda, int service_data,
+ int adv_handle, PeriodicAdvertisingCallback callback) {
+ transferSetInfo(bda, service_data, adv_handle, callback, null);
+ }
+
+ public void transferSetInfo (BluetoothDevice bda, int service_data,
+ int adv_handle, PeriodicAdvertisingCallback callback, Handler handler) {
+ if (callback == null) {
+ throw new IllegalArgumentException("callback can't be null");
+ }
+ IBluetoothGatt gatt;
+ try {
+ gatt = mBluetoothManager.getBluetoothGatt();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
+ return;
+ }
+ if (handler == null) {
+ handler = new Handler(Looper.getMainLooper());
+ }
+ IPeriodicAdvertisingCallback wrapper = wrap(callback, handler);
+ if (wrapper == null) {
+ throw new IllegalArgumentException("callback was not properly registered");
+ }
+ try {
+ gatt.transferSetInfo(bda, service_data , adv_handle, wrapper);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register sync - ", e);
+ return;
+ }
+
+ }
private IPeriodicAdvertisingCallback wrap(PeriodicAdvertisingCallback callback,
Handler handler) {
return new IPeriodicAdvertisingCallback.Stub() {
@@ -239,6 +295,18 @@
}
});
}
+
+ public void onSyncTransfered(BluetoothDevice device, int status) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onSyncTransfered(device, status);
+ // App can still unregister the sync until notified it's lost.
+ // Remove callback after app was notifed.
+ //mCallbackWrappers.remove(callback);
+ }
+ });
+ }
};
}
}
diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java
index 108141c..f7276c3 100644
--- a/core/java/android/bluetooth/le/ScanFilter.java
+++ b/core/java/android/bluetooth/le/ScanFilter.java
@@ -87,6 +87,10 @@
private final int mTDSFlagsMask;
private final byte[] mWifiNANHash;
+ private final boolean mGroupBasedFiltering;
+
+ private static final int GROUP_DATA_LEN = 6;
+
/** @hide */
public static final ScanFilter EMPTY = new ScanFilter.Builder().build();
@@ -96,7 +100,8 @@
ParcelUuid solicitationUuidMask, ParcelUuid serviceDataUuid,
byte[] serviceData, byte[] serviceDataMask,
int manufacturerId, byte[] manufacturerData, byte[] manufacturerDataMask,
- int orgId, int TDSFlags, int TDSFlagsMask, byte[] wifiNANHash) {
+ int orgId, int TDSFlags, int TDSFlagsMask, byte[] wifiNANHash,
+ boolean groupBasedFiltering) {
mDeviceName = name;
mServiceUuid = uuid;
mServiceUuidMask = uuidMask;
@@ -113,6 +118,7 @@
mTDSFlags = TDSFlags;
mTDSFlagsMask = TDSFlagsMask;
mWifiNANHash = wifiNANHash;
+ mGroupBasedFiltering = groupBasedFiltering;
}
@Override
@@ -184,6 +190,7 @@
dest.writeByteArray(mWifiNANHash);
}
}
+ dest.writeBoolean(mGroupBasedFiltering);
}
/**
@@ -277,6 +284,8 @@
}
}
+ boolean groupBasedFiltering = in.readBoolean();
+ builder.setGroupBasedFiltering(groupBasedFiltering);
return builder.build();
}
};
@@ -387,6 +396,14 @@
}
/**
+ * @hide
+ * Returns true, if Group AD Type based filtering is enabled. Otherwise, false.
+ */
+ public boolean getGroupFilteringValue() {
+ return mGroupBasedFiltering;
+ }
+
+ /**
* Check if the scan filter matches a {@code scanResult}. A scan result is considered as a match
* if it matches all the field filters.
*/
@@ -455,6 +472,13 @@
}
}
+ // Group AD Type filter match
+ if (mGroupBasedFiltering) {
+ if (scanRecord.getGroupIdentifierData().length != GROUP_DATA_LEN) {
+ return false;
+ }
+ }
+
// All filters match.
return true;
}
@@ -552,7 +576,8 @@
+ ", mManufacturerDataMask=" + Arrays.toString(mManufacturerDataMask)
+ ", mOrganizationId=" + mOrgId + ", mTDSFlags=" + mTDSFlags
+ ", mTDSFlagsMask=" + mTDSFlagsMask
- + ", mWifiNANHash=" + Arrays.toString(mWifiNANHash) +"]";
+ + ", mWifiNANHash=" + Arrays.toString(mWifiNANHash) +"]"
+ + ", mGroupBasedFiltering=" + mGroupBasedFiltering;
}
@Override
@@ -565,7 +590,8 @@
Arrays.hashCode(mServiceDataMask),
mServiceUuid, mServiceUuidMask,
mServiceSolicitationUuid, mServiceSolicitationUuidMask,
- mOrgId, mTDSFlags, mTDSFlagsMask, Arrays.hashCode(mWifiNANHash));
+ mOrgId, mTDSFlags, mTDSFlagsMask, Arrays.hashCode(mWifiNANHash),
+ mGroupBasedFiltering);
}
@Override
@@ -593,7 +619,8 @@
&& mOrgId == other.mOrgId
&& mTDSFlags == other.mTDSFlags
&& mTDSFlagsMask == other.mTDSFlagsMask
- && Objects.deepEquals(mWifiNANHash, other.mWifiNANHash);
+ && Objects.deepEquals(mWifiNANHash, other.mWifiNANHash)
+ && mGroupBasedFiltering == other.mGroupBasedFiltering;
}
/**
@@ -632,6 +659,8 @@
private int mTDSFlagsMask = -1;
private byte[] mWifiNANHash;
+ private boolean mGroupBasedFiltering;
+
/**
* Set filter on device name.
*/
@@ -837,6 +866,17 @@
mWifiNANHash = wifiNANHash;
return this;
}
+
+ /**
+ * @hide
+ * Enable filter on Group AD Type.
+ */
+ public @NonNull Builder setGroupBasedFiltering(
+ boolean enable) {
+ mGroupBasedFiltering = enable;
+ return this;
+ }
+
/**
* Build {@link ScanFilter}.
*
@@ -848,7 +888,8 @@
mServiceSolicitationUuidMask,
mServiceDataUuid, mServiceData, mServiceDataMask,
mManufacturerId, mManufacturerData, mManufacturerDataMask,
- mOrgId, mTDSFlags, mTDSFlagsMask, mWifiNANHash);
+ mOrgId, mTDSFlags, mTDSFlagsMask, mWifiNANHash,
+ mGroupBasedFiltering);
}
}
}
diff --git a/core/java/android/bluetooth/le/ScanRecord.java b/core/java/android/bluetooth/le/ScanRecord.java
index abcb381..9509c53 100644
--- a/core/java/android/bluetooth/le/ScanRecord.java
+++ b/core/java/android/bluetooth/le/ScanRecord.java
@@ -57,6 +57,10 @@
private static final int DATA_TYPE_SERVICE_SOLICITATION_UUIDS_128_BIT = 0x15;
private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
private static final int DATA_TYPE_TRANSPORT_DISCOVERY_DATA = 0x26;
+ /**
+ * @hide
+ */
+ public static int DATA_TYPE_GROUP_AD_TYPE = 0x00;
// Flags of the advertising data.
private final int mAdvertiseFlags;
@@ -82,6 +86,9 @@
// Transport Discovery data.
private final byte[] mTDSData;
+ // Group Identifier Data
+ private final byte[] mGroupIdentifierData;
+
/**
* Returns the advertising flags indicating the discoverable mode and capability of the device.
* Returns -1 if the flag field is not set.
@@ -174,6 +181,14 @@
}
/**
+ * @hide
+ * Returns Group Identifier data
+ */
+ public byte[] getGroupIdentifierData() {
+ return mGroupIdentifierData;
+ }
+
+ /**
* Returns raw bytes of scan record.
*/
public byte[] getBytes() {
@@ -185,7 +200,7 @@
SparseArray<byte[]> manufacturerData,
Map<ParcelUuid, byte[]> serviceData,
int advertiseFlags, int txPowerLevel,
- String localName, byte[] tdsData, byte[] bytes) {
+ String localName, byte[] tdsData, byte[] groupIdentifierData, byte[] bytes) {
mServiceSolicitationUuids = serviceSolicitationUuids;
mServiceUuids = serviceUuids;
mManufacturerSpecificData = manufacturerData;
@@ -194,6 +209,7 @@
mAdvertiseFlags = advertiseFlags;
mTxPowerLevel = txPowerLevel;
mTDSData = tdsData;
+ mGroupIdentifierData = groupIdentifierData;
mBytes = bytes;
}
@@ -225,6 +241,7 @@
Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>();
byte[] tdsData = null;
+ byte[] groupIdentifierData = null;
try {
while (currentPos < scanRecord.length) {
@@ -306,8 +323,12 @@
case DATA_TYPE_TRANSPORT_DISCOVERY_DATA:
tdsData = extractBytes(scanRecord, currentPos, dataLength);
break;
+
default:
- // Just ignore, we don't handle such data type.
+ if (fieldType == DATA_TYPE_GROUP_AD_TYPE) {
+ Log.d(TAG, "Parsing Group Identifier data");
+ groupIdentifierData = extractBytes(scanRecord, currentPos, dataLength);
+ }
break;
}
currentPos += dataLength;
@@ -317,12 +338,14 @@
serviceUuids = null;
}
return new ScanRecord(serviceUuids, serviceSolicitationUuids, manufacturerData,
- serviceData, advertiseFlag, txPowerLevel, localName, tdsData, scanRecord);
+ serviceData, advertiseFlag, txPowerLevel, localName, tdsData,
+ groupIdentifierData, scanRecord);
} catch (Exception e) {
Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
// As the record is invalid, ignore all the parsed results for this packet
// and return an empty record with raw scanRecord bytes in results
- return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, null, scanRecord);
+ return new ScanRecord(null, null, null, null, -1, Integer.MIN_VALUE, null, null,
+ null, scanRecord);
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
old mode 100644
new mode 100755
index faeda81..2d0e268
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -434,7 +434,7 @@
}
}
for (int i = 0; i < changedSubscriptions.size(); i++) {
- SimData data = mSimDatas.get(changedSubscriptions.get(i).getSubscriptionId());
+ SimData data = mSimDatas.get(changedSubscriptions.get(i).getSimSlotIndex());
for (int j = 0; j < mCallbacks.size(); j++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(j).get();
if (cb != null) {
@@ -2386,7 +2386,13 @@
// Even though the subscription is not valid anymore, we need to notify that the
// SIM card was removed so we can update the UI.
becameAbsent = true;
- mSimDatas.clear();
+ for (SimData data : mSimDatas.values()) {
+ // Set the SIM state of all SimData associated with that slot to ABSENT se we
+ // do not move back into PIN/PUK locked and not detect the change below.
+ if (data.slotId == slotId) {
+ data.simState = TelephonyManager.SIM_STATE_ABSENT;
+ }
+ }
} else if (state == TelephonyManager.SIM_STATE_CARD_IO_ERROR) {
updateTelephonyCapable(true);
} else {
@@ -2394,11 +2400,11 @@
}
}
- SimData data = mSimDatas.get(subId);
+ SimData data = mSimDatas.get(slotId);
final boolean changed;
if (data == null) {
data = new SimData(state, slotId, subId);
- mSimDatas.put(subId, data);
+ mSimDatas.put(slotId, data);
changed = true; // no data yet; force update
} else {
changed = (data.simState != state || data.subId != subId || data.slotId != slotId);
@@ -2741,18 +2747,20 @@
}
public int getSimState(int subId) {
- if (mSimDatas.containsKey(subId)) {
- return mSimDatas.get(subId).simState;
+ int slotId = SubscriptionManager.getSlotIndex(subId);
+ if (mSimDatas.containsKey(slotId)) {
+ return mSimDatas.get(slotId).simState;
} else {
return TelephonyManager.SIM_STATE_UNKNOWN;
}
}
private int getSlotId(int subId) {
- if (!mSimDatas.containsKey(subId)) {
- refreshSimState(subId, SubscriptionManager.getSlotIndex(subId));
+ int slotId = SubscriptionManager.getSlotIndex(subId);
+ if (!mSimDatas.containsKey(slotId)) {
+ refreshSimState(subId, slotId);
}
- return mSimDatas.get(subId).slotId;
+ return mSimDatas.get(slotId).slotId;
}
private final TaskStackChangeListener
@@ -2811,11 +2819,11 @@
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
int state = (tele != null) ?
tele.getSimState(slotId) : TelephonyManager.SIM_STATE_UNKNOWN;
- SimData data = mSimDatas.get(subId);
+ SimData data = mSimDatas.get(slotId);
final boolean changed;
if (data == null) {
data = new SimData(state, slotId, subId);
- mSimDatas.put(subId, data);
+ mSimDatas.put(slotId, data);
changed = true; // no data yet; force update
} else {
changed = (data.simState != state) || (data.slotId != slotId);
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index dd001ba..dd74909 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -92,6 +92,8 @@
void allowAutojoinGlobal(boolean choice);
+ void allowConnectOnPartialScanResults(boolean enable);
+
void allowAutojoin(int netId, boolean choice);
void allowAutojoinPasspoint(String fqdn, boolean enableAutoJoin);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 15415f0..3346e10 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1052,6 +1052,15 @@
public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
/**
+ * An access point partial scan has completed, and results are available.
+ * Call {@link #getScanResults()} to obtain the results.
+ * The broadcast intent may contain an extra field with the key {@link #EXTRA_RESULTS_UPDATED}
+ * and a {@code boolean} value indicating if the scan was successful.
+ * @hide
+ */
+ public static final String PARTIAL_SCAN_RESULTS_AVAILABLE_ACTION = "com.qualcomm.qti.net.wifi.PARTIAL_SCAN_RESULTS";
+
+ /**
* Lookup key for a {@code boolean} extra in intent {@link #SCAN_RESULTS_AVAILABLE_ACTION}
* representing if the scan was successful or not.
* Scans may fail for multiple reasons, these may include:
@@ -4578,6 +4587,19 @@
}
}
+ /**
+ * Enable/disable quick connect on partial scan results.
+ *
+ * @param enable true to not allow quick connect, false to allow quick connect
+ * @hide
+ */
+ public void allowConnectOnPartialScanResults(boolean enable) {
+ try {
+ mService.allowConnectOnPartialScanResults(enable);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
/**
* Sets the user choice for allowing auto-join to a network.
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 94771ac..4d61351 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -154,6 +154,16 @@
/** An outstanding request with the same listener hasn't finished yet. */
public static final int REASON_DUPLICATE_REQEUST = -5;
+ /** Partial scan results msg arg
+ * @hide
+ */
+ public static final int ON_PARTIAL_SCAN_RESULTS = 1;
+
+ /** Complete scan results msg arg
+ * @hide
+ */
+ public static final int ON_COMPLETE_SCAN_RESULTS = 0;
+
/** @hide */
public static final String GET_AVAILABLE_CHANNELS_EXTRA = "Channels";
@@ -865,6 +875,11 @@
*/
public void onResults(ScanData[] results);
/**
+ * reports partial results retrieved from single shot scans
+ * @hide
+ */
+ default void onPartialScanResults(ScanData[] results) {}
+ /**
* reports full scan result for each access point found in scan
*/
public void onFullResult(ScanResult fullScanResult);
@@ -1648,7 +1663,11 @@
ScanListener scanListener = (ScanListener) listener;
ParcelableScanData parcelableScanData = (ParcelableScanData) msg.obj;
Binder.clearCallingIdentity();
- executor.execute(() -> scanListener.onResults(parcelableScanData.getResults()));
+ if (msg.arg1 == ON_PARTIAL_SCAN_RESULTS) {
+ executor.execute(() -> scanListener.onPartialScanResults(parcelableScanData.getResults()));
+ } else {
+ executor.execute(() -> scanListener.onResults(parcelableScanData.getResults()));
+ }
} break;
case CMD_FULL_SCAN_RESULT: {
ScanResult result = (ScanResult) msg.obj;