From 39225c57893f1ce1d18d6d6d4374110387dd8024 Mon Sep 17 00:00:00 2001 From: Etienne Ruffieux Date: Thu, 30 Sep 2021 12:14:47 +0000 Subject: [PATCH 01/12] Refactor Bluetooth scan mode APIs Removed setScanMode(int, long), setScanMode(int mode) is now a SystemApi. Made getDiscoverableTimeout a public API. setDiscoverableTimeout is now SystemApi. Discoverable timeout is now in seconds everywhere. Tag: #feature Bug: 195150096 Test: Manual Change-Id: Iee0a80b382f601a81f14afd7224637b88fbdf7ce --- .../BluetoothDiscoverableEnabler.java | 7 ++-- .../bluetooth/RequestPermissionActivity.java | 39 +++++++++++-------- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java index 0a9003d4e7d..55c76e3c1a7 100755 --- a/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java +++ b/src/com/android/settings/bluetooth/BluetoothDiscoverableEnabler.java @@ -31,6 +31,8 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver; +import java.time.Duration; + /** * BluetoothDiscoverableEnabler is a helper to manage the "Discoverable" * checkbox. It sets/unsets discoverability and keeps track of how much time @@ -136,9 +138,8 @@ final class BluetoothDiscoverableEnabler implements Preference.OnPreferenceClick int timeout = getDiscoverableTimeout(); long endTimestamp = System.currentTimeMillis() + timeout * 1000L; LocalBluetoothPreferences.persistDiscoverableEndTimestamp(mContext, endTimestamp); - - mBluetoothAdapter - .setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, timeout); + mBluetoothAdapter.setDiscoverableTimeout(Duration.ofSeconds(timeout)); + mBluetoothAdapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE); updateCountdownSummary(); Log.d(TAG, "setEnabled(): enabled = " + enable + "timeout = " + timeout); diff --git a/src/com/android/settings/bluetooth/RequestPermissionActivity.java b/src/com/android/settings/bluetooth/RequestPermissionActivity.java index 362849d850d..588bc7392bf 100644 --- a/src/com/android/settings/bluetooth/RequestPermissionActivity.java +++ b/src/com/android/settings/bluetooth/RequestPermissionActivity.java @@ -16,10 +16,13 @@ package com.android.settings.bluetooth; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; + import android.annotation.NonNull; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothStatusCodes; import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; @@ -39,7 +42,7 @@ import androidx.appcompat.app.AlertDialog; import com.android.settings.R; import com.android.settingslib.bluetooth.BluetoothDiscoverableTimeoutReceiver; -import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import java.time.Duration; /** * RequestPermissionActivity asks the user whether to enable discovery. This is @@ -261,22 +264,26 @@ public class RequestPermissionActivity extends Activity implements if (mRequest == REQUEST_ENABLE || mRequest == REQUEST_DISABLE) { // BT toggled. Done returnCode = RESULT_OK; - } else if (mBluetoothAdapter.setScanMode( - BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, mTimeout)) { - // If already in discoverable mode, this will extend the timeout. - long endTime = System.currentTimeMillis() + (long) mTimeout * 1000; - LocalBluetoothPreferences.persistDiscoverableEndTimestamp( - this, endTime); - if (0 < mTimeout) { - BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(this, endTime); - } - returnCode = mTimeout; - // Activity.RESULT_FIRST_USER should be 1 - if (returnCode < RESULT_FIRST_USER) { - returnCode = RESULT_FIRST_USER; - } } else { - returnCode = RESULT_CANCELED; + mBluetoothAdapter.setDiscoverableTimeout(Duration.ofSeconds(mTimeout)); + if (mBluetoothAdapter.setScanMode( + BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) + == BluetoothStatusCodes.SUCCESS) { + // If already in discoverable mode, this will extend the timeout. + long endTime = System.currentTimeMillis() + (long) mTimeout * 1000; + LocalBluetoothPreferences.persistDiscoverableEndTimestamp( + this, endTime); + if (0 < mTimeout) { + BluetoothDiscoverableTimeoutReceiver.setDiscoverableAlarm(this, endTime); + } + returnCode = mTimeout; + // Activity.RESULT_FIRST_USER should be 1 + if (returnCode < RESULT_FIRST_USER) { + returnCode = RESULT_FIRST_USER; + } + } else { + returnCode = RESULT_CANCELED; + } } if (mDialog != null) { From 8ca17560e50c419ad9121530b41d52e448be20b9 Mon Sep 17 00:00:00 2001 From: Adam Bookatz Date: Tue, 23 Nov 2021 14:55:28 -0800 Subject: [PATCH 02/12] Use UM.canAddMoreUsers and UM.isUserTypeEnabled Settings shouldn't allow creating users if the type is diabled, and it shouldn't allow creating more of a particular user type if no more can be created (even if more can be created of other user types). Previously, Settings didn't take into account the user type when querying whether more users could be created. Bug: 192577100 Test: com.android.settings.users.UserSettingsTest Change-Id: I065478fd14779f528be4edce8ae215391a752ef4 --- .../android/settings/users/UserCapabilities.java | 14 ++++++++++---- src/com/android/settings/users/UserSettings.java | 6 +++++- .../android/settings/users/UserSettingsTest.java | 14 +++++++++----- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/users/UserCapabilities.java b/src/com/android/settings/users/UserCapabilities.java index 459a880964f..7af6c645f66 100644 --- a/src/com/android/settings/users/UserCapabilities.java +++ b/src/com/android/settings/users/UserCapabilities.java @@ -58,7 +58,9 @@ public class UserCapabilities { DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService( Context.DEVICE_POLICY_SERVICE); // No restricted profiles for tablets with a device owner, or phones. - if (dpm.isDeviceManaged() || Utils.isVoiceCapable(context)) { + if (dpm.isDeviceManaged() + || Utils.isVoiceCapable(context) + || !userManager.isUserTypeEnabled(UserManager.USER_TYPE_FULL_RESTRICTED)) { caps.mCanAddRestrictedProfile = false; } caps.updateAddUserCapabilities(context); @@ -76,15 +78,19 @@ public class UserCapabilities { mDisallowAddUser = (mEnforcedAdmin != null || hasBaseUserRestriction); mUserSwitcherEnabled = userManager.isUserSwitcherEnabled(); mCanAddUser = true; - if (!mIsAdmin || UserManager.getMaxSupportedUsers() < 2 + if (!mIsAdmin + || UserManager.getMaxSupportedUsers() < 2 || !UserManager.supportsMultipleUsers() - || mDisallowAddUser) { + || mDisallowAddUser + || (!userManager.isUserTypeEnabled(UserManager.USER_TYPE_FULL_SECONDARY) + && !mCanAddRestrictedProfile)) { mCanAddUser = false; } final boolean canAddUsersWhenLocked = mIsAdmin || Settings.Global.getInt( context.getContentResolver(), Settings.Global.ADD_USERS_WHEN_LOCKED, 0) == 1; - mCanAddGuest = !mIsGuest && !mDisallowAddUser && canAddUsersWhenLocked; + mCanAddGuest = !mIsGuest && !mDisallowAddUser && canAddUsersWhenLocked + && userManager.isUserTypeEnabled(UserManager.USER_TYPE_FULL_GUEST); mDisallowSwitchUser = userManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH); } diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java index 23cdaf987f7..de547c7dddb 100644 --- a/src/com/android/settings/users/UserSettings.java +++ b/src/com/android/settings/users/UserSettings.java @@ -1073,6 +1073,7 @@ public class UserSettings extends SettingsPreferenceFragment private void updateAddGuest(Context context, boolean isGuestAlreadyCreated) { if (!isGuestAlreadyCreated && mUserCaps.mCanAddGuest + && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_GUEST) && WizardManagerHelper.isDeviceProvisioned(context) && mUserCaps.mUserSwitcherEnabled) { mAddGuest.setVisible(true); @@ -1097,7 +1098,10 @@ public class UserSettings extends SettingsPreferenceFragment && mUserCaps.mUserSwitcherEnabled) { mAddUser.setVisible(true); mAddUser.setSelectable(true); - final boolean canAddMoreUsers = mUserManager.canAddMoreUsers(); + final boolean canAddMoreUsers = + mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY) + || (mUserCaps.mCanAddRestrictedProfile + && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_RESTRICTED)); mAddUser.setEnabled(canAddMoreUsers && !mAddingUser && canSwitchUserNow()); if (!canAddMoreUsers) { mAddUser.setSummary( diff --git a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java index 299e054c6fc..9d357977a6c 100644 --- a/tests/robotests/src/com/android/settings/users/UserSettingsTest.java +++ b/tests/robotests/src/com/android/settings/users/UserSettingsTest.java @@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.notNull; import static org.mockito.Mockito.doReturn; @@ -258,7 +259,8 @@ public class UserSettingsTest { @Test public void updateUserList_canAddUserAndSwitchUser_shouldShowAddUser() { mUserCapabilities.mCanAddUser = true; - doReturn(true).when(mUserManager).canAddMoreUsers(); + doReturn(true) + .when(mUserManager).canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_SECONDARY)); doReturn(true).when(mAddUserPreference).isEnabled(); doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability(); @@ -274,7 +276,8 @@ public class UserSettingsTest { @Test public void updateUserList_canAddGuestAndSwitchUser_shouldShowAddGuest() { mUserCapabilities.mCanAddGuest = true; - doReturn(true).when(mUserManager).canAddMoreUsers(); + doReturn(true) + .when(mUserManager).canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_GUEST)); doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability(); mFragment.updateUserList(); @@ -288,7 +291,7 @@ public class UserSettingsTest { @Test public void updateUserList_cannotSwitchUser_shouldDisableAddUser() { mUserCapabilities.mCanAddUser = true; - doReturn(true).when(mUserManager).canAddMoreUsers(); + doReturn(true).when(mUserManager).canAddMoreUsers(anyString()); doReturn(true).when(mAddUserPreference).isEnabled(); doReturn(SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED) .when(mUserManager).getUserSwitchability(); @@ -304,7 +307,7 @@ public class UserSettingsTest { @Test public void updateUserList_canNotAddMoreUsers_shouldDisableAddUserWithSummary() { mUserCapabilities.mCanAddUser = true; - doReturn(false).when(mUserManager).canAddMoreUsers(); + doReturn(false).when(mUserManager).canAddMoreUsers(anyString()); doReturn(false).when(mAddUserPreference).isEnabled(); doReturn(SWITCHABILITY_STATUS_OK).when(mUserManager).getUserSwitchability(); doReturn(4).when(mFragment).getRealUsersCount(); @@ -320,7 +323,8 @@ public class UserSettingsTest { @Test public void updateUserList_cannotSwitchUser_shouldDisableAddGuest() { mUserCapabilities.mCanAddGuest = true; - doReturn(true).when(mUserManager).canAddMoreUsers(); + doReturn(true) + .when(mUserManager).canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_GUEST)); doReturn(SWITCHABILITY_STATUS_USER_IN_CALL).when(mUserManager).getUserSwitchability(); mFragment.updateUserList(); From f57f720c38d34cca6d93568af228359552517e64 Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Fri, 29 Jan 2021 15:37:39 +0800 Subject: [PATCH 03/12] Add the pairing string for CSIP supported device Show the pairing dialog with the hint message that pairing this device will pair all of the set member of a coordinated set. If the device supports CSIP, the message will be shown. Screenshot: https://screenshot.googleplex.com/8WcrdgBoLRgJjHs Bug: 178981521 Test: make RunSettingsRoboTests ROBOTEST_FILTER=BlueotohPairingDialog Change-Id: I5432b7264652dd4485e2669f6004caa4f7459238 Merged-In: I5432b7264652dd4485e2669f6004caa4f7459238 --- res/layout/bluetooth_pin_confirm.xml | 12 ++++++++ res/values/strings.xml | 3 ++ .../bluetooth/BluetoothPairingController.java | 15 ++++++++++ .../BluetoothPairingDialogFragment.java | 3 ++ .../bluetooth/BluetoothPairingDialogTest.java | 28 +++++++++++++++++++ 5 files changed, 61 insertions(+) diff --git a/res/layout/bluetooth_pin_confirm.xml b/res/layout/bluetooth_pin_confirm.xml index 48912755890..28ad1f62920 100644 --- a/res/layout/bluetooth_pin_confirm.xml +++ b/res/layout/bluetooth_pin_confirm.xml @@ -65,6 +65,18 @@ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead" android:visibility="gone" /> + + To pair with:<br><b>%1$s</b><br><br>Make sure it is showing this passkey:<br><b>%2$s</b> + + Confirm to pair with the coordinated set + From:<br><b>%1$s</b><br><br>Pair with this device? diff --git a/src/com/android/settings/bluetooth/BluetoothPairingController.java b/src/com/android/settings/bluetooth/BluetoothPairingController.java index ca3dda67384..ec5c8ddf912 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingController.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingController.java @@ -28,6 +28,7 @@ import androidx.annotation.VisibleForTesting; import com.android.settings.R; import com.android.settings.bluetooth.BluetoothPairingDialogFragment.BluetoothPairingDialogListener; +import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; @@ -64,6 +65,7 @@ public class BluetoothPairingController implements OnCheckedChangeListener, private String mDeviceName; private LocalBluetoothProfile mPbapClientProfile; private boolean mPbapAllowed; + private boolean mIsCoordinatedSetMember; /** * Creates an instance of a BluetoothPairingController. @@ -90,6 +92,10 @@ public class BluetoothPairingController implements OnCheckedChangeListener, mDeviceName = mBluetoothManager.getCachedDeviceManager().getName(mDevice); mPbapClientProfile = mBluetoothManager.getProfileManager().getPbapClientProfile(); mPasskeyFormatted = formatKey(mPasskey); + final CachedBluetoothDevice cachedDevice = + mBluetoothManager.getCachedDeviceManager().findDevice(mDevice); + mIsCoordinatedSetMember = (cachedDevice != null) + ? cachedDevice.isCoordinatedSetMemberDevice() : false; } @Override @@ -155,6 +161,15 @@ public class BluetoothPairingController implements OnCheckedChangeListener, return mDeviceName; } + /** + * A method for querying if the bluetooth device is a LE coordinated set member device. + * + * @return - A boolean indicating if the device is a CSIP supported device. + */ + public boolean isCoordinatedSetMemberDevice() { + return mIsCoordinatedSetMember; + } + /** * A method for querying if the bluetooth device has a profile already set up on this device. * diff --git a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java index d38302d8830..9e3624732d0 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingDialogFragment.java @@ -344,6 +344,9 @@ public class BluetoothPairingDialogFragment extends InstrumentedDialogFragment i pairingViewContent.setVisibility(View.VISIBLE); pairingViewContent.setText(mPairingController.getPairingContent()); } + final TextView messagePairingSet = (TextView) view.findViewById(R.id.pairing_group_message); + messagePairingSet.setVisibility(mPairingController.isCoordinatedSetMemberDevice() + ? View.VISIBLE : View.GONE); return view; } diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java index be733ec97d4..a53e693976e 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDialogTest.java @@ -427,6 +427,34 @@ public class BluetoothPairingDialogTest { userEntryDialogExistingTextTest("test"); } + @Test + public void groupPairing_setMemberDevice_showsMessageHint() { + // set the correct dialog type + when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); + when(controller.isCoordinatedSetMemberDevice()).thenReturn(true); + + // build the fragment + BluetoothPairingDialogFragment frag = makeFragment(); + + // verify message is what we expect it to be and is visible + TextView message = frag.getmDialog().findViewById(R.id.pairing_group_message); + assertThat(message.getVisibility()).isEqualTo(View.VISIBLE); + } + + @Test + public void groupPairing_nonSetMemberDevice_hidesMessageHint() { + // set the correct dialog type + when(controller.getDialogType()).thenReturn(BluetoothPairingController.CONFIRMATION_DIALOG); + when(controller.isCoordinatedSetMemberDevice()).thenReturn(false); + + // build the fragment + BluetoothPairingDialogFragment frag = makeFragment(); + + // verify message is what we expect it to be and is visible + TextView message = frag.getmDialog().findViewById(R.id.pairing_group_message); + assertThat(message.getVisibility()).isEqualTo(View.GONE); + } + // Runs a test simulating the user entry dialog type in a situation like device rotation, where // the dialog fragment gets created and we already have some existing text entered into the // pin field. From 9f11a4cddf42cb04e3980e7c86b3c83bb66fdafd Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Tue, 14 Sep 2021 14:42:48 +0800 Subject: [PATCH 04/12] Show the multiple Mac address for the coordinated set Show the mac address for all the devices if the device detail combine with the multiple connections based on CSIP. Screenshot: https://screenshot.googleplex.com/qQjc2pxNTr3tMUV Bug: 178981521 Test: pair with the coordinated set, and check the UI Change-Id: I01e0ec91e5c856481318d6435d174b5a2018d820 Merged-In: I01e0ec91e5c856481318d6435d174b5a2018d820 --- res/values/strings.xml | 2 ++ .../BluetoothDetailsMacAddressController.java | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 0dd205433f0..86c80c3e6d0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1912,6 +1912,8 @@ Device details Device\'s Bluetooth address: %1$s + + Device\'s Bluetooth address:\n%1$s Forget device? diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsMacAddressController.java b/src/com/android/settings/bluetooth/BluetoothDetailsMacAddressController.java index dda247eac52..c5f845371b4 100644 --- a/src/com/android/settings/bluetooth/BluetoothDetailsMacAddressController.java +++ b/src/com/android/settings/bluetooth/BluetoothDetailsMacAddressController.java @@ -16,6 +16,7 @@ package com.android.settings.bluetooth; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.content.Context; import androidx.preference.PreferenceFragmentCompat; @@ -50,8 +51,17 @@ public class BluetoothDetailsMacAddressController extends BluetoothDetailsContro @Override protected void refresh() { - mFooterPreference.setTitle(mContext.getString( + if (mCachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { + StringBuilder mTitle = new StringBuilder(mContext.getString( + R.string.bluetooth_multuple_devices_mac_address, mCachedDevice.getAddress())); + for (CachedBluetoothDevice member: mCachedDevice.getMemberDevice()) { + mTitle.append("\n").append(member.getAddress()); + } + mFooterPreference.setTitle(mTitle); + } else { + mFooterPreference.setTitle(mContext.getString( R.string.bluetooth_device_mac_address, mCachedDevice.getAddress())); + } } @Override From 61460a1ab16983b4eb258115576d323caded70dd Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Fri, 17 Sep 2021 07:43:01 +0800 Subject: [PATCH 05/12] Accept the pairing request automatically for the set member pairing Check the pairing request from which device that if it's the outgoing set member pairing, accept the pairing request automatically to make the CSIP pairing seamless. Bug: 178981521 Bug: 150670922 Test: Pair one of the CSIP device, and confirm the other set member can paired without the confirmation from user Change-Id: I40afabb09b4cb12a0253035452c9f6974799ed05 Merged-In: I40afabb09b4cb12a0253035452c9f6974799ed05 --- .../android/settings/bluetooth/BluetoothPairingRequest.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java index 993f584dd36..4ea433812ff 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java @@ -23,6 +23,8 @@ import android.content.Intent; import android.os.PowerManager; import android.os.UserHandle; +import com.android.settingslib.bluetooth.LocalBluetoothManager; + /** * BluetoothPairingRequest is a receiver for any Bluetooth pairing request. It * checks if the Bluetooth Settings is currently visible and brings up the PIN, the passkey or a @@ -47,9 +49,11 @@ public final class BluetoothPairingRequest extends BroadcastReceiver { boolean shouldShowDialog = LocalBluetoothPreferences.shouldShowDialogInForeground( context, deviceAddress, deviceName); + final LocalBluetoothManager mBluetoothManager = Utils.getLocalBtManager(context); // Skips consent pairing dialog if the device was recently associated with CDM if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_CONSENT - && device.canBondWithoutDialog()) { + && (device.canBondWithoutDialog() + || mBluetoothManager.getCachedDeviceManager().isOngoingPairByCsip(device))) { device.setPairingConfirmation(true); } else if (powerManager.isInteractive() && shouldShowDialog) { // Since the screen is on and the BT-related activity is in the foreground, From c78fb83aeedb5ce5f9bcef0817f1a92e817c75fd Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Tue, 28 Sep 2021 18:02:41 +0800 Subject: [PATCH 06/12] Do not update the previously connected devices for the sub device As bluetooth turn on, and device reboot, UI will show the sub device entry for hearing aid device or csip device. Check if the device is a sub device, do not update the cachedDevice information. Bug: 150670922 Bug: 178981521 Test: bonded with a coordinated set. Check the UI only have one entry as Bluetooth turn on and device reboot. Change-Id: I03dfdc25b57e614194fb8de2c9265edd50760d30 Merged-In: I03dfdc25b57e614194fb8de2c9265edd50760d30 --- .../android/settings/bluetooth/SavedBluetoothDeviceUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java index dab4f231e35..f5bc279b8a3 100644 --- a/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java +++ b/src/com/android/settings/bluetooth/SavedBluetoothDeviceUpdater.java @@ -65,7 +65,7 @@ public class SavedBluetoothDeviceUpdater extends BluetoothDeviceUpdater removePreferenceIfNecessary(bluetoothDevices, cachedManager); for (BluetoothDevice device : bluetoothDevices) { final CachedBluetoothDevice cachedDevice = cachedManager.findDevice(device); - if (cachedDevice != null) { + if (cachedDevice != null && !cachedManager.isSubDevice(device)) { update(cachedDevice); } } From 629611a43e9964b149d86ca411ac7323264b2273 Mon Sep 17 00:00:00 2001 From: Alice Kuo Date: Wed, 13 Oct 2021 18:43:47 +0800 Subject: [PATCH 07/12] Handle csip set member automatic pair in Setting Move the set member handle to setting. SystemUI and Setting have the individual settingLib instance. If we trigger pairing inside settingLib, the action would be called twice. SystemUI does not contain the concept to handle the pair interaction. Setting would take the action to createBond for CSIP automatically. Bug: 201758444 Bug: 150670922 Test: Pair the coordinated set devices, and check the set member pairing would be done automatically without the pairing dialog Change-Id: Idbdd21a1f15b04cc91cbc2d30a5cb4e9b24174b9 Merged-In: Idbdd21a1f15b04cc91cbc2d30a5cb4e9b24174b9 --- AndroidManifest.xml | 1 + .../bluetooth/BluetoothPairingRequest.java | 71 ++++++++++++------- 2 files changed, 46 insertions(+), 26 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index e10b17ddbf8..ec4d8efd183 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2290,6 +2290,7 @@ android:exported="true"> + diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java index 4ea433812ff..6b80256285a 100644 --- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java +++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java @@ -16,12 +16,14 @@ package com.android.settings.bluetooth; +import android.bluetooth.BluetoothCsipSetCoordinator; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.os.UserHandle; +import android.text.TextUtils; import com.android.settingslib.bluetooth.LocalBluetoothManager; @@ -36,38 +38,55 @@ public final class BluetoothPairingRequest extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (action == null || !action.equals(BluetoothDevice.ACTION_PAIRING_REQUEST)) { + if (action == null) { return; } - PowerManager powerManager = context.getSystemService(PowerManager.class); BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - int pairingVariant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, - BluetoothDevice.ERROR); - String deviceAddress = device != null ? device.getAddress() : null; - String deviceName = device != null ? device.getName() : null; - boolean shouldShowDialog = LocalBluetoothPreferences.shouldShowDialogInForeground( - context, deviceAddress, deviceName); - final LocalBluetoothManager mBluetoothManager = Utils.getLocalBtManager(context); - // Skips consent pairing dialog if the device was recently associated with CDM - if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_CONSENT - && (device.canBondWithoutDialog() - || mBluetoothManager.getCachedDeviceManager().isOngoingPairByCsip(device))) { - device.setPairingConfirmation(true); - } else if (powerManager.isInteractive() && shouldShowDialog) { - // Since the screen is on and the BT-related activity is in the foreground, - // just open the dialog - // convert broadcast intent into activity intent (same action string) - Intent pairingIntent = BluetoothPairingService.getPairingDialogIntent(context, intent, - BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND); + if (TextUtils.equals(action, BluetoothDevice.ACTION_PAIRING_REQUEST)) { + PowerManager powerManager = context.getSystemService(PowerManager.class); + int pairingVariant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT, + BluetoothDevice.ERROR); + String deviceAddress = device != null ? device.getAddress() : null; + String deviceName = device != null ? device.getName() : null; + boolean shouldShowDialog = LocalBluetoothPreferences.shouldShowDialogInForeground( + context, deviceAddress, deviceName); - context.startActivityAsUser(pairingIntent, UserHandle.CURRENT); - } else { - // Put up a notification that leads to the dialog - intent.setClass(context, BluetoothPairingService.class); - intent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST); - context.startServiceAsUser(intent, UserHandle.CURRENT); + // Skips consent pairing dialog if the device was recently associated with CDM + if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_CONSENT + && (device.canBondWithoutDialog() + || mBluetoothManager.getCachedDeviceManager().isOngoingPairByCsip(device))) { + device.setPairingConfirmation(true); + } else if (powerManager.isInteractive() && shouldShowDialog) { + // Since the screen is on and the BT-related activity is in the foreground, + // just open the dialog + // convert broadcast intent into activity intent (same action string) + Intent pairingIntent = BluetoothPairingService.getPairingDialogIntent(context, + intent, BluetoothDevice.EXTRA_PAIRING_INITIATOR_FOREGROUND); + + context.startActivityAsUser(pairingIntent, UserHandle.CURRENT); + } else { + // Put up a notification that leads to the dialog + intent.setClass(context, BluetoothPairingService.class); + intent.setAction(BluetoothDevice.ACTION_PAIRING_REQUEST); + context.startServiceAsUser(intent, UserHandle.CURRENT); + } + } else if (TextUtils.equals(action, + BluetoothCsipSetCoordinator.ACTION_CSIS_SET_MEMBER_AVAILABLE)) { + if (device == null) { + return; + } + + final int groupId = intent.getIntExtra(BluetoothCsipSetCoordinator.EXTRA_CSIS_GROUP_ID, + BluetoothCsipSetCoordinator.GROUP_ID_INVALID); + if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { + return; + } + + if (mBluetoothManager.getCachedDeviceManager().shouldPairByCsip(device, groupId)) { + device.createBond(BluetoothDevice.TRANSPORT_LE); + } } } } From 14e76c3233219bc2a5b5321dd367c5f9321ca464 Mon Sep 17 00:00:00 2001 From: Bonian Chen Date: Thu, 18 Nov 2021 10:27:34 +0800 Subject: [PATCH 08/12] [Settings] Move display of VPN version into summary text Move the display of version text within VPN into summary part of the display, and limit the height of summary area. Bug: 205460459 Test: local Change-Id: I666b9db356feeebf04e3be688897c2d9110a5275 (cherry picked from commit 144f295d7aa66bae8556ba030553a49615eab0b2) --- res/values/strings.xml | 2 +- res/values/styles.xml | 10 ++++ res/xml/vpn_app_management.xml | 14 ++++- .../settings/vpn2/AppManagementFragment.java | 51 +++++++++++++++++-- 4 files changed, 71 insertions(+), 6 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index c730d9871dc..3fbbf4e3d62 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7452,7 +7452,7 @@ Disconnect - Version %s + Version Forget VPN diff --git a/res/values/styles.xml b/res/values/styles.xml index eaebd85b952..8402dec73ca 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -237,6 +237,16 @@ @android:style/TextAppearance.DeviceDefault.Small + + + +