summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sarah Chin <sarahchin@google.com> 2023-06-27 00:14:20 -0700
committer Sarah Chin <sarahchin@google.com> 2023-07-11 11:39:27 -0700
commitb1ff20e42882282c33c0295f4f0ad1db79da061c (patch)
treeac72c0141835cccd6552ba1e4788c5ec119b0a61
parentbbbb02338c26629460da5d80e4aee6df823d4f36 (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
-rw-r--r--core/api/current.txt1
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java52
-rw-r--r--packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java37
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java1
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java12
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 {}
/**