diff options
author | 2023-06-27 00:14:20 -0700 | |
---|---|---|
committer | 2023-07-11 11:39:27 -0700 | |
commit | b1ff20e42882282c33c0295f4f0ad1db79da061c (patch) | |
tree | ac72c0141835cccd6552ba1e4788c5ec119b0a61 | |
parent | bbbb02338c26629460da5d80e4aee6df823d4f36 (diff) |
Slice upsell fail if notifications are disabled
If notifications are disabled for the app or channel,
fail the purchase request and notify SlicePurchaseController.
Create a new PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED result for
this scenario.
Test: atest CarrierDefaultAppTest
Test: manual verify failure when notifications are disabled
Test: manual verify no regressions of other behavior
Bug: 258083232
Change-Id: I4a3d2b09320edfa232cf87e6235371dc0d84c224
5 files changed, 82 insertions, 21 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 82b880a02111..7dd5eadbbec1 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -46015,6 +46015,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 diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java index 9b33704cc8e7..eccf6047b90c 100644 --- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java +++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java @@ -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)); + } - String carrier = intent.getStringExtra(SlicePurchaseController.EXTRA_CARRIER); + 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); diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java index 61847b517c8d..3c8ef6ed0550 100644 --- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java +++ b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java @@ -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(); + } } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index f86d2b53089c..87a4b2a0f652 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -9628,6 +9628,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 = diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index a3099db9b7a0..efcbd31fb6e4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -17602,6 +17602,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 {} /** |