diff options
author | 2025-02-20 15:32:27 +0800 | |
---|---|---|
committer | 2025-02-20 17:05:23 +0800 | |
commit | 11f10d71be9179627e7b75f4045c9fa7b7cedccb (patch) | |
tree | f4746831299e3830cdab77f6ed1b3404f2c2b874 | |
parent | b46e123d872c4fc92400b65611f7322d1436b091 (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
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(); + } } |