Merge "Slice upsell fail if notifications are disabled" into main

This commit is contained in:
TreeHugger Robot
2023-07-15 00:22:55 +00:00
committed by Android (Google) Code Review
5 changed files with 82 additions and 21 deletions

View File

@@ -46018,6 +46018,7 @@ package android.telephony {
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED = 2; // 0x2
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT = 9; // 0x9
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED = 6; // 0x6
field public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED = 16; // 0x10
field public static final int SET_OPPORTUNISTIC_SUB_INACTIVE_SUBSCRIPTION = 2; // 0x2
field public static final int SET_OPPORTUNISTIC_SUB_NO_OPPORTUNISTIC_SUB_AVAILABLE = 3; // 0x3
field public static final int SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION = 4; // 0x4

View File

@@ -191,6 +191,8 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
&& isPendingIntentValid(intent, SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED)
&& isPendingIntentValid(intent,
SlicePurchaseController.EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION)
&& isPendingIntentValid(intent,
SlicePurchaseController.EXTRA_INTENT_NOTIFICATIONS_DISABLED)
&& isPendingIntentValid(intent, SlicePurchaseController.EXTRA_INTENT_SUCCESS)
&& isPendingIntentValid(intent,
SlicePurchaseController.EXTRA_INTENT_NOTIFICATION_SHOWN);
@@ -276,6 +278,8 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
case SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED: return "request failed";
case SlicePurchaseController.EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION:
return "not default data subscription";
case SlicePurchaseController.EXTRA_INTENT_NOTIFICATIONS_DISABLED:
return "notifications disabled";
case SlicePurchaseController.EXTRA_INTENT_SUCCESS: return "success";
case SlicePurchaseController.EXTRA_INTENT_NOTIFICATION_SHOWN:
return "notification shown";
@@ -321,26 +325,45 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
}
private void onDisplayPerformanceBoostNotification(@NonNull Context context,
@NonNull Intent intent, boolean repeat) {
if (!repeat && !isIntentValid(intent)) {
@NonNull Intent intent, boolean localeChanged) {
if (!localeChanged && !isIntentValid(intent)) {
sendSlicePurchaseAppResponse(intent,
SlicePurchaseController.EXTRA_INTENT_REQUEST_FAILED);
return;
}
Resources res = getResources(context);
NotificationChannel channel = new NotificationChannel(
PERFORMANCE_BOOST_NOTIFICATION_CHANNEL_ID,
res.getString(R.string.performance_boost_notification_channel),
NotificationManager.IMPORTANCE_DEFAULT);
// CarrierDefaultApp notifications are unblockable by default. Make this channel blockable
// to allow users to disable notifications posted to this channel without affecting other
// notifications in this application.
channel.setBlockable(true);
context.getSystemService(NotificationManager.class).createNotificationChannel(channel);
NotificationManager notificationManager =
context.getSystemService(NotificationManager.class);
NotificationChannel channel = notificationManager.getNotificationChannel(
PERFORMANCE_BOOST_NOTIFICATION_CHANNEL_ID);
if (channel == null) {
channel = new NotificationChannel(
PERFORMANCE_BOOST_NOTIFICATION_CHANNEL_ID,
res.getString(R.string.performance_boost_notification_channel),
NotificationManager.IMPORTANCE_DEFAULT);
// CarrierDefaultApp notifications are unblockable by default.
// Make this channel blockable to allow users to disable notifications posted to this
// channel without affecting other notifications in this application.
channel.setBlockable(true);
context.getSystemService(NotificationManager.class).createNotificationChannel(channel);
} else if (localeChanged) {
// If the channel already exists but the locale has changed, update the channel name.
channel.setName(res.getString(R.string.performance_boost_notification_channel));
}
boolean channelNotificationsDisabled =
channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
if (channelNotificationsDisabled || !notificationManager.areNotificationsEnabled()) {
// If notifications are disabled for the app or channel, fail the purchase request.
logd("Purchase request failed because notifications are disabled for the "
+ (channelNotificationsDisabled ? "channel." : "application."));
sendSlicePurchaseAppResponse(intent,
SlicePurchaseController.EXTRA_INTENT_NOTIFICATIONS_DISABLED);
return;
}
String carrier = intent.getStringExtra(SlicePurchaseController.EXTRA_CARRIER);
Notification notification =
new Notification.Builder(context, PERFORMANCE_BOOST_NOTIFICATION_CHANNEL_ID)
.setContentTitle(res.getString(
@@ -369,11 +392,12 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
int capability = intent.getIntExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
SlicePurchaseController.PREMIUM_CAPABILITY_INVALID);
logd((repeat ? "Update" : "Display") + " the performance boost notification for capability "
logd((localeChanged ? "Update" : "Display")
+ " the performance boost notification for capability "
+ TelephonyManager.convertPremiumCapabilityToString(capability));
context.getSystemService(NotificationManager.class).notifyAsUser(
PERFORMANCE_BOOST_NOTIFICATION_TAG, capability, notification, UserHandle.ALL);
if (!repeat) {
if (!localeChanged) {
sIntents.put(capability, intent);
sendSlicePurchaseAppResponse(intent,
SlicePurchaseController.EXTRA_INTENT_NOTIFICATION_SHOWN);

View File

@@ -32,6 +32,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -72,6 +73,7 @@ public class SlicePurchaseBroadcastReceiverTest {
@Mock PendingIntent mContentIntent1;
@Mock PendingIntent mContentIntent2;
@Mock PendingIntent mNotificationShownIntent;
@Mock PendingIntent mNotificationsDisabledIntent;
@Mock Context mContext;
@Mock Resources mResources;
@Mock Configuration mConfiguration;
@@ -90,6 +92,7 @@ public class SlicePurchaseBroadcastReceiverTest {
doReturn("").when(mResources).getString(anyInt());
doReturn(mNotificationManager).when(mContext)
.getSystemService(eq(NotificationManager.class));
doReturn(true).when(mNotificationManager).areNotificationsEnabled();
doReturn(mApplicationInfo).when(mContext).getApplicationInfo();
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mSpiedResources).when(mContext).getResources();
@@ -221,12 +224,10 @@ public class SlicePurchaseBroadcastReceiverTest {
doReturn(true).when(mPendingIntent).isBroadcast();
doReturn(mPendingIntent).when(mIntent).getParcelableExtra(
anyString(), eq(PendingIntent.class));
doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(mNotificationShownIntent)
.getCreatorPackage();
doReturn(true).when(mNotificationShownIntent).isBroadcast();
doReturn(mNotificationShownIntent).when(mIntent).getParcelableExtra(
eq(SlicePurchaseController.EXTRA_INTENT_NOTIFICATION_SHOWN),
eq(PendingIntent.class));
createValidPendingIntent(mNotificationShownIntent,
SlicePurchaseController.EXTRA_INTENT_NOTIFICATION_SHOWN);
createValidPendingIntent(mNotificationsDisabledIntent,
SlicePurchaseController.EXTRA_INTENT_NOTIFICATIONS_DISABLED);
// spy notification intents to prevent PendingIntent issues
doReturn(mContentIntent1).when(mSlicePurchaseBroadcastReceiver).createContentIntent(
@@ -253,6 +254,12 @@ public class SlicePurchaseBroadcastReceiverTest {
mSlicePurchaseBroadcastReceiver.onReceive(mContext, mIntent);
}
private void createValidPendingIntent(@NonNull PendingIntent intent, @NonNull String extra) {
doReturn(TelephonyManager.PHONE_PROCESS_NAME).when(intent).getCreatorPackage();
doReturn(true).when(intent).isBroadcast();
doReturn(intent).when(mIntent).getParcelableExtra(eq(extra), eq(PendingIntent.class));
}
@Test
public void testNotificationCanceled() {
// send ACTION_NOTIFICATION_CANCELED
@@ -335,4 +342,22 @@ public class SlicePurchaseBroadcastReceiverTest {
clearInvocations(mConfiguration);
return captor.getValue();
}
@Test
public void testNotificationsDisabled() throws Exception {
doReturn(false).when(mNotificationManager).areNotificationsEnabled();
displayPerformanceBoostNotification();
// verify notification was not shown
verify(mNotificationManager, never()).notifyAsUser(
eq(SlicePurchaseBroadcastReceiver.PERFORMANCE_BOOST_NOTIFICATION_TAG),
eq(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY),
any(),
eq(UserHandle.ALL));
verify(mNotificationShownIntent, never()).send();
// verify SlicePurchaseController was notified that notifications are disabled
verify(mNotificationsDisabledIntent).send();
}
}

View File

@@ -9659,6 +9659,7 @@ public class CarrierConfigManager {
*
* @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED
* @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT
* @see TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED
*/
public static final String
KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG =

View File

@@ -17601,6 +17601,15 @@ public class TelephonyManager {
*/
public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP = 15;
/**
* Purchase premium capability failed because the user disabled the feature.
* Subsequent attempts will be throttled for the amount of time specified by
* {@link CarrierConfigManager
* #KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG}
* and return {@link #PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED}.
*/
public static final int PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED = 16;
/**
* Results of the purchase premium capability request.
* @hide
@@ -17620,7 +17629,8 @@ public class TelephonyManager {
PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE,
PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED,
PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION,
PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP})
PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP,
PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED})
public @interface PurchasePremiumCapabilityResult {}
/**