Loading res/values/strings.xml +2 −2 Original line number Diff line number Diff line Loading @@ -256,8 +256,8 @@ <string name="stylus_textfield_handwriting">Stylus writing in textfields</string> <!-- Preference title for toggling whether stylus button presses are ignored [CHAR LIMIT=none] --> <string name="stylus_ignore_button">Ignore all stylus button presses</string> <!-- Name shown in a USI stylus header in device details page [CHAR LIMIT=60] --> <string name="stylus_usi_header_title">USI stylus</string> <!-- Name shown in the title of individual stylus preference in the connected devices page [CHAR LIMIT=60] --> <string name="stylus_connected_devices_title">Stylus</string> <!-- Date & time settings screen title --> <string name="date_and_time">Date & time</string> Loading src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java +55 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.settings.connecteddevice; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.input.InputManager; import android.util.FeatureFlagUtils; import android.view.InputDevice; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; Loading @@ -26,6 +29,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.bluetooth.BluetoothDeviceUpdater; import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater; import com.android.settings.connecteddevice.dock.DockUpdater; import com.android.settings.connecteddevice.stylus.StylusDeviceUpdater; import com.android.settings.connecteddevice.usb.ConnectedUsbDeviceUpdater; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.PreferenceControllerMixin; Loading @@ -51,11 +55,14 @@ public class ConnectedDeviceGroupController extends BasePreferenceController private BluetoothDeviceUpdater mBluetoothDeviceUpdater; private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater; private DockUpdater mConnectedDockUpdater; private StylusDeviceUpdater mStylusDeviceUpdater; private final PackageManager mPackageManager; private final InputManager mInputManager; public ConnectedDeviceGroupController(Context context) { super(context, KEY); mPackageManager = context.getPackageManager(); mInputManager = context.getSystemService(InputManager.class); } @Override Loading @@ -69,9 +76,15 @@ public class ConnectedDeviceGroupController extends BasePreferenceController mConnectedUsbDeviceUpdater.registerCallback(); } if (mConnectedDockUpdater != null) { mConnectedDockUpdater.registerCallback(); } if (mStylusDeviceUpdater != null) { mStylusDeviceUpdater.registerCallback(); } } @Override public void onStop() { if (mBluetoothDeviceUpdater != null) { Loading @@ -82,9 +95,15 @@ public class ConnectedDeviceGroupController extends BasePreferenceController mConnectedUsbDeviceUpdater.unregisterCallback(); } if (mConnectedDockUpdater != null) { mConnectedDockUpdater.unregisterCallback(); } if (mStylusDeviceUpdater != null) { mStylusDeviceUpdater.unregisterCallback(); } } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); Loading @@ -103,15 +122,23 @@ public class ConnectedDeviceGroupController extends BasePreferenceController mConnectedUsbDeviceUpdater.initUsbPreference(context); } if (mConnectedDockUpdater != null) { mConnectedDockUpdater.setPreferenceContext(context); mConnectedDockUpdater.forceUpdate(); } if (mStylusDeviceUpdater != null) { mStylusDeviceUpdater.setPreferenceContext(context); mStylusDeviceUpdater.forceUpdate(); } } } @Override public int getAvailabilityStatus() { return (hasBluetoothFeature() || hasUsbFeature() || hasUsiStylusFeature() || mConnectedDockUpdater != null) ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE; Loading Loading @@ -141,11 +168,13 @@ public class ConnectedDeviceGroupController extends BasePreferenceController @VisibleForTesting void init(BluetoothDeviceUpdater bluetoothDeviceUpdater, ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater, DockUpdater connectedDockUpdater) { DockUpdater connectedDockUpdater, StylusDeviceUpdater connectedStylusDeviceUpdater) { mBluetoothDeviceUpdater = bluetoothDeviceUpdater; mConnectedUsbDeviceUpdater = connectedUsbDeviceUpdater; mConnectedDockUpdater = connectedDockUpdater; mStylusDeviceUpdater = connectedStylusDeviceUpdater; } public void init(DashboardFragment fragment) { Loading @@ -160,7 +189,10 @@ public class ConnectedDeviceGroupController extends BasePreferenceController hasUsbFeature() ? new ConnectedUsbDeviceUpdater(context, fragment, this) : null, connectedDockUpdater); connectedDockUpdater, hasUsiStylusFeature() ? new StylusDeviceUpdater(context, fragment, this) : null); } private boolean hasBluetoothFeature() { Loading @@ -171,4 +203,21 @@ public class ConnectedDeviceGroupController extends BasePreferenceController return mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY) || mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST); } private boolean hasUsiStylusFeature() { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_SHOW_STYLUS_PREFERENCES)) { return false; } for (int deviceId : mInputManager.getInputDeviceIds()) { InputDevice device = mInputManager.getInputDevice(deviceId); if (device != null && device.supportsSource(InputDevice.SOURCE_STYLUS) && !device.isExternal()) { return true; } } return false; } } src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdater.java 0 → 100644 +225 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.connecteddevice.stylus; import android.content.Context; import android.hardware.BatteryState; import android.hardware.input.InputManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; import android.util.Log; import android.view.InputDevice; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.ArrayList; import java.util.List; /** * Controller to maintain available USI stylus devices. Listens to bluetooth * stylus connection to determine whether to show the USI preference. */ public class StylusDeviceUpdater implements InputManager.InputDeviceListener, InputManager.InputDeviceBatteryListener { private static final String TAG = "StylusDeviceUpdater"; private static final String PREF_KEY = "stylus_usi_device"; private static final String INPUT_ID_ARG = "device_input_id"; private final DevicePreferenceCallback mDevicePreferenceCallback; private final List<Integer> mRegisteredBatteryCallbackIds; private final DashboardFragment mFragment; private final InputManager mInputManager; private final MetricsFeatureProvider mMetricsFeatureProvider; private long mLastUsiSeenTime = 0; private Context mContext; @VisibleForTesting Integer mLastDetectedUsiId; @VisibleForTesting Preference mUsiPreference; public StylusDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback) { mFragment = fragment; mRegisteredBatteryCallbackIds = new ArrayList<>(); mDevicePreferenceCallback = devicePreferenceCallback; mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mContext = context; mInputManager = context.getSystemService(InputManager.class); } /** * Register the stylus event callback and update the list */ public void registerCallback() { for (int deviceId : mInputManager.getInputDeviceIds()) { onInputDeviceAdded(deviceId); } mInputManager.registerInputDeviceListener(this, new Handler(Looper.myLooper())); forceUpdate(); } /** * Unregister the stylus event callback */ public void unregisterCallback() { for (int deviceId : mRegisteredBatteryCallbackIds) { mInputManager.removeInputDeviceBatteryListener(deviceId, this); } mInputManager.unregisterInputDeviceListener(this); } @Override public void onInputDeviceAdded(int deviceId) { InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (inputDevice.supportsSource(InputDevice.SOURCE_STYLUS) && !inputDevice.isExternal()) { try { mInputManager.addInputDeviceBatteryListener(deviceId, mContext.getMainExecutor(), this); mRegisteredBatteryCallbackIds.add(deviceId); } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); } } forceUpdate(); } @Override public void onInputDeviceRemoved(int deviceId) { Log.d(TAG, String.format("Input device removed %d", deviceId)); forceUpdate(); } @Override public void onInputDeviceChanged(int deviceId) { if (mInputManager.getInputDevice(deviceId).supportsSource(InputDevice.SOURCE_STYLUS)) { forceUpdate(); } } @Override public void onBatteryStateChanged(int deviceId, long eventTimeMillis, @NonNull BatteryState batteryState) { if (batteryState.isPresent()) { mLastUsiSeenTime = eventTimeMillis; mLastDetectedUsiId = deviceId; } else { mLastUsiSeenTime = -1; mLastDetectedUsiId = null; } forceUpdate(); } /** * Set the context to generate the {@link Preference}, so it could get the correct theme. */ public void setPreferenceContext(Context context) { mContext = context; } /** * Force update to add or remove stylus preference */ public void forceUpdate() { if (shouldShowUsiPreference()) { addOrUpdateUsiPreference(); } else { removeUsiPreference(); } } private synchronized void addOrUpdateUsiPreference() { if (mUsiPreference == null) { mUsiPreference = new Preference(mContext); mDevicePreferenceCallback.onDeviceAdded(mUsiPreference); } mUsiPreference.setKey(PREF_KEY); mUsiPreference.setTitle(R.string.stylus_connected_devices_title); // TODO(b/250909304): pending actual icon visD mUsiPreference.setIcon(R.drawable.circle); mUsiPreference.setOnPreferenceClickListener((Preference p) -> { mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory()); launchDeviceDetails(); return true; }); } private synchronized void removeUsiPreference() { if (mUsiPreference != null) { mDevicePreferenceCallback.onDeviceRemoved(mUsiPreference); mUsiPreference = null; } } private boolean shouldShowUsiPreference() { return isUsiConnectionValid() && !hasConnectedBluetoothStylusDevice(); } @VisibleForTesting public Preference getPreference() { return mUsiPreference; } @VisibleForTesting boolean hasConnectedBluetoothStylusDevice() { for (int deviceId : mInputManager.getInputDeviceIds()) { InputDevice device = mInputManager.getInputDevice(deviceId); if (device.supportsSource(InputDevice.SOURCE_STYLUS) && mInputManager.getInputDeviceBluetoothAddress(deviceId) != null) { return true; } } return false; } @VisibleForTesting boolean isUsiConnectionValid() { // battery listener uses uptimeMillis as its eventTime long currentTime = SystemClock.uptimeMillis(); long usiValidityDuration = 60 * 60 * 1000; // 1 hour return mLastUsiSeenTime > 0 && currentTime - usiValidityDuration <= mLastUsiSeenTime; } private void launchDeviceDetails() { final Bundle args = new Bundle(); args.putInt(INPUT_ID_ARG, mLastDetectedUsiId); new SubSettingLauncher(mFragment.getContext()) .setDestination(StylusUsiDetailsFragment.class.getName()) .setArguments(args) .setSourceMetricsCategory(mFragment.getMetricsCategory()).launch(); } } src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderController.java +1 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ public class StylusUsiHeaderController extends BasePreferenceController implemen mHeaderPreference = screen.findPreference(getPreferenceKey()); View view = mHeaderPreference.findViewById(R.id.entity_header); TextView titleView = view.findViewById(R.id.entity_header_title); titleView.setText(R.string.stylus_usi_header_title); titleView.setText(R.string.stylus_connected_devices_title); ImageView iconView = mHeaderPreference.findViewById(R.id.entity_header_icon); if (iconView != null) { Loading src/com/android/settings/core/gateway/SettingsGateway.java +2 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFrag import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.NfcAndPaymentFragment; import com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.stylus.StylusUsiDetailsFragment; import com.android.settings.connecteddevice.usb.UsbDetailsFragment; import com.android.settings.datausage.DataSaverSummary; import com.android.settings.datausage.DataUsageList; Loading Loading @@ -338,6 +339,7 @@ public class SettingsGateway { BluetoothDeviceDetailsFragment.class.getName(), BluetoothBroadcastDialog.class.getName(), BluetoothFindBroadcastsFragment.class.getName(), StylusUsiDetailsFragment.class.getName(), DataUsageList.class.getName(), ToggleBackupSettingFragment.class.getName(), PreviouslyConnectedDeviceDashboardFragment.class.getName(), Loading Loading
res/values/strings.xml +2 −2 Original line number Diff line number Diff line Loading @@ -256,8 +256,8 @@ <string name="stylus_textfield_handwriting">Stylus writing in textfields</string> <!-- Preference title for toggling whether stylus button presses are ignored [CHAR LIMIT=none] --> <string name="stylus_ignore_button">Ignore all stylus button presses</string> <!-- Name shown in a USI stylus header in device details page [CHAR LIMIT=60] --> <string name="stylus_usi_header_title">USI stylus</string> <!-- Name shown in the title of individual stylus preference in the connected devices page [CHAR LIMIT=60] --> <string name="stylus_connected_devices_title">Stylus</string> <!-- Date & time settings screen title --> <string name="date_and_time">Date & time</string> Loading
src/com/android/settings/connecteddevice/ConnectedDeviceGroupController.java +55 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.settings.connecteddevice; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.input.InputManager; import android.util.FeatureFlagUtils; import android.view.InputDevice; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; Loading @@ -26,6 +29,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.bluetooth.BluetoothDeviceUpdater; import com.android.settings.bluetooth.ConnectedBluetoothDeviceUpdater; import com.android.settings.connecteddevice.dock.DockUpdater; import com.android.settings.connecteddevice.stylus.StylusDeviceUpdater; import com.android.settings.connecteddevice.usb.ConnectedUsbDeviceUpdater; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.PreferenceControllerMixin; Loading @@ -51,11 +55,14 @@ public class ConnectedDeviceGroupController extends BasePreferenceController private BluetoothDeviceUpdater mBluetoothDeviceUpdater; private ConnectedUsbDeviceUpdater mConnectedUsbDeviceUpdater; private DockUpdater mConnectedDockUpdater; private StylusDeviceUpdater mStylusDeviceUpdater; private final PackageManager mPackageManager; private final InputManager mInputManager; public ConnectedDeviceGroupController(Context context) { super(context, KEY); mPackageManager = context.getPackageManager(); mInputManager = context.getSystemService(InputManager.class); } @Override Loading @@ -69,9 +76,15 @@ public class ConnectedDeviceGroupController extends BasePreferenceController mConnectedUsbDeviceUpdater.registerCallback(); } if (mConnectedDockUpdater != null) { mConnectedDockUpdater.registerCallback(); } if (mStylusDeviceUpdater != null) { mStylusDeviceUpdater.registerCallback(); } } @Override public void onStop() { if (mBluetoothDeviceUpdater != null) { Loading @@ -82,9 +95,15 @@ public class ConnectedDeviceGroupController extends BasePreferenceController mConnectedUsbDeviceUpdater.unregisterCallback(); } if (mConnectedDockUpdater != null) { mConnectedDockUpdater.unregisterCallback(); } if (mStylusDeviceUpdater != null) { mStylusDeviceUpdater.unregisterCallback(); } } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); Loading @@ -103,15 +122,23 @@ public class ConnectedDeviceGroupController extends BasePreferenceController mConnectedUsbDeviceUpdater.initUsbPreference(context); } if (mConnectedDockUpdater != null) { mConnectedDockUpdater.setPreferenceContext(context); mConnectedDockUpdater.forceUpdate(); } if (mStylusDeviceUpdater != null) { mStylusDeviceUpdater.setPreferenceContext(context); mStylusDeviceUpdater.forceUpdate(); } } } @Override public int getAvailabilityStatus() { return (hasBluetoothFeature() || hasUsbFeature() || hasUsiStylusFeature() || mConnectedDockUpdater != null) ? AVAILABLE_UNSEARCHABLE : UNSUPPORTED_ON_DEVICE; Loading Loading @@ -141,11 +168,13 @@ public class ConnectedDeviceGroupController extends BasePreferenceController @VisibleForTesting void init(BluetoothDeviceUpdater bluetoothDeviceUpdater, ConnectedUsbDeviceUpdater connectedUsbDeviceUpdater, DockUpdater connectedDockUpdater) { DockUpdater connectedDockUpdater, StylusDeviceUpdater connectedStylusDeviceUpdater) { mBluetoothDeviceUpdater = bluetoothDeviceUpdater; mConnectedUsbDeviceUpdater = connectedUsbDeviceUpdater; mConnectedDockUpdater = connectedDockUpdater; mStylusDeviceUpdater = connectedStylusDeviceUpdater; } public void init(DashboardFragment fragment) { Loading @@ -160,7 +189,10 @@ public class ConnectedDeviceGroupController extends BasePreferenceController hasUsbFeature() ? new ConnectedUsbDeviceUpdater(context, fragment, this) : null, connectedDockUpdater); connectedDockUpdater, hasUsiStylusFeature() ? new StylusDeviceUpdater(context, fragment, this) : null); } private boolean hasBluetoothFeature() { Loading @@ -171,4 +203,21 @@ public class ConnectedDeviceGroupController extends BasePreferenceController return mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY) || mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST); } private boolean hasUsiStylusFeature() { if (!FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_SHOW_STYLUS_PREFERENCES)) { return false; } for (int deviceId : mInputManager.getInputDeviceIds()) { InputDevice device = mInputManager.getInputDevice(deviceId); if (device != null && device.supportsSource(InputDevice.SOURCE_STYLUS) && !device.isExternal()) { return true; } } return false; } }
src/com/android/settings/connecteddevice/stylus/StylusDeviceUpdater.java 0 → 100644 +225 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.connecteddevice.stylus; import android.content.Context; import android.hardware.BatteryState; import android.hardware.input.InputManager; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; import android.util.Log; import android.view.InputDevice; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.connecteddevice.DevicePreferenceCallback; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.ArrayList; import java.util.List; /** * Controller to maintain available USI stylus devices. Listens to bluetooth * stylus connection to determine whether to show the USI preference. */ public class StylusDeviceUpdater implements InputManager.InputDeviceListener, InputManager.InputDeviceBatteryListener { private static final String TAG = "StylusDeviceUpdater"; private static final String PREF_KEY = "stylus_usi_device"; private static final String INPUT_ID_ARG = "device_input_id"; private final DevicePreferenceCallback mDevicePreferenceCallback; private final List<Integer> mRegisteredBatteryCallbackIds; private final DashboardFragment mFragment; private final InputManager mInputManager; private final MetricsFeatureProvider mMetricsFeatureProvider; private long mLastUsiSeenTime = 0; private Context mContext; @VisibleForTesting Integer mLastDetectedUsiId; @VisibleForTesting Preference mUsiPreference; public StylusDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback) { mFragment = fragment; mRegisteredBatteryCallbackIds = new ArrayList<>(); mDevicePreferenceCallback = devicePreferenceCallback; mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); mContext = context; mInputManager = context.getSystemService(InputManager.class); } /** * Register the stylus event callback and update the list */ public void registerCallback() { for (int deviceId : mInputManager.getInputDeviceIds()) { onInputDeviceAdded(deviceId); } mInputManager.registerInputDeviceListener(this, new Handler(Looper.myLooper())); forceUpdate(); } /** * Unregister the stylus event callback */ public void unregisterCallback() { for (int deviceId : mRegisteredBatteryCallbackIds) { mInputManager.removeInputDeviceBatteryListener(deviceId, this); } mInputManager.unregisterInputDeviceListener(this); } @Override public void onInputDeviceAdded(int deviceId) { InputDevice inputDevice = mInputManager.getInputDevice(deviceId); if (inputDevice.supportsSource(InputDevice.SOURCE_STYLUS) && !inputDevice.isExternal()) { try { mInputManager.addInputDeviceBatteryListener(deviceId, mContext.getMainExecutor(), this); mRegisteredBatteryCallbackIds.add(deviceId); } catch (IllegalArgumentException e) { Log.e(TAG, e.getMessage()); } } forceUpdate(); } @Override public void onInputDeviceRemoved(int deviceId) { Log.d(TAG, String.format("Input device removed %d", deviceId)); forceUpdate(); } @Override public void onInputDeviceChanged(int deviceId) { if (mInputManager.getInputDevice(deviceId).supportsSource(InputDevice.SOURCE_STYLUS)) { forceUpdate(); } } @Override public void onBatteryStateChanged(int deviceId, long eventTimeMillis, @NonNull BatteryState batteryState) { if (batteryState.isPresent()) { mLastUsiSeenTime = eventTimeMillis; mLastDetectedUsiId = deviceId; } else { mLastUsiSeenTime = -1; mLastDetectedUsiId = null; } forceUpdate(); } /** * Set the context to generate the {@link Preference}, so it could get the correct theme. */ public void setPreferenceContext(Context context) { mContext = context; } /** * Force update to add or remove stylus preference */ public void forceUpdate() { if (shouldShowUsiPreference()) { addOrUpdateUsiPreference(); } else { removeUsiPreference(); } } private synchronized void addOrUpdateUsiPreference() { if (mUsiPreference == null) { mUsiPreference = new Preference(mContext); mDevicePreferenceCallback.onDeviceAdded(mUsiPreference); } mUsiPreference.setKey(PREF_KEY); mUsiPreference.setTitle(R.string.stylus_connected_devices_title); // TODO(b/250909304): pending actual icon visD mUsiPreference.setIcon(R.drawable.circle); mUsiPreference.setOnPreferenceClickListener((Preference p) -> { mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory()); launchDeviceDetails(); return true; }); } private synchronized void removeUsiPreference() { if (mUsiPreference != null) { mDevicePreferenceCallback.onDeviceRemoved(mUsiPreference); mUsiPreference = null; } } private boolean shouldShowUsiPreference() { return isUsiConnectionValid() && !hasConnectedBluetoothStylusDevice(); } @VisibleForTesting public Preference getPreference() { return mUsiPreference; } @VisibleForTesting boolean hasConnectedBluetoothStylusDevice() { for (int deviceId : mInputManager.getInputDeviceIds()) { InputDevice device = mInputManager.getInputDevice(deviceId); if (device.supportsSource(InputDevice.SOURCE_STYLUS) && mInputManager.getInputDeviceBluetoothAddress(deviceId) != null) { return true; } } return false; } @VisibleForTesting boolean isUsiConnectionValid() { // battery listener uses uptimeMillis as its eventTime long currentTime = SystemClock.uptimeMillis(); long usiValidityDuration = 60 * 60 * 1000; // 1 hour return mLastUsiSeenTime > 0 && currentTime - usiValidityDuration <= mLastUsiSeenTime; } private void launchDeviceDetails() { final Bundle args = new Bundle(); args.putInt(INPUT_ID_ARG, mLastDetectedUsiId); new SubSettingLauncher(mFragment.getContext()) .setDestination(StylusUsiDetailsFragment.class.getName()) .setArguments(args) .setSourceMetricsCategory(mFragment.getMetricsCategory()).launch(); } }
src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderController.java +1 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ public class StylusUsiHeaderController extends BasePreferenceController implemen mHeaderPreference = screen.findPreference(getPreferenceKey()); View view = mHeaderPreference.findViewById(R.id.entity_header); TextView titleView = view.findViewById(R.id.entity_header_title); titleView.setText(R.string.stylus_usi_header_title); titleView.setText(R.string.stylus_connected_devices_title); ImageView iconView = mHeaderPreference.findViewById(R.id.entity_header_icon); if (iconView != null) { Loading
src/com/android/settings/core/gateway/SettingsGateway.java +2 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFrag import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.NfcAndPaymentFragment; import com.android.settings.connecteddevice.PreviouslyConnectedDeviceDashboardFragment; import com.android.settings.connecteddevice.stylus.StylusUsiDetailsFragment; import com.android.settings.connecteddevice.usb.UsbDetailsFragment; import com.android.settings.datausage.DataSaverSummary; import com.android.settings.datausage.DataUsageList; Loading Loading @@ -338,6 +339,7 @@ public class SettingsGateway { BluetoothDeviceDetailsFragment.class.getName(), BluetoothBroadcastDialog.class.getName(), BluetoothFindBroadcastsFragment.class.getName(), StylusUsiDetailsFragment.class.getName(), DataUsageList.class.getName(), ToggleBackupSettingFragment.class.getName(), PreviouslyConnectedDeviceDashboardFragment.class.getName(), Loading