Snap for 6535363 from 3b1ef19c33 to mainline-release

Change-Id: Id6cd3fa911b0d8662242b4fa66f62828f715c7df
This commit is contained in:
android-build-team Robot
2020-05-28 07:09:12 +00:00
35 changed files with 326 additions and 67 deletions

View File

@@ -42,7 +42,6 @@
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:labelFor="@id/user_photo"
android:inputType="text|textCapWords" android:inputType="text|textCapWords"
android:selectAllOnFocus="true" android:selectAllOnFocus="true"
android:hint="@string/user_nickname" android:hint="@string/user_nickname"

View File

@@ -76,7 +76,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical" android:layout_gravity="left|center_vertical"
android:ellipsize="end" android:ellipsize="end"
android:singleLine="true" android:maxLines="3"
android:paddingTop="3dp" android:paddingTop="3dp"
android:textAppearance="@style/TextAppearance.NotificationHistory.Text" android:textAppearance="@style/TextAppearance.NotificationHistory.Text"
android:textAlignment="viewStart" /> android:textAlignment="viewStart" />

View File

@@ -125,7 +125,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical" android:layout_gravity="left|center_vertical"
android:ellipsize="end" android:ellipsize="end"
android:singleLine="true" android:maxLines="3"
android:textAppearance="@style/TextAppearance.NotificationHistory.Text" android:textAppearance="@style/TextAppearance.NotificationHistory.Text"
android:textAlignment="viewStart" android:textAlignment="viewStart"
/> />

View File

@@ -7323,7 +7323,7 @@
<string name="mms_message_summary">Send &amp; receive when mobile data is off</string> <string name="mms_message_summary">Send &amp; receive when mobile data is off</string>
<!-- Cell broacast receiver package name [DO NOT TRANSLATE] --> <!-- Cell broacast receiver package name [DO NOT TRANSLATE] -->
<string name="cell_broadcast_receiver_package">com.android.cellbroadcastreceiver</string> <string name="cell_broadcast_receiver_package">com.android.cellbroadcastreceiver.module</string>
<!-- Title of a preference for whether to allow data during calls that is shown when mobile <!-- Title of a preference for whether to allow data during calls that is shown when mobile
data is turned off. This is needed for some multi-SIM scenarios, because the SIM that is data is turned off. This is needed for some multi-SIM scenarios, because the SIM that is

View File

@@ -17,7 +17,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"> xmlns:settings="http://schemas.android.com/apk/res-auto">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch" /> android:key="app_ops_settings_switch" />
<Preference <Preference

View File

@@ -16,8 +16,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto" xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/bubbles_app_toggle_title" android:title="@string/bubbles_app_toggle_title">
android:key="bubble_notification_settings">
<com.android.settings.widget.VideoPreference <com.android.settings.widget.VideoPreference
android:key="bubbles_illustration" android:key="bubbles_illustration"

View File

@@ -18,7 +18,7 @@
android:key="change_wifi_state" android:key="change_wifi_state"
android:title="@string/change_wifi_state_title"> android:title="@string/change_wifi_state_title">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch" android:key="app_ops_settings_switch"
android:title="@string/change_wifi_state_app_detail_switch"/> android:title="@string/change_wifi_state_app_detail_switch"/>

View File

@@ -18,7 +18,7 @@
android:key="draw_overlay_permission_detail_settings" android:key="draw_overlay_permission_detail_settings"
android:title="@string/draw_overlay"> android:title="@string/draw_overlay">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch" android:key="app_ops_settings_switch"
android:title="@string/permit_draw_overlay"/> android:title="@string/permit_draw_overlay"/>

View File

@@ -17,7 +17,7 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/install_other_apps"> android:title="@string/install_other_apps">
<com.android.settingslib.RestrictedSwitchPreference <com.android.settings.widget.FilterTouchesRestrictedSwitchPreference
android:key="external_sources_settings_switch" android:key="external_sources_settings_switch"
android:title="@string/external_source_switch_title" /> android:title="@string/external_source_switch_title" />

View File

@@ -1,19 +1,18 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!-- Copyright (C) 2020 The Android Open Source Project
~ Copyright (C) 2020 The Android Open Source Project
~ Licensed under the Apache License, Version 2.0 (the "License");
~ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
~ you may not use this file except in compliance with the License. You may obtain a copy of the License at
~ You may obtain a copy of the License at
~ http://www.apache.org/licenses/LICENSE-2.0
~ http://www.apache.org/licenses/LICENSE-2.0
~ Unless required by applicable law or agreed to in writing, software
~ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and
~ See the License for the specific language governing permissions and limitations under the License.
~ limitations under the License. -->
-->
<PreferenceScreen <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
@@ -29,7 +28,7 @@
android:icon="@drawable/ic_download_for_offline" android:icon="@drawable/ic_download_for_offline"
android:gravity="top"/> android:gravity="top"/>
<com.android.settingslib.RestrictedSwitchPreference <com.android.settings.widget.FilterTouchesRestrictedSwitchPreference
android:key="interact_across_profiles_settings_switch" /> android:key="interact_across_profiles_settings_switch" />
<Preference <Preference

View File

@@ -20,7 +20,7 @@
android:key="manage_external_storage_permission_details" android:key="manage_external_storage_permission_details"
android:title="@string/manage_external_storage_title"> android:title="@string/manage_external_storage_title">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch" android:key="app_ops_settings_switch"
android:title="@string/permit_manage_external_storage"/> android:title="@string/permit_manage_external_storage"/>

View File

@@ -20,7 +20,7 @@
android:key="notification_access_permission_detail_settings" android:key="notification_access_permission_detail_settings"
android:title="@string/manage_notification_access_title"> android:title="@string/manage_notification_access_title">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="notification_access_switch" android:key="notification_access_switch"
android:title="@string/notification_access_detail_switch"/> android:title="@string/notification_access_detail_switch"/>

View File

@@ -18,7 +18,7 @@
android:key="picture_in_picture_permission_detail_settings" android:key="picture_in_picture_permission_detail_settings"
android:title="@string/picture_in_picture_app_detail_title"> android:title="@string/picture_in_picture_app_detail_title">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch" android:key="app_ops_settings_switch"
android:title="@string/picture_in_picture_app_detail_switch"/> android:title="@string/picture_in_picture_app_detail_switch"/>

View File

@@ -18,7 +18,7 @@
android:key="write_system_settings_permission_detail_settings" android:key="write_system_settings_permission_detail_settings"
android:title="@string/write_settings"> android:title="@string/write_settings">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="app_ops_settings_switch" android:key="app_ops_settings_switch"
android:title="@string/permit_write_settings"/> android:title="@string/permit_write_settings"/>

View File

@@ -20,7 +20,7 @@
android:key="zen_access_permission_detail_settings" android:key="zen_access_permission_detail_settings"
android:title="@string/manage_zen_access_title"> android:title="@string/manage_zen_access_title">
<SwitchPreference <com.android.settings.widget.FilterTouchesSwitchPreference
android:key="zen_access_switch" android:key="zen_access_switch"
android:title="@string/zen_access_detail_switch"/> android:title="@string/zen_access_detail_switch"/>

View File

@@ -119,7 +119,6 @@ import com.android.settings.widget.LoadingViewController;
import com.android.settings.wifi.AppStateChangeWifiStateBridge; import com.android.settings.wifi.AppStateChangeWifiStateBridge;
import com.android.settings.wifi.ChangeWifiStateDetails; import com.android.settings.wifi.ChangeWifiStateDetails;
import com.android.settingslib.HelpUtils; import com.android.settingslib.HelpUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState; import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry; import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter; import com.android.settingslib.applications.ApplicationsState.AppFilter;
@@ -1462,12 +1461,10 @@ public class ManageApplications extends InstrumentedFragment
ApplicationsState.AppEntry entry = mEntries.get(position); ApplicationsState.AppEntry entry = mEntries.get(position);
synchronized (entry) { synchronized (entry) {
holder.setTitle(entry.label); holder.setTitle(entry.label);
holder.itemView.setContentDescription( mState.ensureLabelDescription(entry);
AppUtils.getAppContentDescription( holder.itemView.setContentDescription(entry.labelDescription);
mContext, mState.ensureIcon(entry);
entry.info.packageName, holder.setIcon(entry.icon);
UserHandle.getUserId(entry.info.uid)));
holder.setIcon(Utils.getBadgedIcon(mContext, entry.info));
updateSummary(holder, entry); updateSummary(holder, entry);
updateSwitch(holder, entry); updateSwitch(holder, entry);
holder.updateDisableView(entry.info); holder.updateDisableView(entry.info);

View File

@@ -43,10 +43,10 @@ import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.PreferenceGroup; import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.FilterTouchesSwitchPreference;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStart;
@@ -168,32 +168,32 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle
if (mFooterPreference != null) { if (mFooterPreference != null) {
mFooterPreference.setVisible(mAdmins.isEmpty()); mFooterPreference.setVisible(mAdmins.isEmpty());
} }
final Map<String, SwitchPreference> preferenceCache = new ArrayMap<>(); final Map<String, FilterTouchesSwitchPreference> preferenceCache = new ArrayMap<>();
final Context prefContext = mPreferenceGroup.getContext(); final Context prefContext = mPreferenceGroup.getContext();
final int childrenCount = mPreferenceGroup.getPreferenceCount(); final int childrenCount = mPreferenceGroup.getPreferenceCount();
for (int i = 0; i < childrenCount; i++) { for (int i = 0; i < childrenCount; i++) {
final Preference pref = mPreferenceGroup.getPreference(i); final Preference pref = mPreferenceGroup.getPreference(i);
if (!(pref instanceof SwitchPreference)) { if (!(pref instanceof FilterTouchesSwitchPreference)) {
continue; continue;
} }
final SwitchPreference appSwitch = (SwitchPreference) pref; final FilterTouchesSwitchPreference appSwitch = (FilterTouchesSwitchPreference) pref;
preferenceCache.put(appSwitch.getKey(), appSwitch); preferenceCache.put(appSwitch.getKey(), appSwitch);
} }
for (DeviceAdminListItem item : mAdmins) { for (DeviceAdminListItem item : mAdmins) {
final String key = item.getKey(); final String key = item.getKey();
SwitchPreference pref = preferenceCache.remove(key); FilterTouchesSwitchPreference pref = preferenceCache.remove(key);
if (pref == null) { if (pref == null) {
pref = new SwitchPreference(prefContext); pref = new FilterTouchesSwitchPreference(prefContext);
mPreferenceGroup.addPreference(pref); mPreferenceGroup.addPreference(pref);
} }
bindPreference(item, pref); bindPreference(item, pref);
} }
for (SwitchPreference unusedCacheItem : preferenceCache.values()) { for (FilterTouchesSwitchPreference unusedCacheItem : preferenceCache.values()) {
mPreferenceGroup.removePreference(unusedCacheItem); mPreferenceGroup.removePreference(unusedCacheItem);
} }
} }
private void bindPreference(DeviceAdminListItem item, SwitchPreference pref) { private void bindPreference(DeviceAdminListItem item, FilterTouchesSwitchPreference pref) {
pref.setKey(item.getKey()); pref.setKey(item.getKey());
pref.setTitle(item.getName()); pref.setTitle(item.getName());
pref.setIcon(item.getIcon()); pref.setIcon(item.getIcon());

View File

@@ -29,4 +29,8 @@ public interface AwareFeatureProvider {
/** Show information dialog. */ /** Show information dialog. */
void showRestrictionDialog(Fragment parent); void showRestrictionDialog(Fragment parent);
/** Return Quick Gestures Summary. */
CharSequence getGestureSummary(Context context, boolean sensorSupported,
boolean assistGestureEnabled, boolean assistGestureSilenceEnabled);
} }

View File

@@ -34,4 +34,10 @@ public class AwareFeatureProviderImpl implements AwareFeatureProvider {
@Override @Override
public void showRestrictionDialog(Fragment parent) { public void showRestrictionDialog(Fragment parent) {
} }
@Override
public CharSequence getGestureSummary(Context context, boolean sensorSupported,
boolean assistGestureEnabled, boolean assistGestureSilenceEnabled) {
return null;
}
} }

View File

@@ -125,5 +125,9 @@ public class DashboardFragmentRegistry {
for (Map.Entry<String, String> parentToKey : PARENT_TO_CATEGORY_KEY_MAP.entrySet()) { for (Map.Entry<String, String> parentToKey : PARENT_TO_CATEGORY_KEY_MAP.entrySet()) {
CATEGORY_KEY_TO_PARENT_MAP.put(parentToKey.getValue(), parentToKey.getKey()); CATEGORY_KEY_TO_PARENT_MAP.put(parentToKey.getValue(), parentToKey.getKey());
} }
// For injection index, redirect CATEGORY_ACCOUNT_DETAIL to AccountDashboardFragment.
CATEGORY_KEY_TO_PARENT_MAP.put(CategoryKey.CATEGORY_ACCOUNT_DETAIL,
AccountDashboardFragment.class.getName());
} }
} }

View File

@@ -20,10 +20,12 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.hardware.display.AmbientDisplayConfiguration; import android.hardware.display.AmbientDisplayConfiguration;
import android.provider.Settings; import android.provider.Settings;
import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.aware.AwareFeatureProvider;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory; import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
@@ -33,6 +35,7 @@ import java.util.List;
public class GesturesSettingPreferenceController extends BasePreferenceController { public class GesturesSettingPreferenceController extends BasePreferenceController {
private final AssistGestureFeatureProvider mFeatureProvider; private final AssistGestureFeatureProvider mFeatureProvider;
private final AwareFeatureProvider mAwareFeatureProvider;
private List<AbstractPreferenceController> mGestureControllers; private List<AbstractPreferenceController> mGestureControllers;
private static final String KEY_GESTURES_SETTINGS = "gesture_settings"; private static final String KEY_GESTURES_SETTINGS = "gesture_settings";
@@ -41,6 +44,7 @@ public class GesturesSettingPreferenceController extends BasePreferenceControlle
public GesturesSettingPreferenceController(Context context) { public GesturesSettingPreferenceController(Context context) {
super(context, KEY_GESTURES_SETTINGS); super(context, KEY_GESTURES_SETTINGS);
mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider(); mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider();
mAwareFeatureProvider = FeatureFactory.getFactory(context).getAwareFeatureProvider();
} }
@Override @Override
@@ -90,8 +94,15 @@ public class GesturesSettingPreferenceController extends BasePreferenceControlle
contentResolver, Settings.Secure.ASSIST_GESTURE_ENABLED, 1) != 0; contentResolver, Settings.Secure.ASSIST_GESTURE_ENABLED, 1) != 0;
final boolean assistGestureSilenceEnabled = Settings.Secure.getInt( final boolean assistGestureSilenceEnabled = Settings.Secure.getInt(
contentResolver, Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, 1) != 0; contentResolver, Settings.Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, 1) != 0;
final boolean sensorSupported = mFeatureProvider.isSupported(mContext);
if (mFeatureProvider.isSupported(mContext) && assistGestureEnabled) { final CharSequence awareSummary = mAwareFeatureProvider.getGestureSummary(mContext,
sensorSupported, assistGestureEnabled, assistGestureSilenceEnabled);
if (!TextUtils.isEmpty(awareSummary)) {
return awareSummary;
}
if (sensorSupported && assistGestureEnabled) {
return mContext.getText( return mContext.getText(
R.string.language_input_gesture_summary_on_with_assist); R.string.language_input_gesture_summary_on_with_assist);
} }

View File

@@ -176,9 +176,13 @@ public class MediaDeviceUpdateWorker extends SliceBackgroundWorker
return mLocalMediaManager.getSelectedMediaDevice(); return mLocalMediaManager.getSelectedMediaDevice();
} }
boolean isSelectedMediaDevice(MediaDevice device) { List<MediaDevice> getDeselectableMediaDevice() {
for (MediaDevice selectedMediaDevice : getSelectedMediaDevice()) { return mLocalMediaManager.getDeselectableMediaDevice();
if (TextUtils.equals(selectedMediaDevice.getId(), device.getId())) { }
boolean isDeviceIncluded(Collection<MediaDevice> deviceCollection, MediaDevice targetDevice) {
for (MediaDevice device : deviceCollection) {
if (TextUtils.equals(device.getId(), targetDevice.getId())) {
return true; return true;
} }
} }

View File

@@ -43,6 +43,7 @@ import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBroadcastReceiver; import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settingslib.media.MediaDevice; import com.android.settingslib.media.MediaDevice;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@@ -122,6 +123,10 @@ public class MediaOutputGroupSlice implements CustomSliceable {
private void addRow(ListBuilder listBuilder, List<MediaDevice> mediaDevices, boolean selected) { private void addRow(ListBuilder listBuilder, List<MediaDevice> mediaDevices, boolean selected) {
final boolean adjustVolumeUserRestriction = getWorker().hasAdjustVolumeUserRestriction(); final boolean adjustVolumeUserRestriction = getWorker().hasAdjustVolumeUserRestriction();
List<MediaDevice> deselectableMediaDevices = new ArrayList<>();
if (selected) {
deselectableMediaDevices = getWorker().getDeselectableMediaDevice();
}
for (MediaDevice device : mediaDevices) { for (MediaDevice device : mediaDevices) {
final int maxVolume = device.getMaxVolume(); final int maxVolume = device.getMaxVolume();
final IconCompat titleIcon = Utils.createIconWithDrawable(device.getIcon()); final IconCompat titleIcon = Utils.createIconWithDrawable(device.getIcon());
@@ -147,7 +152,8 @@ public class MediaOutputGroupSlice implements CustomSliceable {
.setMax(device.getMaxVolume()) .setMax(device.getMaxVolume())
.setValue(device.getCurrentVolume()); .setValue(device.getCurrentVolume());
// Add endItem with different icons // Add endItem with different icons
if (mediaDevices.size() == 1 && selected) { if (selected && (!getWorker().isDeviceIncluded(deselectableMediaDevices, device)
|| mediaDevices.size() == 1)) {
builder.addEndItem(disabledIconSliceAction); builder.addEndItem(disabledIconSliceAction);
} else { } else {
builder.addEndItem(enabledIconSliceAction); builder.addEndItem(enabledIconSliceAction);
@@ -158,7 +164,8 @@ public class MediaOutputGroupSlice implements CustomSliceable {
.setTitleItem(titleIcon, ListBuilder.ICON_IMAGE) .setTitleItem(titleIcon, ListBuilder.ICON_IMAGE)
.setTitle(title); .setTitle(title);
// Add endItem with different icons // Add endItem with different icons
if (mediaDevices.size() == 1 && selected) { if (selected && (!getWorker().isDeviceIncluded(deselectableMediaDevices, device)
|| mediaDevices.size() == 1)) {
rowBuilder.addEndItem(disabledIconSliceAction); rowBuilder.addEndItem(disabledIconSliceAction);
} else { } else {
rowBuilder.addEndItem(enabledIconSliceAction); rowBuilder.addEndItem(enabledIconSliceAction);
@@ -209,7 +216,8 @@ public class MediaOutputGroupSlice implements CustomSliceable {
Log.e(TAG, "Unable to handle notification. The device is unavailable"); Log.e(TAG, "Unable to handle notification. The device is unavailable");
return; return;
} }
final MediaDevice device = getWorker().getMediaDeviceById(id); final MediaDeviceUpdateWorker worker = getWorker();
final MediaDevice device = worker.getMediaDeviceById(id);
switch (intent.getIntExtra(CUSTOMIZED_ACTION, ERROR)) { switch (intent.getIntExtra(CUSTOMIZED_ACTION, ERROR)) {
case ACTION_VOLUME_ADJUSTMENT: case ACTION_VOLUME_ADJUSTMENT:
final int newPosition = intent.getIntExtra(EXTRA_RANGE_VALUE, ERROR); final int newPosition = intent.getIntExtra(EXTRA_RANGE_VALUE, ERROR);
@@ -219,7 +227,7 @@ public class MediaOutputGroupSlice implements CustomSliceable {
} }
// Group volume adjustment // Group volume adjustment
if (TextUtils.equals(id, GROUP_DEVICES)) { if (TextUtils.equals(id, GROUP_DEVICES)) {
getWorker().adjustSessionVolume(newPosition); worker.adjustSessionVolume(newPosition);
} else { } else {
if (device == null) { if (device == null) {
Log.e(TAG, "Unable to adjust volume. The device(" + id Log.e(TAG, "Unable to adjust volume. The device(" + id
@@ -227,7 +235,7 @@ public class MediaOutputGroupSlice implements CustomSliceable {
return; return;
} }
// Single device volume adjustment // Single device volume adjustment
getWorker().adjustVolume(device, newPosition); worker.adjustVolume(device, newPosition);
} }
break; break;
case ACTION_MEDIA_SESSION_OPERATION: case ACTION_MEDIA_SESSION_OPERATION:
@@ -236,10 +244,13 @@ public class MediaOutputGroupSlice implements CustomSliceable {
+ ") is unavailable"); + ") is unavailable");
return; return;
} }
if (getWorker().isSelectedMediaDevice(device)) { if (worker.isDeviceIncluded(worker.getSelectableMediaDevice(), device)) {
getWorker().removeDeviceFromPlayMedia(device); worker.addDeviceToPlayMedia(device);
} else if (worker.isDeviceIncluded(worker.getDeselectableMediaDevice(), device)) {
worker.removeDeviceFromPlayMedia(device);
} else { } else {
getWorker().addDeviceToPlayMedia(device); // Do nothing
Log.d(TAG, device.getName() + " is not selectable nor deselectable");
} }
break; break;
} }

View File

@@ -75,13 +75,14 @@ public class MobileNetworkSwitchController extends BasePreferenceController impl
mSwitchBar.setSwitchBarText(R.string.mobile_network_use_sim_on, mSwitchBar.setSwitchBarText(R.string.mobile_network_use_sim_on,
R.string.mobile_network_use_sim_off); R.string.mobile_network_use_sim_off);
mSwitchBar.addOnSwitchChangeListener((switchView, isChecked) -> { mSwitchBar.getSwitch().setOnBeforeCheckedChangeListener((toggleSwitch, isChecked) -> {
// TODO b/135222940: re-evaluate whether to use // TODO b/135222940: re-evaluate whether to use
// mSubscriptionManager#isSubscriptionEnabled // mSubscriptionManager#isSubscriptionEnabled
if (mSubscriptionManager.isActiveSubscriptionId(mSubId) != isChecked if (mSubscriptionManager.isActiveSubscriptionId(mSubId) != isChecked
&& (!mSubscriptionManager.setSubscriptionEnabled(mSubId, isChecked))) { && (!mSubscriptionManager.setSubscriptionEnabled(mSubId, isChecked))) {
mSwitchBar.setChecked(!isChecked); return true;
} }
return false;
}); });
update(); update();
} }
@@ -106,7 +107,7 @@ public class MobileNetworkSwitchController extends BasePreferenceController impl
mSwitchBar.hide(); mSwitchBar.hide();
} else { } else {
mSwitchBar.show(); mSwitchBar.show();
mSwitchBar.setChecked(mSubscriptionManager.isActiveSubscriptionId(mSubId)); mSwitchBar.setCheckedInternal(mSubscriptionManager.isActiveSubscriptionId(mSubId));
} }
} }

View File

@@ -140,7 +140,15 @@ public class NotificationHistoryActivity extends Activity {
final NotificationHistoryRecyclerView rv = final NotificationHistoryRecyclerView rv =
viewForPackage.findViewById(R.id.notification_list); viewForPackage.findViewById(R.id.notification_list);
rv.setAdapter(new NotificationHistoryAdapter(mNm, rv)); rv.setAdapter(new NotificationHistoryAdapter(mNm, rv,
newCount -> {
count.setText(getResources().getQuantityString(
R.plurals.notification_history_count,
newCount, newCount));
if (newCount == 0) {
viewForPackage.setVisibility(View.GONE);
}
}));
((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete( ((NotificationHistoryAdapter) rv.getAdapter()).onRebuildComplete(
new ArrayList<>(nhp.notifications)); new ArrayList<>(nhp.notifications));

View File

@@ -49,13 +49,16 @@ public class NotificationHistoryAdapter extends
private INotificationManager mNm; private INotificationManager mNm;
private List<HistoricalNotification> mValues; private List<HistoricalNotification> mValues;
private OnItemDeletedListener mListener;
public NotificationHistoryAdapter(INotificationManager nm, public NotificationHistoryAdapter(INotificationManager nm,
NotificationHistoryRecyclerView listView) { NotificationHistoryRecyclerView listView,
OnItemDeletedListener listener) {
mValues = new ArrayList<>(); mValues = new ArrayList<>();
setHasStableIds(true); setHasStableIds(true);
listView.setOnItemSwipeDeleteListener(this); listView.setOnItemSwipeDeleteListener(this);
mNm = nm; mNm = nm;
mListener = listener;
} }
@Override @Override
@@ -134,6 +137,11 @@ public class NotificationHistoryAdapter extends
Slog.e(TAG, "Failed to delete item", e); Slog.e(TAG, "Failed to delete item", e);
} }
} }
mListener.onItemDeleted(mValues.size());
notifyItemRemoved(position); notifyItemRemoved(position);
} }
interface OnItemDeletedListener {
void onItemDeleted(int newCount);
}
} }

View File

@@ -20,12 +20,16 @@ import static android.app.Notification.COLOR_DEFAULT;
import static android.content.pm.PackageManager.MATCH_ANY_USER; import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.content.pm.PackageManager.NameNotFoundException; import static android.content.pm.PackageManager.NameNotFoundException;
import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_ALL;
import static android.provider.Settings.EXTRA_APP_PACKAGE;
import static android.provider.Settings.EXTRA_CHANNEL_ID;
import static android.provider.Settings.EXTRA_CONVERSATION_ID;
import android.annotation.ColorInt; import android.annotation.ColorInt;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.app.Notification; import android.app.Notification;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Configuration; import android.content.res.Configuration;
@@ -33,6 +37,7 @@ import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -113,6 +118,15 @@ public class NotificationSbnAdapter extends
holder.setProfileBadge(mUserBadgeCache.get(userId)); holder.setProfileBadge(mUserBadgeCache.get(userId));
holder.addOnClick(sbn.getPackageName(), sbn.getUserId(), holder.addOnClick(sbn.getPackageName(), sbn.getUserId(),
sbn.getNotification().contentIntent); sbn.getNotification().contentIntent);
holder.itemView.setOnLongClickListener(v -> {
Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS)
.putExtra(EXTRA_APP_PACKAGE, sbn.getPackageName())
.putExtra(EXTRA_CHANNEL_ID, sbn.getNotification().getChannelId())
.putExtra(EXTRA_CONVERSATION_ID, sbn.getNotification().getShortcutId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
holder.itemView.getContext().startActivityAsUser(intent, UserHandle.of(userId));
return true;
});
} else { } else {
Slog.w(TAG, "null entry in list at position " + position); Slog.w(TAG, "null entry in list at position " + position);
} }

View File

@@ -107,6 +107,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
private int mUserId; private int mUserId;
private int mCredentialMode; private int mCredentialMode;
private boolean mGoingToBackground; private boolean mGoingToBackground;
private boolean mWaitingForBiometricCallback;
private Executor mExecutor = (runnable -> { private Executor mExecutor = (runnable -> {
mHandler.post(runnable); mHandler.post(runnable);
@@ -116,6 +117,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
@Override @Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) { public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
if (!mGoingToBackground) { if (!mGoingToBackground) {
mWaitingForBiometricCallback = false;
if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED if (errorCode == BiometricPrompt.BIOMETRIC_ERROR_USER_CANCELED
|| errorCode == BiometricPrompt.BIOMETRIC_ERROR_CANCELED) { || errorCode == BiometricPrompt.BIOMETRIC_ERROR_CANCELED) {
finish(); finish();
@@ -123,11 +125,15 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
// All other errors go to some version of CC // All other errors go to some version of CC
showConfirmCredentials(); showConfirmCredentials();
} }
} else if (mWaitingForBiometricCallback) { // mGoingToBackground is true
mWaitingForBiometricCallback = false;
finish();
} }
} }
@Override @Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) { public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
mWaitingForBiometricCallback = false;
mTrustManager.setDeviceLockedForUser(mUserId, false); mTrustManager.setDeviceLockedForUser(mUserId, false);
final boolean isStrongAuth = result.getAuthenticationType() final boolean isStrongAuth = result.getAuthenticationType()
== BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL; == BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL;
@@ -142,6 +148,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
@Override @Override
public void onAuthenticationFailed() { public void onAuthenticationFailed() {
mWaitingForBiometricCallback = false;
mDevicePolicyManager.reportFailedBiometricAttempt(mUserId); mDevicePolicyManager.reportFailedBiometricAttempt(mUserId);
} }
@@ -262,6 +269,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
finish(); finish();
} else if (launchedBiometric) { } else if (launchedBiometric) {
// Keep this activity alive until BiometricPrompt goes away // Keep this activity alive until BiometricPrompt goes away
mWaitingForBiometricCallback = true;
} else { } else {
Log.d(TAG, "No pattern, password or PIN set."); Log.d(TAG, "No pattern, password or PIN set.");
setResult(Activity.RESULT_OK); setResult(Activity.RESULT_OK);
@@ -320,7 +328,9 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
super.onPause(); super.onPause();
if (!isChangingConfigurations()) { if (!isChangingConfigurations()) {
mGoingToBackground = true; mGoingToBackground = true;
finish(); if (!mWaitingForBiometricCallback) {
finish();
}
} else { } else {
mGoingToBackground = false; mGoingToBackground = false;
} }

View File

@@ -52,8 +52,6 @@ public class MultiUserSwitchBarController implements SwitchWidgetController.OnSw
mListener = listener; mListener = listener;
mUserCapabilities = UserCapabilities.create(context); mUserCapabilities = UserCapabilities.create(context);
mSwitchBar.setChecked(mUserCapabilities.mUserSwitcherEnabled); mSwitchBar.setChecked(mUserCapabilities.mUserSwitcherEnabled);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.USER_SWITCHER_ENABLED, mSwitchBar.isChecked() ? 1 : 0);
if (mUserCapabilities.mDisallowSwitchUser) { if (mUserCapabilities.mDisallowSwitchUser) {
mSwitchBar.setDisabledByAdmin(RestrictedLockUtilsInternal mSwitchBar.setDisabledByAdmin(RestrictedLockUtilsInternal

View File

@@ -20,6 +20,7 @@ import static com.android.internal.net.VpnProfile.isLegacyType;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.net.Proxy; import android.net.Proxy;
import android.net.ProxyInfo; import android.net.ProxyInfo;
import android.os.Bundle; import android.os.Bundle;
@@ -43,6 +44,9 @@ import com.android.internal.net.VpnProfile;
import com.android.settings.R; import com.android.settings.R;
import java.net.InetAddress; import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** /**
* Dialog showing information about a VPN configuration. The dialog * Dialog showing information about a VPN configuration. The dialog
@@ -129,6 +133,7 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
// Second, copy values from the profile. // Second, copy values from the profile.
mName.setText(mProfile.name); mName.setText(mProfile.name);
setTypesByFeature(mType);
mType.setSelection(mProfile.type); mType.setSelection(mProfile.type);
mServer.setText(mProfile.server); mServer.setText(mProfile.server);
if (mProfile.saveLogin) { if (mProfile.saveLogin) {
@@ -487,6 +492,25 @@ class ConfigDialog extends AlertDialog implements TextWatcher,
return true; return true;
} }
private void setTypesByFeature(Spinner typeSpinner) {
String[] types = getContext().getResources().getStringArray(R.array.vpn_types);
if (!getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_IPSEC_TUNNELS)) {
final List<String> typesList = new ArrayList<>(Arrays.asList(types));
// This must be removed from back to front in order to ensure index consistency
typesList.remove(VpnProfile.TYPE_IKEV2_IPSEC_RSA);
typesList.remove(VpnProfile.TYPE_IKEV2_IPSEC_PSK);
typesList.remove(VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS);
types = typesList.toArray(new String[0]);
}
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
getContext(), android.R.layout.simple_spinner_item, types);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
typeSpinner.setAdapter(adapter);
}
private void loadCertificates(Spinner spinner, String prefix, int firstId, String selected) { private void loadCertificates(Spinner spinner, String prefix, int firstId, String selected) {
Context context = getContext(); Context context = getContext();
String first = (firstId == 0) ? "" : context.getString(firstId); String first = (firstId == 0) ? "" : context.getString(firstId);

View File

@@ -17,7 +17,9 @@
package com.android.settings.widget; package com.android.settings.widget;
import android.content.Context; import android.content.Context;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference; import androidx.preference.SwitchPreference;
import com.android.settings.R; import com.android.settings.R;
@@ -28,4 +30,13 @@ public class AppSwitchPreference extends SwitchPreference {
super(context); super(context);
setLayoutResource(R.layout.preference_app); setLayoutResource(R.layout.preference_app);
} }
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final View switchView = holder.findViewById(android.R.id.switch_widget);
if (switchView != null) {
switchView.setFilterTouchesWhenObscured(true);
}
}
} }

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2020 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.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
import com.android.settingslib.RestrictedSwitchPreference;
/**
* This widget with enabled filterTouchesWhenObscured attribute use to replace
* the {@link RestrictedSwitchPreference} in the Special access app pages for
* security.
*/
public class FilterTouchesRestrictedSwitchPreference extends RestrictedSwitchPreference {
public FilterTouchesRestrictedSwitchPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FilterTouchesRestrictedSwitchPreference(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FilterTouchesRestrictedSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FilterTouchesRestrictedSwitchPreference(Context context) {
super(context);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final View switchView = holder.findViewById(android.R.id.switch_widget);
if (switchView != null) {
switchView.setFilterTouchesWhenObscured(true);
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2020 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.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
import androidx.preference.SwitchPreference;
/**
* This widget with enabled filterTouchesWhenObscured attribute use to replace
* the {@link SwitchPreference} in the Special access app pages for security.
*/
public class FilterTouchesSwitchPreference extends SwitchPreference {
public FilterTouchesSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public FilterTouchesSwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public FilterTouchesSwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FilterTouchesSwitchPreference(Context context) {
super(context);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
final View switchView = holder.findViewById(android.R.id.switch_widget);
if (switchView != null) {
switchView.setFilterTouchesWhenObscured(true);
}
}
}

View File

@@ -18,6 +18,9 @@ package com.android.settings.dashboard;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settingslib.drawer.CategoryKey;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
@@ -29,4 +32,12 @@ public class DashboardFragmentRegistryTest {
assertThat(DashboardFragmentRegistry.CATEGORY_KEY_TO_PARENT_MAP.size()) assertThat(DashboardFragmentRegistry.CATEGORY_KEY_TO_PARENT_MAP.size())
.isEqualTo(DashboardFragmentRegistry.PARENT_TO_CATEGORY_KEY_MAP.size()); .isEqualTo(DashboardFragmentRegistry.PARENT_TO_CATEGORY_KEY_MAP.size());
} }
@Test
public void accountDetailCategoryShouldRedirectToAccountDashboardFragment() {
final String fragment = DashboardFragmentRegistry.CATEGORY_KEY_TO_PARENT_MAP.get(
CategoryKey.CATEGORY_ACCOUNT_DETAIL);
assertThat(fragment).isEqualTo(AccountDashboardFragment.class.getName());
}
} }

View File

@@ -90,6 +90,7 @@ public class MediaOutputGroupSliceTest {
private final List<MediaDevice> mSelectableDevices = new ArrayList<>(); private final List<MediaDevice> mSelectableDevices = new ArrayList<>();
private final List<MediaDevice> mSelectedDevices = new ArrayList<>(); private final List<MediaDevice> mSelectedDevices = new ArrayList<>();
private final List<MediaDevice> mDeselectableDevices = new ArrayList<>();
private Context mContext; private Context mContext;
private MediaOutputGroupSlice mMediaOutputGroupSlice; private MediaOutputGroupSlice mMediaOutputGroupSlice;
@@ -227,14 +228,19 @@ public class MediaOutputGroupSliceTest {
verify(sMediaDeviceUpdateWorker).addDeviceToPlayMedia(mDevice2); verify(sMediaDeviceUpdateWorker).addDeviceToPlayMedia(mDevice2);
} }
@Test @Test
public void onNotifyChange_sendSelectedDevice_verifyRemoveSession() { public void onNotifyChange_sendDeselectableDevice_verifyRemoveSession() {
mSelectedDevices.add(mDevice1); mSelectedDevices.add(mDevice1);
mSelectedDevices.add(mDevice2); mSelectedDevices.add(mDevice2);
mDeselectableDevices.add(mDevice1);
mDeselectableDevices.add(mDevice2);
when(mLocalMediaManager.getMediaDeviceById(mSelectedDevices, TEST_DEVICE_2_ID)) when(mLocalMediaManager.getMediaDeviceById(mSelectedDevices, TEST_DEVICE_2_ID))
.thenReturn(mDevice2); .thenReturn(mDevice2);
sMediaDeviceUpdateWorker.onDeviceListUpdate(mSelectedDevices); sMediaDeviceUpdateWorker.onDeviceListUpdate(mSelectedDevices);
when(sMediaDeviceUpdateWorker.getSelectedMediaDevice()).thenReturn(mSelectedDevices); when(sMediaDeviceUpdateWorker.getSelectedMediaDevice()).thenReturn(mSelectedDevices);
when(sMediaDeviceUpdateWorker.getDeselectableMediaDevice()).thenReturn(
mDeselectableDevices);
final Intent intent = new Intent(); final Intent intent = new Intent();
intent.putExtra(MEDIA_DEVICE_ID, TEST_DEVICE_2_ID); intent.putExtra(MEDIA_DEVICE_ID, TEST_DEVICE_2_ID);
intent.putExtra(CUSTOMIZED_ACTION, ACTION_MEDIA_SESSION_OPERATION); intent.putExtra(CUSTOMIZED_ACTION, ACTION_MEDIA_SESSION_OPERATION);
@@ -244,6 +250,26 @@ public class MediaOutputGroupSliceTest {
verify(sMediaDeviceUpdateWorker).removeDeviceFromPlayMedia(mDevice2); verify(sMediaDeviceUpdateWorker).removeDeviceFromPlayMedia(mDevice2);
} }
@Test
public void onNotifyChange_sendNonDeselectableDevice_notRemoveSession() {
mSelectedDevices.add(mDevice1);
mSelectedDevices.add(mDevice2);
mDeselectableDevices.add(mDevice1);
when(mLocalMediaManager.getMediaDeviceById(mSelectedDevices, TEST_DEVICE_2_ID))
.thenReturn(mDevice2);
sMediaDeviceUpdateWorker.onDeviceListUpdate(mSelectedDevices);
when(sMediaDeviceUpdateWorker.getSelectedMediaDevice()).thenReturn(mSelectedDevices);
when(sMediaDeviceUpdateWorker.getDeselectableMediaDevice()).thenReturn(
mDeselectableDevices);
final Intent intent = new Intent();
intent.putExtra(MEDIA_DEVICE_ID, TEST_DEVICE_2_ID);
intent.putExtra(CUSTOMIZED_ACTION, ACTION_MEDIA_SESSION_OPERATION);
mMediaOutputGroupSlice.onNotifyChange(intent);
verify(sMediaDeviceUpdateWorker, never()).removeDeviceFromPlayMedia(mDevice2);
}
@Test @Test
public void onNotifyChange_noId_doNothing() { public void onNotifyChange_noId_doNothing() {
mSelectableDevices.add(mDevice1); mSelectableDevices.add(mDevice1);