Loading src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +2 −1 Original line number Diff line number Diff line Loading @@ -312,7 +312,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice, lifecycle)); controllers.add(new StylusDevicesController(context, mInputDevice, lifecycle)); controllers.add(new StylusDevicesController(context, mInputDevice, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsRelatedToolsController(context, this, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsPairOtherController(context, this, mCachedDevice, Loading src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java +44 −9 Original line number Diff line number Diff line Loading @@ -17,12 +17,14 @@ package com.android.settings.connecteddevice.stylus; import android.app.role.RoleManager; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.provider.Settings; import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.Log; import android.view.InputDevice; Loading @@ -34,6 +36,8 @@ import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; Loading Loading @@ -61,18 +65,23 @@ public class StylusDevicesController extends AbstractPreferenceController implem @Nullable private final InputDevice mInputDevice; @Nullable private final CachedBluetoothDevice mCachedBluetoothDevice; @VisibleForTesting PreferenceCategory mPreferencesContainer; public StylusDevicesController(Context context, InputDevice inputDevice, Lifecycle lifecycle) { public StylusDevicesController(Context context, InputDevice inputDevice, CachedBluetoothDevice cachedBluetoothDevice, Lifecycle lifecycle) { super(context); mInputDevice = inputDevice; mCachedBluetoothDevice = cachedBluetoothDevice; lifecycle.addObserver(this); } @Override public boolean isAvailable() { return mInputDevice != null && mInputDevice.supportsSource(InputDevice.SOURCE_STYLUS); return isDeviceStylus(mInputDevice, mCachedBluetoothDevice); } @Nullable Loading Loading @@ -179,7 +188,6 @@ public class StylusDevicesController extends AbstractPreferenceController implem private void refresh() { if (!isAvailable()) return; if (mInputDevice.getBluetoothAddress() != null) { Preference notesPref = mPreferencesContainer.findPreference(KEY_DEFAULT_NOTES); if (notesPref == null) { notesPref = createDefaultNotesPreference(); Loading @@ -187,7 +195,6 @@ public class StylusDevicesController extends AbstractPreferenceController implem mPreferencesContainer.addPreference(notesPref); } } } Preference handwritingPref = mPreferencesContainer.findPreference(KEY_HANDWRITING); // TODO(b/255732419): add proper InputMethodInfo conditional to show or hide Loading @@ -201,4 +208,32 @@ public class StylusDevicesController extends AbstractPreferenceController implem mPreferencesContainer.addPreference(createButtonPressPreference()); } } /** * 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; } } src/com/android/settings/connecteddevice/stylus/StylusUsiDetailsFragment.java +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class StylusUsiDetailsFragment extends DashboardFragment { if (mInputDevice != null) { Lifecycle lifecycle = getSettingsLifecycle(); controllers.add(new StylusUsiHeaderController(context, mInputDevice)); controllers.add(new StylusDevicesController(context, mInputDevice, lifecycle)); controllers.add(new StylusDevicesController(context, mInputDevice, null, lifecycle)); } return controllers; } Loading tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java +79 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.role.RoleManager; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; Loading @@ -44,6 +45,7 @@ import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; Loading Loading @@ -76,6 +78,10 @@ public class StylusDevicesControllerTest { private RoleManager mRm; @Mock private Lifecycle mLifecycle; @Mock private CachedBluetoothDevice mCachedBluetoothDevice; @Mock private BluetoothDevice mBluetoothDevice; @Before Loading @@ -101,24 +107,94 @@ public class StylusDevicesControllerTest { any(PackageManager.ApplicationInfoFlags.class))).thenReturn(new ApplicationInfo()); when(mPm.getApplicationLabel(any(ApplicationInfo.class))).thenReturn(NOTES_APP_LABEL); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mInputDevice = spy(new InputDevice.Builder() .setId(1) .setSources(InputDevice.SOURCE_STYLUS) .build()); when(mInputDevice.getBluetoothAddress()).thenReturn("SOME:ADDRESS"); mController = new StylusDevicesController(mContext, mInputDevice, mLifecycle); mController = new StylusDevicesController(mContext, mInputDevice, null, mLifecycle); } @Test public void isDeviceStylus_noDevices_false() { assertThat(StylusDevicesController.isDeviceStylus(null, null)).isFalse(); } @Test public void isDeviceStylus_nonStylusInputDevice_false() { InputDevice inputDevice = new InputDevice.Builder() .setSources(InputDevice.SOURCE_DPAD) .build(); assertThat(StylusDevicesController.isDeviceStylus(inputDevice, null)).isFalse(); } @Test public void isDeviceStylus_stylusInputDevice_true() { InputDevice inputDevice = new InputDevice.Builder() .setSources(InputDevice.SOURCE_STYLUS) .build(); assertThat(StylusDevicesController.isDeviceStylus(inputDevice, null)).isTrue(); } @Test public void noInputDevice_noPreference() { public void isDeviceStylus_nonStylusBluetoothDevice_false() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.DEVICE_TYPE_WATCH.getBytes()); assertThat(StylusDevicesController.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(StylusDevicesController.isDeviceStylus(null, mCachedBluetoothDevice)).isTrue(); } @Test public void noInputDevice_noBluetoothDevice_noPreference() { StylusDevicesController controller = new StylusDevicesController( mContext, null, mLifecycle mContext, null, null, mLifecycle ); showScreen(controller); assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(0); } @Test public void noInputDevice_nonStylusBluetoothDevice_noPreference() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.DEVICE_TYPE_WATCH.getBytes()); StylusDevicesController controller = new StylusDevicesController( mContext, null, mCachedBluetoothDevice, mLifecycle ); showScreen(controller); assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(0); } @Test public void noInputDevice_stylusBluetoothDevice_showsPreference() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.DEVICE_TYPE_STYLUS.getBytes()); StylusDevicesController controller = new StylusDevicesController( mContext, null, mCachedBluetoothDevice, mLifecycle ); showScreen(controller); assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(3); } @Test public void btStylusInputDevice_showsAllPreferences() { showScreen(mController); Loading Loading
src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +2 −1 Original line number Diff line number Diff line Loading @@ -312,7 +312,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsMacAddressController(context, this, mCachedDevice, lifecycle)); controllers.add(new StylusDevicesController(context, mInputDevice, lifecycle)); controllers.add(new StylusDevicesController(context, mInputDevice, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsRelatedToolsController(context, this, mCachedDevice, lifecycle)); controllers.add(new BluetoothDetailsPairOtherController(context, this, mCachedDevice, Loading
src/com/android/settings/connecteddevice/stylus/StylusDevicesController.java +44 −9 Original line number Diff line number Diff line Loading @@ -17,12 +17,14 @@ package com.android.settings.connecteddevice.stylus; import android.app.role.RoleManager; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.provider.Settings; import android.provider.Settings.Secure; import android.text.TextUtils; import android.util.Log; import android.view.InputDevice; Loading @@ -34,6 +36,8 @@ import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; Loading Loading @@ -61,18 +65,23 @@ public class StylusDevicesController extends AbstractPreferenceController implem @Nullable private final InputDevice mInputDevice; @Nullable private final CachedBluetoothDevice mCachedBluetoothDevice; @VisibleForTesting PreferenceCategory mPreferencesContainer; public StylusDevicesController(Context context, InputDevice inputDevice, Lifecycle lifecycle) { public StylusDevicesController(Context context, InputDevice inputDevice, CachedBluetoothDevice cachedBluetoothDevice, Lifecycle lifecycle) { super(context); mInputDevice = inputDevice; mCachedBluetoothDevice = cachedBluetoothDevice; lifecycle.addObserver(this); } @Override public boolean isAvailable() { return mInputDevice != null && mInputDevice.supportsSource(InputDevice.SOURCE_STYLUS); return isDeviceStylus(mInputDevice, mCachedBluetoothDevice); } @Nullable Loading Loading @@ -179,7 +188,6 @@ public class StylusDevicesController extends AbstractPreferenceController implem private void refresh() { if (!isAvailable()) return; if (mInputDevice.getBluetoothAddress() != null) { Preference notesPref = mPreferencesContainer.findPreference(KEY_DEFAULT_NOTES); if (notesPref == null) { notesPref = createDefaultNotesPreference(); Loading @@ -187,7 +195,6 @@ public class StylusDevicesController extends AbstractPreferenceController implem mPreferencesContainer.addPreference(notesPref); } } } Preference handwritingPref = mPreferencesContainer.findPreference(KEY_HANDWRITING); // TODO(b/255732419): add proper InputMethodInfo conditional to show or hide Loading @@ -201,4 +208,32 @@ public class StylusDevicesController extends AbstractPreferenceController implem mPreferencesContainer.addPreference(createButtonPressPreference()); } } /** * 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; } }
src/com/android/settings/connecteddevice/stylus/StylusUsiDetailsFragment.java +1 −1 Original line number Diff line number Diff line Loading @@ -77,7 +77,7 @@ public class StylusUsiDetailsFragment extends DashboardFragment { if (mInputDevice != null) { Lifecycle lifecycle = getSettingsLifecycle(); controllers.add(new StylusUsiHeaderController(context, mInputDevice)); controllers.add(new StylusDevicesController(context, mInputDevice, lifecycle)); controllers.add(new StylusDevicesController(context, mInputDevice, null, lifecycle)); } return controllers; } Loading
tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusDevicesControllerTest.java +79 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.role.RoleManager; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; Loading @@ -44,6 +45,7 @@ import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; Loading Loading @@ -76,6 +78,10 @@ public class StylusDevicesControllerTest { private RoleManager mRm; @Mock private Lifecycle mLifecycle; @Mock private CachedBluetoothDevice mCachedBluetoothDevice; @Mock private BluetoothDevice mBluetoothDevice; @Before Loading @@ -101,24 +107,94 @@ public class StylusDevicesControllerTest { any(PackageManager.ApplicationInfoFlags.class))).thenReturn(new ApplicationInfo()); when(mPm.getApplicationLabel(any(ApplicationInfo.class))).thenReturn(NOTES_APP_LABEL); when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice); mInputDevice = spy(new InputDevice.Builder() .setId(1) .setSources(InputDevice.SOURCE_STYLUS) .build()); when(mInputDevice.getBluetoothAddress()).thenReturn("SOME:ADDRESS"); mController = new StylusDevicesController(mContext, mInputDevice, mLifecycle); mController = new StylusDevicesController(mContext, mInputDevice, null, mLifecycle); } @Test public void isDeviceStylus_noDevices_false() { assertThat(StylusDevicesController.isDeviceStylus(null, null)).isFalse(); } @Test public void isDeviceStylus_nonStylusInputDevice_false() { InputDevice inputDevice = new InputDevice.Builder() .setSources(InputDevice.SOURCE_DPAD) .build(); assertThat(StylusDevicesController.isDeviceStylus(inputDevice, null)).isFalse(); } @Test public void isDeviceStylus_stylusInputDevice_true() { InputDevice inputDevice = new InputDevice.Builder() .setSources(InputDevice.SOURCE_STYLUS) .build(); assertThat(StylusDevicesController.isDeviceStylus(inputDevice, null)).isTrue(); } @Test public void noInputDevice_noPreference() { public void isDeviceStylus_nonStylusBluetoothDevice_false() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.DEVICE_TYPE_WATCH.getBytes()); assertThat(StylusDevicesController.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(StylusDevicesController.isDeviceStylus(null, mCachedBluetoothDevice)).isTrue(); } @Test public void noInputDevice_noBluetoothDevice_noPreference() { StylusDevicesController controller = new StylusDevicesController( mContext, null, mLifecycle mContext, null, null, mLifecycle ); showScreen(controller); assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(0); } @Test public void noInputDevice_nonStylusBluetoothDevice_noPreference() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.DEVICE_TYPE_WATCH.getBytes()); StylusDevicesController controller = new StylusDevicesController( mContext, null, mCachedBluetoothDevice, mLifecycle ); showScreen(controller); assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(0); } @Test public void noInputDevice_stylusBluetoothDevice_showsPreference() { when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE)).thenReturn( BluetoothDevice.DEVICE_TYPE_STYLUS.getBytes()); StylusDevicesController controller = new StylusDevicesController( mContext, null, mCachedBluetoothDevice, mLifecycle ); showScreen(controller); assertThat(mPreferenceContainer.getPreferenceCount()).isEqualTo(3); } @Test public void btStylusInputDevice_showsAllPreferences() { showScreen(mController); Loading