Snap for 5523284 from 9a4fa9bf0d to qt-release

Change-Id: I3b70095a1b32cba4adfb5ed73e55b2df7f4f821a
This commit is contained in:
android-build-team Robot
2019-05-02 03:15:37 +00:00
24 changed files with 616 additions and 260 deletions

View File

@@ -138,6 +138,7 @@
<intent-filter android:priority="1">
<action android:name="android.settings.NETWORK_OPERATOR_SETTINGS" />
<action android:name="android.settings.DATA_ROAMING_SETTINGS" />
<action android:name="android.settings.MMS_MESSAGE_SETTING" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -2624,6 +2625,7 @@
<receiver android:name=".sim.SimSelectNotification">
<intent-filter>
<action android:name="android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"/>
<action android:name="android.settings.ENABLE_MMS_DATA_REQUEST"/>
</intent-filter>
</receiver>

View File

@@ -18,6 +18,6 @@
android:shape="rectangle">
<stroke
android:width="2dp"
android:color="?android:attr/colorAccent"/>
android:color="?android:attr/textColorSecondary"/>
<corners android:radius="@dimen/rect_button_radius" />
</shape>
</shape>

View File

@@ -18,7 +18,7 @@
android:shape="rectangle">
<stroke
android:width="2dp"
android:color="@color/notification_importance_button_unselected"/>
android:color="?android:attr/textColorSecondary"/>
<corners android:radius="@dimen/rect_button_radius" />
</shape>
</shape>

View File

@@ -20,9 +20,6 @@
android:viewportHeight="32.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="M20,20.2V24H6V5.3h8.7l2.4,-4H7.6c-2.2,0 -4,1.8 -4,4v21.3c0,2.2 1.8,4 4,4h10.7c2.2,0 4,-1.8 4,-4V14.9L20,20.2zM15.6,28h-5.3v-1.3h5.3V28z"/>
<path
android:fillColor="#FF000000"
android:pathData="M28.5,7l1.1,-2.4L32,3.5l-2.4,-1.1L28.5,0l-1.1,2.4L25,3.5l2.4,1.1L28.5,7zM21,7.4l-2.2,-4.8l-2.2,4.8l-4.8,2.2l4.8,2.2l2.2,4.8l2.2,-4.8l4.8,-2.2L21,7.4zM28.5,12.2l-1.1,2.4L25,15.6l2.4,1.1l1.1,2.4l1.1,-2.4l2.4,-1.1l-2.4,-1.1L28.5,12.2z"/>
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" />
</vector>

View File

@@ -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">
<LinearLayout
android:id="@+id/buttons"
<RelativeLayout
android:id="@+id/alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/notification_importance_toggle_marginTop"
android:orientation="horizontal"
android:gravity="center">
android:padding="@dimen/notification_importance_button_padding"
android:clickable="true"
android:focusable="true">
<ImageView
android:id="@+id/alert_icon"
android:src="@drawable/ic_notification_alert"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"/>
<TextView
android:id="@+id/alert_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:clickable="false"
android:focusable="false"
android:layout_toEndOf="@id/alert_icon"
android:layout_marginStart="@dimen/notification_importance_drawable_padding"
android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
android:text="@string/notification_alert_title"/>
<TextView
android:id="@+id/alert_summary"
android:paddingTop="@dimen/notification_importance_button_padding"
android:text="@string/notification_channel_summary_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
android:maxLines="2"
android:layout_below="@id/alert_icon"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</RelativeLayout>
<Button
android:id="@+id/alert"
android:layout_width="wrap_content"
android:layout_height="@dimen/notification_importance_toggle_size"
android:minWidth="@dimen/notification_importance_button_width"
android:paddingStart="@dimen/notification_importance_button_horiz_padding"
android:paddingEnd="@dimen/notification_importance_button_horiz_padding"
android:drawablePadding="@dimen/notification_importance_drawable_padding"
android:foreground="@drawable/button_ripple_radius"
android:drawableLeft="@drawable/ic_notification_alert"
android:text="@string/notification_alert_title" />
<Button
android:id="@+id/silence"
android:layout_width="wrap_content"
android:layout_height="@dimen/notification_importance_toggle_size"
android:minWidth="@dimen/notification_importance_button_width"
android:paddingStart="@dimen/notification_importance_button_horiz_padding"
android:paddingEnd="@dimen/notification_importance_button_horiz_padding"
android:drawablePadding="@dimen/notification_importance_drawable_padding"
android:foreground="@drawable/button_ripple_radius"
android:layout_marginStart="@dimen/notification_importance_button_separation"
android:drawableLeft="@drawable/ic_notification_silence"
android:text="@string/notification_silence_title" />
</LinearLayout>
<TextView
android:id="@+id/description"
<RelativeLayout
android:id="@+id/silence"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/notification_alert_title"
android:gravity="center"
android:layout_marginTop="@dimen/notification_importance_text_marginTop"
android:layout_marginBottom="@dimen/notification_importance_toggle_marginBottom"
android:paddingStart="@dimen/notification_importance_description_padding"
android:paddingEnd="@dimen/notification_importance_description_padding"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail" />
android:padding="@dimen/notification_importance_button_padding"
android:layout_marginTop="@dimen/notification_importance_button_separation"
android:clickable="true"
android:focusable="true">
<ImageView
android:id="@+id/silence_icon"
android:src="@drawable/ic_notification_silence"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"/>
<TextView
android:id="@+id/silence_label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:clickable="false"
android:focusable="false"
android:layout_toEndOf="@id/silence_icon"
android:layout_marginStart="@dimen/notification_importance_drawable_padding"
android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
android:text="@string/notification_silence_title"/>
<TextView
android:id="@+id/silence_summary"
android:paddingTop="@dimen/notification_importance_button_padding"
android:text="@string/notification_channel_summary_default"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
android:ellipsize="end"
android:maxLines="2"
android:layout_below="@id/silence_icon"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
</RelativeLayout>
</LinearLayout>

View File

@@ -22,8 +22,9 @@
<androidx.slice.widget.SliceView
android:id="@+id/slice_view"
style="@style/SliceViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="20dp"
android:paddingEnd="20dp"/>
android:paddingStart="8dp"
android:paddingEnd="8dp"/>
</LinearLayout>

View File

@@ -79,6 +79,7 @@
<dimen name="notification_importance_description_padding">20dp</dimen>
<dimen name="notification_importance_description_text">14sp</dimen>
<dimen name="notification_importance_button_text">16sp</dimen>
<dimen name="notification_importance_button_padding">14dp</dimen>
<dimen name="zen_schedule_rule_checkbox_padding">7dp</dimen>
<dimen name="zen_schedule_day_margin">17dp</dimen>

View File

@@ -7805,7 +7805,7 @@
<string name="profile_section_header">Work notifications</string>
<!-- Configure Notifications: section header for prioritizer settings [CHAR LIMIT=80] -->
<string name="smart_notifications_title">Smart notifications</string>
<string name="smart_notifications_title">Adaptive notifications</string>
<!-- Configure Notifications: setting title [CHAR LIMIT=80] -->
<string name="asst_capability_prioritizer_title">Automatic Prioritization</string>
@@ -7976,25 +7976,25 @@
<!-- Channel summaries for the app notification page -->
<!-- [CHAR LIMIT=100] Notification Importance title: min importance level summary -->
<!-- [CHAR LIMIT=150] Notification Importance title: min importance level summary -->
<string name="notification_channel_summary_min">In the pull-down shade, collapse notifications to one line</string>
<!-- [CHAR LIMIT=100] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low">Always silent. Displays in pull-down shade.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low">Helps you focus with notifications only in the pull-down shade. Always silent.</string>
<!-- [CHAR LIMIT=100] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low_status">Always silent. Displays in pull-down shade &amp; status bar.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low_status">Displays below priority notifications. Always silent.</string>
<!-- [CHAR LIMIT=100] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low_lock">Always silent. Displays in pull-down shade &amp; on lock screen.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low_lock">Displays below priority notifications. Always silent.</string>
<!-- [CHAR LIMIT=100] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low_status_lock">Always silent. Displays in pull-down shade, status bar &amp; on lock screen.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: low importance level summary -->
<string name="notification_channel_summary_low_status_lock">Displays below priority notifications. Always silent.</string>
<!-- [CHAR LIMIT=100] Notification Importance title: normal importance level summary -->
<string name="notification_channel_summary_default">Makes sound and displays in pull-down shade, status bar &amp; on lock screen.</string>
<!-- [CHAR LIMIT=150] Notification Importance title: normal importance level summary -->
<string name="notification_channel_summary_default">Gets your attention with sound &amp; a status bar icon. Shows on lock screen.</string>
<!-- [CHAR LIMIT=100] Notification Importance title: high importance level summary -->
<!-- [CHAR LIMIT=150] Notification Importance title: high importance level summary -->
<string name="notification_channel_summary_high">When device is unlocked, show notifications as a banner across the top of the screen</string>
<!-- [CHAR LIMIT=100] Label for on/off toggle -->

View File

@@ -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

View File

@@ -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) {

View File

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

View File

@@ -20,10 +20,16 @@ import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_MIN;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.transition.AutoTransition;
import android.transition.TransitionManager;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
@@ -38,11 +44,12 @@ public class ImportancePreference extends Preference {
private int mImportance;
private boolean mDisplayInStatusBar;
private boolean mDisplayOnLockscreen;
private Button mSilenceButton;
private Button mAlertButton;
private View mSilenceButton;
private View mAlertButton;
private Context mContext;
Drawable selectedBackground;
Drawable unselectedBackground;
private static final int BUTTON_ANIM_TIME_MS = 100;
public ImportancePreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
@@ -89,13 +96,12 @@ public class ImportancePreference extends Preference {
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
public void onBindViewHolder(final PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
holder.itemView.setClickable(false);
TextView textView = (TextView) holder.findViewById(R.id.description);
mSilenceButton = (Button) holder.findViewById(R.id.silence);
mAlertButton = (Button) holder.findViewById(R.id.alert);
mSilenceButton = holder.findViewById(R.id.silence);
mAlertButton = holder.findViewById(R.id.alert);
if (!mIsConfigurable) {
mSilenceButton.setEnabled(false);
@@ -114,34 +120,41 @@ public class ImportancePreference extends Preference {
mAlertButton.setBackground(selectedBackground);
break;
}
setImportanceSummary(textView, mImportance);
setImportanceSummary((ViewGroup) holder.itemView, mImportance, false);
mSilenceButton.setOnClickListener(v -> {
callChangeListener(IMPORTANCE_LOW);
mAlertButton.setBackground(unselectedBackground);
mAlertButton.setSelected(false);
mSilenceButton.setBackground(selectedBackground);
mSilenceButton.setTextAppearance(
R.style.TextAppearance_NotificationImportanceButton_Selected);
mAlertButton.setTextAppearance(
R.style.TextAppearance_NotificationImportanceButton_Unselected);
setImportanceSummary(textView, IMPORTANCE_LOW);
mSilenceButton.setSelected(true);
setImportanceSummary((ViewGroup) holder.itemView, IMPORTANCE_LOW, true);
});
mAlertButton.setOnClickListener(v -> {
callChangeListener(IMPORTANCE_DEFAULT);
mSilenceButton.setBackground(unselectedBackground);
mSilenceButton.setSelected(false);
mAlertButton.setBackground(selectedBackground);
mAlertButton.setTextAppearance(
R.style.TextAppearance_NotificationImportanceButton_Selected);
mSilenceButton.setTextAppearance(
R.style.TextAppearance_NotificationImportanceButton_Unselected);
setImportanceSummary(textView, IMPORTANCE_DEFAULT);
mAlertButton.setSelected(true);
setImportanceSummary((ViewGroup) holder.itemView, IMPORTANCE_DEFAULT, true);
});
}
void setImportanceSummary(TextView view, int importance) {
void setImportanceSummary(ViewGroup parent, int importance, boolean fromUser) {
if (fromUser) {
AutoTransition transition = new AutoTransition();
transition.setDuration(BUTTON_ANIM_TIME_MS);
TransitionManager.beginDelayedTransition(parent, transition);
}
if (importance >= IMPORTANCE_DEFAULT) {
parent.findViewById(R.id.silence_summary).setVisibility(GONE);
TextView view = parent.findViewById(R.id.alert_summary);
view.setText(R.string.notification_channel_summary_default);
view.setVisibility(VISIBLE);
} else {
parent.findViewById(R.id.alert_summary).setVisibility(GONE);
TextView view = parent.findViewById(R.id.silence_summary);
view.setVisibility(VISIBLE);
if (mDisplayInStatusBar) {
if (mDisplayOnLockscreen) {
view.setText(R.string.notification_channel_summary_low_status_lock);

View File

@@ -22,6 +22,7 @@ import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import android.app.NotificationChannel;
import android.content.Context;
import android.media.RingtoneManager;
import android.provider.Settings;
import com.android.settings.core.PreferenceControllerMixin;
@@ -64,7 +65,8 @@ public class ImportancePreferenceController extends NotificationPreferenceContro
pref.setConfigurable(!mChannel.isImportanceLockedByOEM());
pref.setImportance(mChannel.getImportance());
pref.setDisplayInStatusBar(mBackend.showSilentInStatusBar(mContext.getPackageName()));
// TODO: b/128445911 pass along lock screen setting
pref.setDisplayOnLockscreen(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0) == 1);
}
}

View File

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

View File

@@ -101,7 +101,7 @@ public class SimSettings extends RestrictedSettingsFragment implements Indexable
mSimCards = (PreferenceScreen)findPreference(SIM_CARD_CATEGORY);
mAvailableSubInfos = new ArrayList<SubscriptionInfo>(mNumSlots);
mSelectableSubInfos = new ArrayList<SubscriptionInfo>();
SimSelectNotification.cancelNotification(getActivity());
SimSelectNotification.cancelSimSelectNotification(getActivity());
}
private final SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangeListener

View File

@@ -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<LocalBluetoothManager> 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<BluetoothDevice> getConnectableA2dpDevices() {
protected List<BluetoothDevice> 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<BluetoothDevice> getConnectableHearingAidDevices() {
final List<BluetoothDevice> connectedDevices = new ArrayList<>();
final HearingAidProfile hapProfile = mProfileManager.getHearingAidProfile();
if (hapProfile == null) {
return connectedDevices;
}
final List<Long> devicesHiSyncIds = new ArrayList<>();
final List<BluetoothDevice> 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) {
}
}
}

View File

@@ -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<BluetoothDevice> connectableA2dpDevices = getConnectableA2dpDevices();
List<BluetoothDevice> connectableHADevices = getConnectableHearingAidDevices();
List<BluetoothDevice> connectedA2dpDevices = getConnectedA2dpDevices();
List<BluetoothDevice> 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());

View File

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

View File

@@ -47,12 +47,14 @@ import java.util.List;
* <p>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<WifiDialog.WifiDialogListener> 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);
}
}
}

View File

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

View File

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

View File

@@ -29,7 +29,10 @@ import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.settings.R;
@@ -110,8 +113,8 @@ public class ImportancePreferenceTest {
assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(selected);
assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
.isEqualTo(unselected);
assertThat(((TextView) holder.itemView.findViewById(R.id.description)).getText()).isEqualTo(
mContext.getString(R.string.notification_channel_summary_default));
assertThat(((TextView) holder.itemView.findViewById(R.id.alert_summary)).getText())
.isEqualTo(mContext.getString(R.string.notification_channel_summary_default));
}
@Test
@@ -129,28 +132,32 @@ public class ImportancePreferenceTest {
preference.setImportance(IMPORTANCE_DEFAULT);
preference.onBindViewHolder(holder);
Button silenceButton = holder.itemView.findViewById(R.id.silence);
View silenceButton = holder.itemView.findViewById(R.id.silence);
silenceButton.callOnClick();
assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
assertThat(holder.itemView.findViewById(R.id.silence).getBackground()).isEqualTo(selected);
assertThat(((TextView) holder.itemView.findViewById(R.id.description)).getText()).isEqualTo(
mContext.getString(R.string.notification_channel_summary_low));
verify(preference, times(1)).callChangeListener(IMPORTANCE_LOW);
}
@Test
public void setImportanceSummary_status() {
ViewGroup parent = new LinearLayout(mContext);
TextView tv = new TextView(mContext);
tv.setId(R.id.silence_summary);
parent.addView(tv);
TextView other = new TextView(mContext);
other.setId(R.id.alert_summary);
parent.addView(other);
final ImportancePreference preference = spy(new ImportancePreference(mContext));
preference.setDisplayInStatusBar(true);
preference.setDisplayOnLockscreen(false);
preference.setImportanceSummary(tv, IMPORTANCE_LOW);
preference.setImportanceSummary(parent, IMPORTANCE_LOW, true);
assertThat(tv.getText()).isEqualTo(
mContext.getString(R.string.notification_channel_summary_low_status));
@@ -158,14 +165,20 @@ public class ImportancePreferenceTest {
@Test
public void setImportanceSummary_lock() {
ViewGroup parent = new LinearLayout(mContext);
TextView tv = new TextView(mContext);
tv.setId(R.id.silence_summary);
parent.addView(tv);
TextView other = new TextView(mContext);
other.setId(R.id.alert_summary);
parent.addView(other);
final ImportancePreference preference = spy(new ImportancePreference(mContext));
preference.setDisplayInStatusBar(false);
preference.setDisplayOnLockscreen(true);
preference.setImportanceSummary(tv, IMPORTANCE_LOW);
preference.setImportanceSummary(parent, IMPORTANCE_LOW, true);
assertThat(tv.getText()).isEqualTo(
mContext.getString(R.string.notification_channel_summary_low_lock));
@@ -173,14 +186,20 @@ public class ImportancePreferenceTest {
@Test
public void setImportanceSummary_statusLock() {
ViewGroup parent = new LinearLayout(mContext);
TextView tv = new TextView(mContext);
tv.setId(R.id.silence_summary);
parent.addView(tv);
TextView other = new TextView(mContext);
other.setId(R.id.alert_summary);
parent.addView(other);
final ImportancePreference preference = spy(new ImportancePreference(mContext));
preference.setDisplayInStatusBar(true);
preference.setDisplayOnLockscreen(true);
preference.setImportanceSummary(tv, IMPORTANCE_LOW);
preference.setImportanceSummary(parent, IMPORTANCE_LOW, true);
assertThat(tv.getText()).isEqualTo(
mContext.getString(R.string.notification_channel_summary_low_status_lock));
@@ -188,14 +207,20 @@ public class ImportancePreferenceTest {
@Test
public void setImportanceSummary_statusLock_default() {
ViewGroup parent = new LinearLayout(mContext);
TextView tv = new TextView(mContext);
tv.setId(R.id.alert_summary);
parent.addView(tv);
TextView other = new TextView(mContext);
other.setId(R.id.silence_summary);
parent.addView(other);
final ImportancePreference preference = spy(new ImportancePreference(mContext));
preference.setDisplayInStatusBar(true);
preference.setDisplayOnLockscreen(true);
preference.setImportanceSummary(tv, IMPORTANCE_DEFAULT);
preference.setImportanceSummary(parent, IMPORTANCE_DEFAULT, true);
assertThat(tv.getText()).isEqualTo(
mContext.getString(R.string.notification_channel_summary_default));

View File

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

View File

@@ -109,7 +109,7 @@ public class MediaOutputPreferenceControllerTest {
private BluetoothDevice mRightBluetoothHapDevice;
private LocalBluetoothManager mLocalBluetoothManager;
private MediaOutputPreferenceController mController;
private List<BluetoothDevice> mProfileConnectableDevices;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> 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);