Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57822a67 authored by Vania Januar's avatar Vania Januar
Browse files

Pass CachedBluetoothDevice into StylusDevicesController.

Styluses can now be identified using the newly added DEVICE_TYPE_STYLUS
metadata.

Bug: 251200056
Test: StylusDevicesControllerTest
Change-Id: Ie89f6419cd16ed97299944b35497c6b2ee764dab
parent 2b347d7f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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,
+44 −9
Original line number Diff line number Diff line
@@ -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;

@@ -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;
@@ -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
@@ -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();
@@ -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
@@ -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;
    }

}
+1 −1
Original line number Diff line number Diff line
@@ -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;
    }
+79 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -76,6 +78,10 @@ public class StylusDevicesControllerTest {
    private RoleManager mRm;
    @Mock
    private Lifecycle mLifecycle;
    @Mock
    private CachedBluetoothDevice mCachedBluetoothDevice;
    @Mock
    private BluetoothDevice mBluetoothDevice;


    @Before
@@ -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);