summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ze Li <lze@google.com> 2025-02-20 15:32:27 +0800
committer Ze Li <lze@google.com> 2025-02-20 17:05:23 +0800
commit11f10d71be9179627e7b75f4045c9fa7b7cedccb (patch)
treef4746831299e3830cdab77f6ed1b3404f2c2b874
parentb46e123d872c4fc92400b65611f7322d1436b091 (diff)
[Battery refactor] Move stylus related functions to BluetoothUtils as util functions.
Test: com.android.settingslib.bluetooth.BluetoothUtilsTest Bug: 397847825 Flag: EXEMPT utils function Change-Id: I9e7d4d167ce303fb6f4c28851128192948ec0570
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java51
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java84
2 files changed, 123 insertions, 12 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 522a436b0732..335f4a8293a0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -23,6 +23,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.input.InputManager;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
@@ -34,6 +35,7 @@ import android.sysprop.BluetoothProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+import android.view.InputDevice;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
@@ -1193,4 +1195,53 @@ public class BluetoothUtils {
}
device.setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS, fastPairCustomizedMeta.getBytes());
}
+
+ /**
+ * Returns the {@link InputDevice} of the given bluetooth address if the device is a input
+ * device.
+ *
+ * @param address The address of the bluetooth device
+ * @return The {@link InputDevice} of the given address if applicable
+ */
+ @Nullable
+ public static InputDevice getInputDevice(Context context, String address) {
+ InputManager im = context.getSystemService(InputManager.class);
+
+ if (im != null) {
+ for (int deviceId : im.getInputDeviceIds()) {
+ String btAddress = im.getInputDeviceBluetoothAddress(deviceId);
+
+ if (btAddress != null && btAddress.equals(address)) {
+ return im.getInputDevice(deviceId);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Identifies whether a device is a stylus using the associated {@link InputDevice} or
+ * {@link CachedBluetoothDevice}.
+ * InputDevices are only available when the device is USI or Bluetooth-connected, whereas
+ * CachedBluetoothDevices are available for Bluetooth devices when connected or paired,
+ * so to handle all cases, both are needed.
+ *
+ * @param inputDevice The associated input device of the stylus
+ * @param cachedBluetoothDevice The associated bluetooth device of the stylus
+ */
+ public static boolean isDeviceStylus(@Nullable InputDevice inputDevice,
+ @Nullable CachedBluetoothDevice cachedBluetoothDevice) {
+ if (inputDevice != null && inputDevice.supportsSource(InputDevice.SOURCE_STYLUS)) {
+ return true;
+ }
+
+ if (cachedBluetoothDevice != null) {
+ BluetoothDevice bluetoothDevice = cachedBluetoothDevice.getDevice();
+ String deviceType = BluetoothUtils.getStringMetaData(bluetoothDevice,
+ BluetoothDevice.METADATA_DEVICE_TYPE);
+ return TextUtils.equals(deviceType, BluetoothDevice.DEVICE_TYPE_STYLUS);
+ }
+
+ return false;
+ }
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
index ebe6128e5582..0325c0ec7915 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/BluetoothUtilsTest.java
@@ -15,7 +15,9 @@
*/
package com.android.settingslib.bluetooth;
+import static com.android.settingslib.bluetooth.BluetoothUtils.getInputDevice;
import static com.android.settingslib.bluetooth.BluetoothUtils.isAvailableAudioSharingMediaBluetoothDevice;
+import static com.android.settingslib.bluetooth.BluetoothUtils.isDeviceStylus;
import static com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast.UNKNOWN_VALUE_PLACEHOLDER;
import static com.android.settingslib.flags.Flags.FLAG_ENABLE_DETERMINING_ADVANCED_DETAILS_HEADER_WITH_METADATA;
@@ -42,6 +44,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
+import android.hardware.input.InputManager;
import android.media.AudioDeviceAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
@@ -51,6 +54,7 @@ import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.util.Pair;
+import android.view.InputDevice;
import com.android.internal.R;
import com.android.settingslib.flags.Flags;
@@ -97,14 +101,18 @@ public class BluetoothUtilsTest {
@Mock private LocalBluetoothLeBroadcastAssistant mAssistant;
@Mock private CachedBluetoothDeviceManager mDeviceManager;
@Mock private BluetoothLeBroadcastReceiveState mLeBroadcastReceiveState;
+ @Mock
+ private InputManager mInputManager;
private Context mContext;
private ShadowBluetoothAdapter mShadowBluetoothAdapter;
+ private final InputDevice mInputDevice = mock(InputDevice.class);
private static final String STRING_METADATA = "string_metadata";
private static final String LE_AUDIO_SHARING_METADATA = "le_audio_sharing";
private static final String BOOL_METADATA = "true";
private static final String INT_METADATA = "25";
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
+ private static final int TEST_DEVICE_ID = 123;
private static final String KEY_HEARABLE_CONTROL_SLICE = "HEARABLE_CONTROL_SLICE_WITH_WIDTH";
private static final String CONTROL_METADATA =
"<HEARABLE_CONTROL_SLICE_WITH_WIDTH>"
@@ -115,6 +123,7 @@ public class BluetoothUtilsTest {
private static final String FAKE_TEMP_BOND_METADATA = "<TEMP_BOND_TYPE>fake</TEMP_BOND_TYPE>";
private static final String TEST_EXCLUSIVE_MANAGER_PACKAGE = "com.test.manager";
private static final String TEST_EXCLUSIVE_MANAGER_COMPONENT = "com.test.manager/.component";
+ private static final String TEST_ADDRESS = "11:22:33:44:55:66";
private static final int TEST_BROADCAST_ID = 25;
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@@ -134,6 +143,10 @@ public class BluetoothUtilsTest {
when(mA2dpProfile.getProfileId()).thenReturn(BluetoothProfile.A2DP);
when(mLeAudioProfile.getProfileId()).thenReturn(BluetoothProfile.LE_AUDIO);
when(mHearingAid.getProfileId()).thenReturn(BluetoothProfile.HEARING_AID);
+ when(mContext.getSystemService(InputManager.class)).thenReturn(mInputManager);
+ when(mInputManager.getInputDeviceIds()).thenReturn(new int[]{TEST_DEVICE_ID});
+ when(mInputManager.getInputDeviceBluetoothAddress(TEST_DEVICE_ID)).thenReturn(TEST_ADDRESS);
+ when(mInputManager.getInputDevice(TEST_DEVICE_ID)).thenReturn(mInputDevice);
}
@Test
@@ -1097,9 +1110,8 @@ public class BluetoothUtilsTest {
@Test
public void getAudioDeviceAttributesForSpatialAudio_bleHeadset() {
- String address = "11:22:33:44:55:66";
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mLeAudioProfile));
when(mLeAudioProfile.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1112,14 +1124,13 @@ public class BluetoothUtilsTest {
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLE_HEADSET,
- address));
+ TEST_ADDRESS));
}
@Test
public void getAudioDeviceAttributesForSpatialAudio_bleSpeaker() {
- String address = "11:22:33:44:55:66";
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mLeAudioProfile));
when(mLeAudioProfile.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1132,14 +1143,14 @@ public class BluetoothUtilsTest {
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLE_SPEAKER,
- address));
+ TEST_ADDRESS));
}
@Test
public void getAudioDeviceAttributesForSpatialAudio_a2dp() {
- String address = "11:22:33:44:55:66";
+
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mA2dpProfile));
when(mA2dpProfile.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1152,14 +1163,13 @@ public class BluetoothUtilsTest {
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
- address));
+ TEST_ADDRESS));
}
@Test
public void getAudioDeviceAttributesForSpatialAudio_hearingAid() {
- String address = "11:22:33:44:55:66";
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
- when(mCachedBluetoothDevice.getAddress()).thenReturn(address);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_ADDRESS);
when(mCachedBluetoothDevice.getProfiles()).thenReturn(List.of(mHearingAid));
when(mHearingAid.isEnabled(mBluetoothDevice)).thenReturn(true);
@@ -1172,7 +1182,7 @@ public class BluetoothUtilsTest {
new AudioDeviceAttributes(
AudioDeviceAttributes.ROLE_OUTPUT,
AudioDeviceInfo.TYPE_HEARING_AID,
- address));
+ TEST_ADDRESS));
}
@Test
@@ -1375,4 +1385,54 @@ public class BluetoothUtilsTest {
verify(mBluetoothDevice).setMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS,
TEMP_BOND_METADATA.getBytes());
}
+
+ @Test
+ public void getInputDevice_addressNotMatched_returnsNull() {
+ assertThat(getInputDevice(mContext, "123")).isNull();
+ }
+
+ @Test
+ public void getInputDevice_isInputDevice_returnsInputDevice() {
+ assertThat(getInputDevice(mContext, TEST_ADDRESS)).isEqualTo(mInputDevice);
+ }
+
+ @Test
+ public void isDeviceStylus_noDevices_false() {
+ assertThat(isDeviceStylus(null, null)).isFalse();
+ }
+
+ @Test
+ public void isDeviceStylus_nonStylusInputDevice_false() {
+ InputDevice inputDevice = new InputDevice.Builder()
+ .setSources(InputDevice.SOURCE_DPAD)
+ .build();
+
+ assertThat(isDeviceStylus(inputDevice, null)).isFalse();
+ }
+
+ @Test
+ public void isDeviceStylus_stylusInputDevice_true() {
+ InputDevice inputDevice = new InputDevice.Builder()
+ .setSources(InputDevice.SOURCE_STYLUS)
+ .build();
+
+ assertThat(isDeviceStylus(inputDevice, null)).isTrue();
+ }
+
+ @Test
+ public void isDeviceStylus_nonStylusBluetoothDevice_false() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_WATCH.getBytes());
+
+ assertThat(isDeviceStylus(null, mCachedBluetoothDevice)).isFalse();
+ }
+
+ @Test
+ public void isDeviceStylus_stylusBluetoothDevice_true() {
+ when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn(
+ BluetoothDevice.DEVICE_TYPE_STYLUS.getBytes());
+ when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
+
+ assertThat(isDeviceStylus(null, mCachedBluetoothDevice)).isTrue();
+ }
}