From 7b0f887000f34ec43cd5189258aa7028804f4081 Mon Sep 17 00:00:00 2001 From: Tim Peng Date: Wed, 24 Apr 2019 10:47:31 +0800 Subject: [PATCH 1/9] Update "Play media to" display rule in SoundSetting - show under Casting mode - hide under no connected Bluetooth devices - update test case Bug: 131143025 Test: make -j42 RunSettingsRoboTests Change-Id: I0eac856970043ecd9a1975fbe382241078ece924 --- .../AudioSwitchPreferenceController.java | 80 +------------------ .../MediaOutputPreferenceController.java | 24 ++---- .../MediaOutputPreferenceControllerTest.java | 64 ++++++--------- 3 files changed, 33 insertions(+), 135 deletions(-) diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java index 0da0f2142d5..5b70d16a7a7 100644 --- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java +++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java @@ -17,7 +17,6 @@ package com.android.settings.sound; import static android.media.AudioManager.STREAM_DEVICES_CHANGED_ACTION; -import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; @@ -29,7 +28,6 @@ import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; import android.media.AudioManager; import android.media.MediaRouter; -import android.media.MediaRouter.Callback; import android.os.Handler; import android.os.Looper; import android.util.FeatureFlagUtils; @@ -76,7 +74,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont protected AudioSwitchCallback mAudioSwitchPreferenceCallback; private final AudioManagerAudioDeviceCallback mAudioManagerAudioDeviceCallback; - private final MediaRouterCallback mMediaRouterCallback; private final WiredHeadsetBroadcastReceiver mReceiver; private final Handler mHandler; private LocalBluetoothManager mLocalBluetoothManager; @@ -92,7 +89,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont mHandler = new Handler(Looper.getMainLooper()); mAudioManagerAudioDeviceCallback = new AudioManagerAudioDeviceCallback(); mReceiver = new WiredHeadsetBroadcastReceiver(); - mMediaRouterCallback = new MediaRouterCallback(); mConnectedDevices = new ArrayList<>(); final FutureTask localBtManagerFutureTask = new FutureTask<>( // Avoid StrictMode ThreadPolicy violation @@ -210,12 +206,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont * get A2dp devices on all states * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) */ - protected List getConnectableA2dpDevices() { + protected List getConnectedA2dpDevices() { final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile(); if (a2dpProfile == null) { return new ArrayList<>(); } - return a2dpProfile.getConnectableDevices(); + return a2dpProfile.getConnectedDevices(); } /** @@ -241,31 +237,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont return connectedDevices; } - /** - * get hearing aid profile devices on all states - * (STATE_DISCONNECTED, STATE_CONNECTING, STATE_CONNECTED, STATE_DISCONNECTING) - * exclude other devices with same hiSyncId. - */ - protected List getConnectableHearingAidDevices() { - final List connectedDevices = new ArrayList<>(); - final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile(); - if (hapProfile == null) { - return connectedDevices; - } - final List devicesHiSyncIds = new ArrayList<>(); - final List devices = hapProfile.getConnectableDevices(); - for (BluetoothDevice device : devices) { - final long hiSyncId = hapProfile.getHiSyncId(device); - // device with same hiSyncId should not be shown in the UI. - // So do not add it into connectedDevices. - if (!devicesHiSyncIds.contains(hiSyncId)) { - devicesHiSyncIds.add(hiSyncId); - connectedDevices.add(device); - } - } - return connectedDevices; - } - /** * Find active hearing aid device */ @@ -299,7 +270,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont private void register() { mLocalBluetoothManager.getEventManager().registerCallback(this); mAudioManager.registerAudioDeviceCallback(mAudioManagerAudioDeviceCallback, mHandler); - mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback); // Register for misc other intent broadcasts. IntentFilter intentFilter = new IntentFilter(Intent.ACTION_HEADSET_PLUG); @@ -310,7 +280,6 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont private void unregister() { mLocalBluetoothManager.getEventManager().unregisterCallback(this); mAudioManager.unregisterAudioDeviceCallback(mAudioManagerAudioDeviceCallback); - mMediaRouter.removeCallback(mMediaRouterCallback); mContext.unregisterReceiver(mReceiver); } @@ -338,49 +307,4 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont } } } - - /** Callback for cast device events. */ - private class MediaRouterCallback extends Callback { - @Override - public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) { - } - - @Override - public void onRouteUnselected(MediaRouter router, int type, MediaRouter.RouteInfo info) { - } - - @Override - public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo info) { - if (info != null && !info.isDefault()) { - // cast mode - updateState(mPreference); - } - } - - @Override - public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo info) { - } - - @Override - public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo info) { - if (info != null && !info.isDefault()) { - // cast mode - updateState(mPreference); - } - } - - @Override - public void onRouteGrouped(MediaRouter router, MediaRouter.RouteInfo info, - MediaRouter.RouteGroup group, int index) { - } - - @Override - public void onRouteUngrouped(MediaRouter router, MediaRouter.RouteInfo info, - MediaRouter.RouteGroup group) { - } - - @Override - public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo info) { - } - } } diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java index 47810f7db3b..1831ad6d70f 100644 --- a/src/com/android/settings/sound/MediaOutputPreferenceController.java +++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java @@ -16,9 +16,6 @@ package com.android.settings.sound; -import static android.media.AudioManager.STREAM_MUSIC; -import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX; - import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; @@ -56,13 +53,6 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro return; } - if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_REMOTE_SUBMIX)) { - // In cast mode, disable switch entry. - mPreference.setVisible(false); - preference.setSummary(mContext.getText(R.string.media_output_summary_unavailable)); - return; - } - if (Utils.isAudioModeOngoingCall(mContext)) { // Ongoing call status, switch entry for media will be disabled. mPreference.setVisible(false); @@ -71,19 +61,19 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro return; } - boolean deviceConnectable = false; + boolean deviceConnected = false; BluetoothDevice activeDevice = null; // Show preference if there is connected or previously connected device // Find active device and set its name as the preference's summary - List connectableA2dpDevices = getConnectableA2dpDevices(); - List connectableHADevices = getConnectableHearingAidDevices(); + List connectedA2dpDevices = getConnectedA2dpDevices(); + List connectedHADevices = getConnectedHearingAidDevices(); if (mAudioManager.getMode() == AudioManager.MODE_NORMAL - && ((connectableA2dpDevices != null && !connectableA2dpDevices.isEmpty()) - || (connectableHADevices != null && !connectableHADevices.isEmpty()))) { - deviceConnectable = true; + && ((connectedA2dpDevices != null && !connectedA2dpDevices.isEmpty()) + || (connectedHADevices != null && !connectedHADevices.isEmpty()))) { + deviceConnected = true; activeDevice = findActiveDevice(); } - mPreference.setVisible(deviceConnectable); + mPreference.setVisible(deviceConnected); mPreference.setSummary((activeDevice == null) ? mContext.getText(R.string.media_output_default_summary) : activeDevice.getAliasName()); diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java index 7fcd3d2986d..51264c17f2c 100644 --- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java @@ -109,7 +109,7 @@ public class MediaOutputPreferenceControllerTest { private BluetoothDevice mRightBluetoothHapDevice; private LocalBluetoothManager mLocalBluetoothManager; private MediaOutputPreferenceController mController; - private List mProfileConnectableDevices; + private List mProfileConnectedDevices; private List mHearingAidActiveDevices; @Before @@ -150,7 +150,7 @@ public class MediaOutputPreferenceControllerTest { mController = new MediaOutputPreferenceController(mContext, TEST_KEY); mScreen = spy(new PreferenceScreen(mContext, null)); mPreference = new Preference(mContext); - mProfileConnectableDevices = new ArrayList<>(); + mProfileConnectedDevices = new ArrayList<>(); mHearingAidActiveDevices = new ArrayList<>(2); when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class)); @@ -172,11 +172,11 @@ public class MediaOutputPreferenceControllerTest { * Preference should be invisible */ @Test - public void updateState_withoutConnectableBtDevice_preferenceInvisible() { + public void updateState_withoutConnectedBtDevice_preferenceInvisible() { mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE); mAudioManager.setMode(AudioManager.MODE_NORMAL); - mProfileConnectableDevices.clear(); - when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + mProfileConnectedDevices.clear(); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); mPreference.setVisible(true); assertThat(mPreference.isVisible()).isTrue(); @@ -185,16 +185,16 @@ public class MediaOutputPreferenceControllerTest { } /** - * A2DP Bluetooth device(s) are connectable, no matter active or inactive + * A2DP Bluetooth device(s) are connected, no matter active or inactive * Preference should be visible */ @Test - public void updateState_withConnectableBtDevice_preferenceVisible() { + public void updateState_withConnectedBtDevice_preferenceVisible() { mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); mAudioManager.setMode(AudioManager.MODE_NORMAL); - mProfileConnectableDevices.clear(); - mProfileConnectableDevices.add(mBluetoothDevice); - when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); assertThat(mPreference.isVisible()).isFalse(); // Without Active Bluetooth Device @@ -208,17 +208,17 @@ public class MediaOutputPreferenceControllerTest { } /** - * A2DP Bluetooth device(s) are connectable, but no device is set as activated + * A2DP Bluetooth device(s) are connected, but no device is set as activated * Preference summary should be "This device" */ @Test - public void updateState_withConnectableBtDevice_withoutActiveBtDevice_setDefaultSummary() { + public void updateState_withConnectedBtDevice_withoutActiveBtDevice_setDefaultSummary() { mShadowAudioManager.setOutputDevice(DEVICE_OUT_EARPIECE); mAudioManager.setMode(AudioManager.MODE_NORMAL); - mProfileConnectableDevices.clear(); - mProfileConnectableDevices.add(mBluetoothDevice); - mProfileConnectableDevices.add(mSecondBluetoothDevice); - when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mSecondBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mA2dpProfile.getActiveDevice()).thenReturn(null); assertThat(mPreference.getSummary()).isNull(); @@ -235,10 +235,10 @@ public class MediaOutputPreferenceControllerTest { public void updateState_withActiveBtDevice_setActivatedDeviceName() { mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP); mAudioManager.setMode(AudioManager.MODE_NORMAL); - mProfileConnectableDevices.clear(); - mProfileConnectableDevices.add(mBluetoothDevice); - mProfileConnectableDevices.add(mSecondBluetoothDevice); - when(mA2dpProfile.getConnectableDevices()).thenReturn(mProfileConnectableDevices); + mProfileConnectedDevices.clear(); + mProfileConnectedDevices.add(mBluetoothDevice); + mProfileConnectedDevices.add(mSecondBluetoothDevice); + when(mA2dpProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices); when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice); assertThat(mPreference.getSummary()).isNull(); @@ -248,16 +248,16 @@ public class MediaOutputPreferenceControllerTest { /** - * Hearing Aid device(s) are connectable, no matter active or inactive + * Hearing Aid device(s) are connected, no matter active or inactive * Preference should be visible */ @Test - public void updateState_withConnectableHADevice_preferenceVisible() { + public void updateState_withConnectedHADevice_preferenceVisible() { mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID); mAudioManager.setMode(AudioManager.MODE_NORMAL); mHearingAidActiveDevices.clear(); mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); - when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mHearingAidActiveDevices); assertThat(mPreference.isVisible()).isFalse(); // Without Active Hearing Aid Device @@ -280,7 +280,7 @@ public class MediaOutputPreferenceControllerTest { mAudioManager.setMode(AudioManager.MODE_NORMAL); mHearingAidActiveDevices.clear(); mHearingAidActiveDevices.add(mLeftBluetoothHapDevice); - when(mHearingAidProfile.getConnectableDevices()).thenReturn(mHearingAidActiveDevices); + when(mHearingAidProfile.getConnectedDevices()).thenReturn(mHearingAidActiveDevices); when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices); assertThat(mPreference.getSummary()).isNull(); @@ -332,22 +332,6 @@ public class MediaOutputPreferenceControllerTest { mContext.getText(R.string.media_out_summary_ongoing_call_state)); } - /** - * Media stream is captured by something else (cast device): - * Preference should be invisible - * Preference summary should be "unavailable" - */ - @Test - public void updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary() { - mShadowAudioManager.setOutputDevice(DEVICE_OUT_REMOTE_SUBMIX); - - mController.updateState(mPreference); - - assertThat(mPreference.isVisible()).isFalse(); - String defaultString = mContext.getString(R.string.media_output_summary_unavailable); - assertThat(mPreference.getSummary()).isEqualTo(defaultString); - } - @Test public void findActiveDevice_onlyA2dpDeviceActive_returnA2dpDevice() { when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null); From 7dd82f966ccad9d94e405105e9f3df9daba29ffa Mon Sep 17 00:00:00 2001 From: Malcolm Chen Date: Thu, 18 Apr 2019 19:45:04 -0700 Subject: [PATCH 2/9] Create enable MMS notification. Adding a notification in SimSelectNotification that will be triggered when receiving a enable MMS request. Tapping on the notificaiton will lead to the subscription setting page. Bug: 130222866 Test: manual -- have a test app that sends the intent when mobile data is turned off. And verify that the heads-up notificaiton is shown and that it will lead to subscription setting page. Change-Id: Ia80e8e5ab20adf78a31647a23cb2ba8dac690e41 --- AndroidManifest.xml | 2 + .../settings/sim/SimSelectNotification.java | 148 ++++++++++++++-- src/com/android/settings/sim/SimSettings.java | 2 +- .../sim/SimSelectNotificationTest.java | 166 ++++++++++++++++++ 4 files changed, 300 insertions(+), 18 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 764e1d2e4d7..5af6a99c563 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -136,6 +136,7 @@ + @@ -2623,6 +2624,7 @@ + diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java index 3179e6a8028..911d0e84091 100644 --- a/src/com/android/settings/sim/SimSelectNotification.java +++ b/src/com/android/settings/sim/SimSelectNotification.java @@ -16,12 +16,18 @@ package com.android.settings.sim; +import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_MMS; +import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS; +import static android.provider.Settings.EXTRA_ENABLE_MMS_DATA_REQUEST_REASON; +import static android.provider.Settings.EXTRA_SUB_ID; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA; import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE; import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID; +import static android.telephony.data.ApnSetting.TYPE_MMS; +import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; @@ -32,28 +38,97 @@ import android.content.res.Resources; import android.provider.Settings; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; -import com.android.settings.Settings.SimSettingsActivity; - -import androidx.core.app.NotificationCompat; +import com.android.settings.network.telephony.MobileNetworkActivity; public class SimSelectNotification extends BroadcastReceiver { private static final String TAG = "SimSelectNotification"; - private static final int NOTIFICATION_ID = 1; + @VisibleForTesting + public static final int SIM_SELECT_NOTIFICATION_ID = 1; + @VisibleForTesting + public static final int ENABLE_MMS_NOTIFICATION_ID = 2; - private static final String SIM_SELECT_NOTIFICATION_CHANNEL = + @VisibleForTesting + public static final String SIM_SELECT_NOTIFICATION_CHANNEL = "sim_select_notification_channel"; + @VisibleForTesting + public static final String ENABLE_MMS_NOTIFICATION_CHANNEL = + "enable_mms_notification_channel"; + @Override public void onReceive(Context context, Intent intent) { - if (!TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED.equals(intent.getAction())) { + String action = intent.getAction(); + + if (action == null) { + Log.w(TAG, "Received unexpected intent with null action."); return; } + + switch (action) { + case TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED: + onPrimarySubscriptionListChanged(context, intent); + break; + case Settings.ACTION_ENABLE_MMS_DATA_REQUEST: + onEnableMmsDataRequest(context, intent); + break; + default: + Log.w(TAG, "Received unexpected intent " + intent.getAction()); + } + } + + private void onEnableMmsDataRequest(Context context, Intent intent) { + // Getting subId from extra. + int subId = intent.getIntExtra(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { + subId = SubscriptionManager.getDefaultSmsSubscriptionId(); + } + + SubscriptionManager subscriptionManager = ((SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE)); + if (!subscriptionManager.isActiveSubId(subId)) { + Log.w(TAG, "onEnableMmsDataRequest invalid sub ID " + subId); + return; + } + + // Getting request reason from extra, which will determine the notification title. + CharSequence notificationTitle = null; + int requestReason = intent.getIntExtra(EXTRA_ENABLE_MMS_DATA_REQUEST_REASON, -1); + if (requestReason == ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_MMS) { + notificationTitle = context.getResources().getText( + R.string.enable_receiving_mms_notification_title); + } else if (requestReason == ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS) { + notificationTitle = context.getResources().getText( + R.string.enable_sending_mms_notification_title); + } else { + Log.w(TAG, "onEnableMmsDataRequest invalid request reason " + requestReason); + return; + } + + TelephonyManager tm = ((TelephonyManager) context.getSystemService( + Context.TELEPHONY_SERVICE)).createForSubscriptionId(subId); + + if (tm.isDataEnabledForApn(TYPE_MMS)) { + Log.w(TAG, "onEnableMmsDataRequest MMS data already enabled on sub ID " + subId); + return; + } + + CharSequence notificationSummary = context.getResources().getString( + R.string.enable_mms_notification_summary, tm.getSimOperatorName()); + + cancelEnableMmsNotification(context); + + createEnableMmsNotification(context, notificationTitle, notificationSummary, subId); + } + + private void onPrimarySubscriptionListChanged(Context context, Intent intent) { // Cancel any previous notifications - cancelNotification(context); + cancelSimSelectNotification(context); // Create a notification to tell the user that some defaults are missing - createNotification(context); + createSimSelectNotification(context); int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE); @@ -76,20 +151,20 @@ public class SimSelectNotification extends BroadcastReceiver { } } - private void createNotification(Context context){ + private void createSimSelectNotification(Context context){ final Resources resources = context.getResources(); NotificationChannel notificationChannel = new NotificationChannel( SIM_SELECT_NOTIFICATION_CHANNEL, - resources.getString(R.string.sim_selection_channel_title), + resources.getText(R.string.sim_selection_channel_title), NotificationManager.IMPORTANCE_LOW); - NotificationCompat.Builder builder = - new NotificationCompat.Builder(context, SIM_SELECT_NOTIFICATION_CHANNEL) + Notification.Builder builder = + new Notification.Builder(context, SIM_SELECT_NOTIFICATION_CHANNEL) .setSmallIcon(R.drawable.ic_sim_card_alert_white_48dp) .setColor(context.getColor(R.color.sim_noitification)) - .setContentTitle(resources.getString(R.string.sim_notification_title)) - .setContentText(resources.getString(R.string.sim_notification_summary)); + .setContentTitle(resources.getText(R.string.sim_notification_title)) + .setContentText(resources.getText(R.string.sim_notification_summary)); Intent resultIntent = new Intent(Settings.ACTION_WIRELESS_SETTINGS); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, @@ -98,12 +173,51 @@ public class SimSelectNotification extends BroadcastReceiver { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(notificationChannel); - notificationManager.notify(NOTIFICATION_ID, builder.build()); + notificationManager.notify(SIM_SELECT_NOTIFICATION_ID, builder.build()); } - public static void cancelNotification(Context context) { + public static void cancelSimSelectNotification(Context context) { NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(NOTIFICATION_ID); + notificationManager.cancel(SIM_SELECT_NOTIFICATION_ID); + } + + private void createEnableMmsNotification(Context context, CharSequence titleString, + CharSequence notificationSummary, int subId) { + final Resources resources = context.getResources(); + + NotificationChannel notificationChannel = new NotificationChannel( + ENABLE_MMS_NOTIFICATION_CHANNEL, + resources.getText(R.string.enable_mms_notification_channel_title), + NotificationManager.IMPORTANCE_HIGH); + + Notification.Builder builder = + new Notification.Builder(context, ENABLE_MMS_NOTIFICATION_CHANNEL) + .setSmallIcon(R.drawable.ic_settings_24dp) + .setColor(context.getColor(R.color.sim_noitification)) + .setContentTitle(titleString) + .setContentText(notificationSummary) + .setStyle(new Notification.BigTextStyle().bigText(notificationSummary)); + + // Create the pending intent that will lead to the subscription setting page. + Intent resultIntent = new Intent(Settings.ACTION_MMS_MESSAGE_SETTING); + resultIntent.setClass(context, MobileNetworkActivity.class); + resultIntent.putExtra(Settings.EXTRA_SUB_ID, subId); + resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent, + PendingIntent.FLAG_CANCEL_CURRENT); + builder.setContentIntent(resultPendingIntent); + + // Notify the notification. + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.createNotificationChannel(notificationChannel); + notificationManager.notify(ENABLE_MMS_NOTIFICATION_ID, builder.build()); + } + + private void cancelEnableMmsNotification(Context context) { + NotificationManager notificationManager = + (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(ENABLE_MMS_NOTIFICATION_ID); } } diff --git a/src/com/android/settings/sim/SimSettings.java b/src/com/android/settings/sim/SimSettings.java index e43c6a5d83f..1222913d8c9 100644 --- a/src/com/android/settings/sim/SimSettings.java +++ b/src/com/android/settings/sim/SimSettings.java @@ -101,7 +101,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable mSimCards = (PreferenceScreen)findPreference(SIM_CARD_CATEGORY); mAvailableSubInfos = new ArrayList(mNumSlots); mSelectableSubInfos = new ArrayList(); - SimSelectNotification.cancelNotification(getActivity()); + SimSelectNotification.cancelSimSelectNotification(getActivity()); } private final SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangeListener diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java new file mode 100644 index 00000000000..69c0919719f --- /dev/null +++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2019 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.sim; + + +import static android.app.NotificationManager.IMPORTANCE_HIGH; +import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_MMS; +import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS; +import static android.provider.Settings.EXTRA_ENABLE_MMS_DATA_REQUEST_REASON; +import static android.provider.Settings.EXTRA_SUB_ID; +import static android.telephony.data.ApnSetting.TYPE_MMS; + +import static com.android.settings.sim.SimSelectNotification.ENABLE_MMS_NOTIFICATION_CHANNEL; +import static com.android.settings.sim.SimSelectNotification.ENABLE_MMS_NOTIFICATION_ID; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.provider.Settings; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; + +import com.android.settings.R; + +import com.android.settings.testutils.shadow.ShadowAlertDialogCompat; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowAlertDialogCompat.class) +public class SimSelectNotificationTest { + @Mock + private Context mContext; + @Mock + private NotificationManager mNotificationManager; + @Mock + private TelephonyManager mTelephonyManager; + @Mock + private SubscriptionManager mSubscriptionManager; + @Mock + private PackageManager mPackageManager; + @Mock + private Resources mResources; + + private String mFakeOperatorName = "fake_operator_name"; + private CharSequence mFakeNotificationChannelTitle = "fake_notification_channel_title"; + private CharSequence mFakeNotificationTitle = "fake_notification_title"; + private String mFakeNotificationSummary = "fake_notification_Summary"; + + private int mSubId = 1; + + SimSelectNotification mSimSelectNotification = new SimSelectNotification(); + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)) + .thenReturn(mNotificationManager); + when(mContext.getSystemService(Context.TELEPHONY_SERVICE)) + .thenReturn(mTelephonyManager); + when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)) + .thenReturn(mSubscriptionManager); + when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mPackageManager.checkPermission(any(), any())) + .thenReturn(PackageManager.PERMISSION_GRANTED); + + when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); + when(mTelephonyManager.getSimOperatorName()).thenReturn(mFakeOperatorName); + when(mTelephonyManager.isDataEnabledForApn(TYPE_MMS)).thenReturn(false); + when(mSubscriptionManager.isActiveSubId(mSubId)).thenReturn(true); + when(mContext.getResources()).thenReturn(mResources); + + when(mResources.getText(R.string.enable_sending_mms_notification_title)) + .thenReturn(mFakeNotificationTitle); + when(mResources.getText(R.string.enable_mms_notification_channel_title)) + .thenReturn(mFakeNotificationChannelTitle); + when(mResources.getString(R.string.enable_mms_notification_summary, + mFakeOperatorName)).thenReturn(mFakeNotificationSummary); + } + + @Test + public void onReceiveEnableMms_notificationShouldSend() { + Intent intent = new Intent(Settings.ACTION_ENABLE_MMS_DATA_REQUEST); + intent.putExtra(EXTRA_SUB_ID, mSubId); + intent.putExtra(EXTRA_ENABLE_MMS_DATA_REQUEST_REASON, + ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS); + + mSimSelectNotification.onReceive(mContext, intent); + + // Capture the notification channel created and verify its fields. + ArgumentCaptor nc = ArgumentCaptor.forClass(NotificationChannel.class); + verify(mNotificationManager).createNotificationChannel(nc.capture()); + + assertThat(nc.getValue().getId()).isEqualTo(ENABLE_MMS_NOTIFICATION_CHANNEL); + assertThat(nc.getValue().getName()).isEqualTo(mFakeNotificationChannelTitle); + assertThat(nc.getValue().getImportance()).isEqualTo(IMPORTANCE_HIGH); + + // Capture the notification it notifies and verify its fields. + ArgumentCaptor notification = ArgumentCaptor.forClass(Notification.class); + verify(mNotificationManager).notify( + eq(ENABLE_MMS_NOTIFICATION_ID), notification.capture()); + assertThat(notification.getValue().extras.getCharSequence(Notification.EXTRA_TITLE)) + .isEqualTo(mFakeNotificationTitle); + assertThat(notification.getValue().extras.getCharSequence(Notification.EXTRA_BIG_TEXT)) + .isEqualTo(mFakeNotificationSummary); + assertThat(notification.getValue().contentIntent).isNotNull(); + } + + @Test + public void onReceiveEnableMms_NoExtra_notificationShouldNotSend() { + Intent intent = new Intent(Settings.ACTION_ENABLE_MMS_DATA_REQUEST); + + // EXTRA_SUB_ID and EXTRA_ENABLE_MMS_DATA_REQUEST_REASON are required. + mSimSelectNotification.onReceive(mContext, intent); + verify(mNotificationManager, never()).createNotificationChannel(any()); + } + + @Test + public void onReceiveEnableMms_MmsDataAlreadyEnabled_notificationShouldNotSend() { + when(mTelephonyManager.isDataEnabledForApn(TYPE_MMS)).thenReturn(true); + Intent intent = new Intent(Settings.ACTION_ENABLE_MMS_DATA_REQUEST); + intent.putExtra(EXTRA_SUB_ID, mSubId); + intent.putExtra(EXTRA_ENABLE_MMS_DATA_REQUEST_REASON, + ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_MMS); + + // If MMS data is already enabled, there's no need to trigger the notification. + mSimSelectNotification.onReceive(mContext, intent); + verify(mNotificationManager, never()).createNotificationChannel(any()); + } +} + From 636ad9d94753a7377ce5f9f3f885a8a8b2018ee0 Mon Sep 17 00:00:00 2001 From: cosmohsieh Date: Sun, 21 Apr 2019 20:11:39 +0800 Subject: [PATCH 3/9] Fix modification of WifiDialog doesn't take effect on details page When clicking modify menu option in detiails page, modification on metered or privacy preferences in the WifiDialog does not effect back to details page but only changing internal data of WifiDialog. Adding callback to update those two preferences. Bug: 130775713 Test: make RunSettingsRoboTests -j32 ROBOTEST_FILTER=com.android.settings.wifi.details.WifiDetailPreferenceControllerTest Change-Id: I74bfa5a9581dfae73894c3e9f73d1069a36fd16b --- .../WifiMeteredPreferenceController.java | 26 ++++++++++++- .../details/WifiNetworkDetailsFragment.java | 28 ++++++++++--- .../WifiPrivacyPreferenceController.java | 39 ++++++++++++++++--- 3 files changed, 81 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java b/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java index 341b2279994..5f4e9d0adb1 100644 --- a/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiMeteredPreferenceController.java @@ -24,19 +24,22 @@ import android.net.wifi.WifiManager; import androidx.annotation.VisibleForTesting; import androidx.preference.DropDownPreference; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; +import com.android.settings.wifi.WifiDialog; import com.android.settingslib.core.AbstractPreferenceController; /** * {@link AbstractPreferenceController} that controls whether the wifi network is metered or not */ public class WifiMeteredPreferenceController extends BasePreferenceController implements - Preference.OnPreferenceChangeListener { + Preference.OnPreferenceChangeListener, WifiDialog.WifiDialogListener { private static final String KEY_WIFI_METERED = "metered"; private WifiConfiguration mWifiConfiguration; private WifiManager mWifiManager; + private Preference mPreference; public WifiMeteredPreferenceController(Context context, WifiConfiguration wifiConfiguration) { super(context, KEY_WIFI_METERED); @@ -81,4 +84,25 @@ public class WifiMeteredPreferenceController extends BasePreferenceController im private void updateSummary(DropDownPreference preference, int meteredOverride) { preference.setSummary(preference.getEntries()[meteredOverride]); } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public void onSubmit(WifiDialog dialog) { + if (dialog.getController() != null) { + final WifiConfiguration newConfig = dialog.getController().getConfig(); + if (newConfig == null || mWifiConfiguration == null) { + return; + } + + if (newConfig.meteredOverride != mWifiConfiguration.meteredOverride) { + mWifiConfiguration = newConfig; + onPreferenceChange(mPreference, String.valueOf(newConfig.meteredOverride)); + } + } + } } diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java index 10d1d48f4a2..b645d60bbd2 100644 --- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java +++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java @@ -47,12 +47,14 @@ import java.util.List; *

The AccessPoint should be saved to the intent Extras when launching this class via * {@link AccessPoint#saveWifiState(Bundle)} in order to properly render this page. */ -public class WifiNetworkDetailsFragment extends DashboardFragment { +public class WifiNetworkDetailsFragment extends DashboardFragment implements + WifiDialog.WifiDialogListener { private static final String TAG = "WifiNetworkDetailsFrg"; private AccessPoint mAccessPoint; private WifiDetailPreferenceController mWifiDetailPreferenceController; + private List mWifiDialogListeners = new ArrayList<>(); @Override public void onAttach(Context context) { @@ -89,7 +91,7 @@ public class WifiNetworkDetailsFragment extends DashboardFragment { || mAccessPoint == null) { return null; } - return WifiDialog.createModal(getActivity(), mWifiDetailPreferenceController, mAccessPoint, + return WifiDialog.createModal(getActivity(), this, mAccessPoint, WifiConfigUiBase.MODE_MODIFY); } @@ -135,15 +137,31 @@ public class WifiNetworkDetailsFragment extends DashboardFragment { controllers.add(mWifiDetailPreferenceController); controllers.add(new AddDevicePreferenceController(context).init(mAccessPoint)); - controllers.add(new WifiMeteredPreferenceController(context, mAccessPoint.getConfig())); - WifiPrivacyPreferenceController privacyController = new WifiPrivacyPreferenceController( - context); + + final WifiMeteredPreferenceController meteredPreferenceController = + new WifiMeteredPreferenceController(context, mAccessPoint.getConfig()); + controllers.add(meteredPreferenceController); + + final WifiPrivacyPreferenceController privacyController = + new WifiPrivacyPreferenceController(context); privacyController.setWifiConfiguration(mAccessPoint.getConfig()); privacyController.setIsEphemeral(mAccessPoint.isEphemeral()); privacyController.setIsPasspoint( mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig()); controllers.add(privacyController); + // Sets callback listener for wifi dialog. + mWifiDialogListeners.add(mWifiDetailPreferenceController); + mWifiDialogListeners.add(privacyController); + mWifiDialogListeners.add(meteredPreferenceController); + return controllers; } + + @Override + public void onSubmit(WifiDialog dialog) { + for (WifiDialog.WifiDialogListener listener : mWifiDialogListeners) { + listener.onSubmit(dialog); + } + } } diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java index 7bec4119f8d..950cc131f4a 100644 --- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java +++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java @@ -18,16 +18,17 @@ package com.android.settings.wifi.details; import android.content.Context; import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; -import android.util.FeatureFlagUtils; import androidx.annotation.VisibleForTesting; import androidx.preference.DropDownPreference; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; -import com.android.settings.core.FeatureFlags; +import com.android.settings.wifi.WifiDialog; import com.android.settingslib.core.AbstractPreferenceController; /** @@ -35,13 +36,14 @@ import com.android.settingslib.core.AbstractPreferenceController; * or not */ public class WifiPrivacyPreferenceController extends BasePreferenceController implements - Preference.OnPreferenceChangeListener { + Preference.OnPreferenceChangeListener, WifiDialog.WifiDialogListener { private static final String KEY_WIFI_PRIVACY = "privacy"; private WifiConfiguration mWifiConfiguration; private WifiManager mWifiManager; private boolean mIsEphemeral = false; private boolean mIsPasspoint = false; + private Preference mPreference; public WifiPrivacyPreferenceController(Context context) { super(context, KEY_WIFI_PRIVACY); @@ -68,6 +70,12 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im AVAILABLE : CONDITIONALLY_UNAVAILABLE; } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + @Override public void updateState(Preference preference) { final DropDownPreference dropDownPreference = (DropDownPreference) preference; @@ -87,9 +95,13 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im if (mWifiConfiguration != null) { mWifiConfiguration.macRandomizationSetting = Integer.parseInt((String) newValue); mWifiManager.updateNetwork(mWifiConfiguration); - // To activate changing, we need reconnect network. WiFi will auto connect to current - // network after disconnect(). - mWifiManager.disconnect(); + + // To activate changing, we need to reconnect network. WiFi will auto connect to + // current network after disconnect(). Only needed when this is connected network. + final WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); + if (wifiInfo != null && wifiInfo.getNetworkId() == mWifiConfiguration.networkId) { + mWifiManager.disconnect(); + } } updateSummary((DropDownPreference) preference, Integer.parseInt((String) newValue)); return true; @@ -133,4 +145,19 @@ public class WifiPrivacyPreferenceController extends BasePreferenceController im final int prefMacRandomized = translateMacRandomizedValueToPrefValue(macRandomized); preference.setSummary(preference.getEntries()[prefMacRandomized]); } + + @Override + public void onSubmit(WifiDialog dialog) { + if (dialog.getController() != null) { + final WifiConfiguration newConfig = dialog.getController().getConfig(); + if (newConfig == null || mWifiConfiguration == null) { + return; + } + + if (newConfig.macRandomizationSetting != mWifiConfiguration.macRandomizationSetting) { + mWifiConfiguration = newConfig; + onPreferenceChange(mPreference, String.valueOf(newConfig.macRandomizationSetting)); + } + } + } } From b5d471c19b7dc6cd6086283be41fe2d959c7ab56 Mon Sep 17 00:00:00 2001 From: Salvador Martinez Date: Tue, 30 Apr 2019 09:56:25 -0700 Subject: [PATCH 4/9] Fix null pointer in SubscriptionUtil Sometimes we get null sub info which causes a crash. This just makes it so that if we see that we treat it as inactive since there isn't really a world where an active null sub info makes sense. Test: atest SubscriptionUtilTest Bug: 131603073 Change-Id: Id5ecbecf011e19ff02d9465e0571b1d17c83de9a --- src/com/android/settings/network/SubscriptionUtil.java | 6 +++++- .../com/android/settings/network/SubscriptionUtilTest.java | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java index e7003298bf7..ebac51f3f67 100644 --- a/src/com/android/settings/network/SubscriptionUtil.java +++ b/src/com/android/settings/network/SubscriptionUtil.java @@ -59,7 +59,11 @@ public class SubscriptionUtil { return subscriptions; } - private static boolean isInactiveInsertedPSim(UiccSlotInfo slotInfo) { + @VisibleForTesting + static boolean isInactiveInsertedPSim(UiccSlotInfo slotInfo) { + if (slotInfo == null) { + return false; + } return !slotInfo.getIsEuicc() && !slotInfo.getIsActive() && slotInfo.getCardStateInfo() == CARD_STATE_INFO_PRESENT; } diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java index c6479147e6a..40b955ccd06 100644 --- a/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java +++ b/tests/robotests/src/com/android/settings/network/SubscriptionUtilTest.java @@ -187,4 +187,9 @@ public class SubscriptionUtilTest { assertThat(subs).isNotNull(); assertThat(subs).hasSize(2); } + + @Test + public void isInactiveInsertedPSim_nullSubInfo_doesNotCrash() { + assertThat(SubscriptionUtil.isInactiveInsertedPSim(null)).isFalse(); + } } From e360f9f0378c42042a421ebc087dc825704b5896 Mon Sep 17 00:00:00 2001 From: Amin Shaikh Date: Tue, 30 Apr 2019 17:29:04 -0400 Subject: [PATCH 5/9] Update settings gesture icon. Fixes: 130148532 Test: visual Change-Id: Ic5fe6dbd5ae726edcd9ad27e512c627aebf554a9 --- res/drawable/ic_settings_gestures.xml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/res/drawable/ic_settings_gestures.xml b/res/drawable/ic_settings_gestures.xml index 4fe0bf37deb..c75e7c3b2e1 100644 --- a/res/drawable/ic_settings_gestures.xml +++ b/res/drawable/ic_settings_gestures.xml @@ -20,9 +20,6 @@ android:viewportHeight="32.0" android:tint="?android:attr/colorControlNormal"> - + android:fillColor="@android:color/white" + android:pathData="M4.59 6.89c0.7-0.71 1.4-1.35 1.71-1.22 0.5 0.2 0 1.03-0.3 1.52-0.25 0.42 -2.86 3.89-2.86 6.31 0 1.28 0.48 2.34 1.34 2.98 0.75 0.56 1.74 0.73 2.64 0.46 1.07-0.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78 0.64 -5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H21v-2.5h-2.47c-0.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-0.58 0.73 -2.06 2.48-2.29 2.72-0.25 0.3 -0.68 0.84 -1.11 0.84 -0.45 0-0.72-0.83-0.36-1.92 0.35 -1.09 1.4-2.86 1.85-3.52 0.78 -1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25c-0.36 0.36 -0.66 0.66 -0.88 0.93 l1.75 1.71zm9.29 11.66c-0.31 0-0.74-0.26-0.74-0.72 0-0.6 0.73 -2.2 2.87-2.76-0.3 2.69-1.43 3.48-2.13 3.48z" /> \ No newline at end of file From 99b22cba097bee6ff15c8a41cba38020fd182e94 Mon Sep 17 00:00:00 2001 From: lindatseng Date: Tue, 30 Apr 2019 14:13:32 -0700 Subject: [PATCH 6/9] Avoid NPE in app storage page Adding null check for ProviderInfo. Skip adding count to map if the Provider cannot be found, to avoid NPE. Fixes: 128368170 Test: Manual Change-Id: I3d3b5301e6ca25a671077c9b93ada89be46e23fd --- src/com/android/settings/applications/AppStorageSettings.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/com/android/settings/applications/AppStorageSettings.java b/src/com/android/settings/applications/AppStorageSettings.java index 56fa4555fd1..f07c66cd8a5 100644 --- a/src/com/android/settings/applications/AppStorageSettings.java +++ b/src/com/android/settings/applications/AppStorageSettings.java @@ -421,6 +421,10 @@ public class AppStorageSettings extends AppInfoWithHeader for (GrantedUriPermission perm : perms) { String authority = perm.uri.getAuthority(); ProviderInfo provider = pm.resolveContentProvider(authority, 0); + if (provider == null) { + continue; + } + CharSequence app = provider.applicationInfo.loadLabel(pm); MutableInt count = uriCounters.get(app); if (count == null) { From a40d2741f0ffa42cc5f76796ada527c3be0ff8a2 Mon Sep 17 00:00:00 2001 From: Pengquan Meng Date: Tue, 30 Apr 2019 19:32:58 -0700 Subject: [PATCH 7/9] Disable 'Enable DSDS' switch for always dsds mode Disable the switch in RadioInfo when the ro.boot.hardware.dsds is set. Bug: 131440879 Test: manual Change-Id: Ib4d3111fc639f44295a82b8790a0b780293b1aa8 --- src/com/android/settings/RadioInfo.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/RadioInfo.java b/src/com/android/settings/RadioInfo.java index e0ce1c0cc8e..fdc930e3264 100644 --- a/src/com/android/settings/RadioInfo.java +++ b/src/com/android/settings/RadioInfo.java @@ -40,6 +40,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.SystemProperties; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.CellIdentityCdma; @@ -130,6 +131,13 @@ public class RadioInfo extends Activity { private static final int CELL_INFO_LIST_RATE_DISABLED = Integer.MAX_VALUE; private static final int CELL_INFO_LIST_RATE_MAX = 0; + private static final String DSDS_MODE_PROPERTY = "ro.boot.hardware.dsds"; + + /** + * A value indicates the device is always on dsds mode. + * @see {@link #DSDS_MODE_PROPERTY} + */ + private static final int ALWAYS_ON_DSDS_MODE = 1; private static final int IMS_VOLTE_PROVISIONED_CONFIG_ID = ImsConfig.ConfigConstants.VLT_SETTING_ENABLED; @@ -497,7 +505,7 @@ public class RadioInfo extends Activity { cbrsDataSwitch.setVisibility(isCbrsSupported() ? View.VISIBLE : View.GONE); dsdsSwitch = findViewById(R.id.dsds_switch); - if (isDsdsSupported()) { + if (isDsdsSupported() && !dsdsModeOnly()) { dsdsSwitch.setVisibility(View.VISIBLE); dsdsSwitch.setOnClickListener(v -> { if (mTelephonyManager.doesSwitchMultiSimConfigTriggerReboot()) { @@ -1694,6 +1702,14 @@ public class RadioInfo extends Activity { mTelephonyManager.switchMultiSimConfig(dsdsSwitch.isChecked() ? 2 : 1); } + /** + * @return {@code True} if the device is only supported dsds mode. + */ + private boolean dsdsModeOnly() { + String dsdsMode = SystemProperties.get(DSDS_MODE_PROPERTY); + return !TextUtils.isEmpty(dsdsMode) && Integer.parseInt(dsdsMode) == ALWAYS_ON_DSDS_MODE; + } + DialogInterface.OnClickListener mOnDsdsDialogConfirmedListener = new DialogInterface.OnClickListener() { @Override From 090e67d938579f478ff85b25ed42e3836824848d Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Tue, 30 Apr 2019 14:18:47 -0400 Subject: [PATCH 8/9] Importance preference updates - Use show on lockscreen setting - Match design to notification shade guts Test: robotests Bug: 131290247 Bug: 128445911 Change-Id: I645b35191c8f22e751c264fd8ca13560f50b7582 --- res/drawable/button_border_selected.xml | 4 +- res/drawable/button_border_unselected.xml | 4 +- res/layout/notif_importance_preference.xml | 121 ++++++++++++------ res/values/dimens.xml | 1 + res/values/strings.xml | 26 ++-- .../notification/ImportancePreference.java | 49 ++++--- .../ImportancePreferenceController.java | 4 +- .../ImportancePreferenceTest.java | 43 +++++-- 8 files changed, 166 insertions(+), 86 deletions(-) diff --git a/res/drawable/button_border_selected.xml b/res/drawable/button_border_selected.xml index 2681bf051b4..9701b382540 100644 --- a/res/drawable/button_border_selected.xml +++ b/res/drawable/button_border_selected.xml @@ -18,6 +18,6 @@ android:shape="rectangle"> + android:color="?android:attr/textColorSecondary"/> - \ No newline at end of file + diff --git a/res/drawable/button_border_unselected.xml b/res/drawable/button_border_unselected.xml index 72e9076ccf2..4153303667d 100644 --- a/res/drawable/button_border_unselected.xml +++ b/res/drawable/button_border_unselected.xml @@ -18,7 +18,7 @@ android:shape="rectangle"> + android:color="?android:attr/textColorSecondary"/> - \ No newline at end of file + diff --git a/res/layout/notif_importance_preference.xml b/res/layout/notif_importance_preference.xml index bc0d5aa90b3..3507675c44a 100644 --- a/res/layout/notif_importance_preference.xml +++ b/res/layout/notif_importance_preference.xml @@ -21,53 +21,92 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" + android:padding="@dimen/notification_importance_toggle_marginTop" android:orientation="vertical"> - + android:padding="@dimen/notification_importance_button_padding" + android:clickable="true" + android:focusable="true"> + + + + -