Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -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 packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java +38 −14 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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"; Loading Loading @@ -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( 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. // 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( Loading Loading @@ -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); Loading packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java +31 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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( Loading @@ -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 Loading Loading @@ -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(); } } telephony/java/android/telephony/CarrierConfigManager.java +1 −0 Original line number Diff line number Diff line Loading @@ -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 = Loading telephony/java/android/telephony/TelephonyManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 {} /** Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -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
packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java +38 −14 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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"; Loading Loading @@ -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( 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. // 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( Loading Loading @@ -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); Loading
packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiverTest.java +31 −6 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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(); Loading Loading @@ -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( Loading @@ -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 Loading Loading @@ -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(); } }
telephony/java/android/telephony/CarrierConfigManager.java +1 −0 Original line number Diff line number Diff line Loading @@ -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 = Loading
telephony/java/android/telephony/TelephonyManager.java +11 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 {} /**