Loading src/java/com/android/internal/telephony/satellite/SatelliteController.java +90 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.internal.telephony.satellite; import static android.provider.Settings.ACTION_SATELLITE_SETTING; import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT; Loading @@ -33,6 +34,10 @@ import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCC import android.annotation.ArrayRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; import android.content.ContentResolver; Loading @@ -42,6 +47,7 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; import android.net.wifi.WifiManager; import android.nfc.NfcAdapter; import android.os.AsyncResult; Loading @@ -62,6 +68,7 @@ import android.os.ResultReceiver; import android.os.ServiceSpecificException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.Rlog; Loading Loading @@ -335,6 +342,16 @@ public class SatelliteController extends Handler { @GuardedBy("mSupportedSatelliteServicesLock") private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); /** Key used to read/write satellite system notification done in shared preferences. */ private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = "satellite_system_notification_done_key"; // The notification tag used when showing a notification. The combination of notification tag // and notification id should be unique within the phone app. private static final String NOTIFICATION_TAG = "SatelliteController"; private static final int NOTIFICATION_ID = 1; private static final String NOTIFICATION_CHANNEL = "satelliteChannel"; private static final String NOTIFICATION_CHANNEL_ID = "satellite"; /** * @return The singleton instance of SatelliteController. */ Loading Loading @@ -3462,6 +3479,7 @@ public class SatelliteController extends Handler { private void handleEventServiceStateChanged() { handleServiceStateForSatelliteConnectionViaCarrier(); determineSystemNotification(); } private void handleServiceStateForSatelliteConnectionViaCarrier() { Loading Loading @@ -3598,6 +3616,78 @@ public class SatelliteController extends Handler { return true; } private void determineSystemNotification() { if (isUsingNonTerrestrialNetworkViaCarrier()) { if (mSharedPreferences == null) { try { mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF, Context.MODE_PRIVATE); } catch (Exception e) { loge("Cannot get default shared preferences: " + e); } } if (mSharedPreferences == null) { loge("handleEventServiceStateChanged: Cannot get default shared preferences"); return; } if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) { showSatelliteSystemNotification(); mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, true).apply(); } } } private void showSatelliteSystemNotification() { logd("showSatelliteSystemNotification"); final NotificationChannel notificationChannel = new NotificationChannel( NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL, NotificationManager.IMPORTANCE_DEFAULT ); notificationChannel.setSound(null, null); NotificationManager notificationManager = mContext.getSystemService( NotificationManager.class); notificationManager.createNotificationChannel(notificationChannel); Notification.Builder notificationBuilder = new Notification.Builder(mContext) .setContentTitle(mContext.getResources().getString( R.string.satellite_notification_title)) .setContentText(mContext.getResources().getString( R.string.satellite_notification_summary)) .setSmallIcon(R.drawable.ic_satellite_alt_24px) .setChannelId(NOTIFICATION_CHANNEL_ID) .setAutoCancel(true) .setColor(mContext.getColor( com.android.internal.R.color.system_notification_accent_color)) .setVisibility(Notification.VISIBILITY_PUBLIC); // Add action to invoke `What to expect` dialog of Messaging application. Intent intentOpenMessage = new Intent(Intent.ACTION_VIEW); intentOpenMessage.setData(Uri.parse("sms:")); // TODO : b/322733285 add putExtra to invoke "What to expect" dialog. PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0, intentOpenMessage, PendingIntent.FLAG_IMMUTABLE); Notification.Action actionOpenMessage = new Notification.Action.Builder(0, mContext.getResources().getString(R.string.satellite_notification_open_message), pendingIntentOpenMessage).build(); notificationBuilder.addAction(actionOpenMessage); // Add action to invoke Satellite setting activity in Settings. Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING); PendingIntent pendingIntentSatelliteSetting = PendingIntent.getActivity(mContext, 0, intentSatelliteSetting, PendingIntent.FLAG_IMMUTABLE); Notification.Action actionOpenSatelliteSetting = new Notification.Action.Builder(null, mContext.getResources().getString(R.string.satellite_notification_how_it_works), pendingIntentSatelliteSetting).build(); notificationBuilder.addAction(actionOpenSatelliteSetting); notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, notificationBuilder.build(), UserHandle.ALL); } private static void logd(@NonNull String log) { Rlog.d(TAG, log); } Loading tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java +39 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.app.NotificationManager; import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncResult; Loading Loading @@ -159,7 +160,10 @@ public class SatelliteControllerTest extends TelephonyTest { private static final String TEST_NEXT_SATELLITE_TOKEN = "TEST_NEXT_SATELLITE_TOKEN"; private static final String[] EMPTY_STRING_ARRAY = {}; private static final List<String> EMPTY_STRING_LIST = new ArrayList<>(); private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = "satellite_system_notification_done_key"; private static final int[] ACTIVE_SUB_IDS = {SUB_ID}; private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>> mCarrierConfigChangedListenerList = new ArrayList<>(); Loading @@ -176,6 +180,7 @@ public class SatelliteControllerTest extends TelephonyTest { @Mock private ProvisionMetricsStats mMockProvisionMetricsStats; @Mock private SessionMetricsStats mMockSessionMetricsStats; @Mock private SubscriptionManagerService mMockSubscriptionManagerService; @Mock private NotificationManager mMockNotificationManager; private List<Integer> mIIntegerConsumerResults = new ArrayList<>(); @Mock private ISatelliteTransmissionUpdateCallback mStartTransmissionUpdateCallback; @Mock private ISatelliteTransmissionUpdateCallback mStopTransmissionUpdateCallback; Loading Loading @@ -503,6 +508,13 @@ public class SatelliteControllerTest extends TelephonyTest { doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics(); doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt()); when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true); doReturn(mSST).when(mPhone).getServiceStateTracker(); doReturn(mSST).when(mPhone2).getServiceStateTracker(); doReturn(mServiceState).when(mSST).getServiceState(); doReturn(Context.NOTIFICATION_SERVICE).when(mContext).getSystemServiceName( NotificationManager.class); doReturn(mMockNotificationManager).when(mContext).getSystemService( Context.NOTIFICATION_SERVICE); mSatelliteControllerUT = new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags); verify(mMockSatelliteModemInterface).registerForSatelliteProvisionStateChanged( Loading Loading @@ -2869,6 +2881,33 @@ public class SatelliteControllerTest extends TelephonyTest { assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1)); } @Test public void testHandleEventServiceStateChanged() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); // Do nothing when the satellite is not connected doReturn(false).when(mServiceState).isUsingNonTerrestrialNetwork(); sendServiceStateChangedEvent(); processAllMessages(); assertEquals(false, mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)); verify(mMockNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any()); // Check sending a system notification when the satellite is connected doReturn(true).when(mServiceState).isUsingNonTerrestrialNetwork(); sendServiceStateChangedEvent(); processAllMessages(); verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(), any()); assertEquals(true, mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)); // Check don't display again after displayed already a system notification. sendServiceStateChangedEvent(); processAllMessages(); verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(), any()); } private void resetSatelliteControllerUTEnabledState() { logd("resetSatelliteControllerUTEnabledState"); setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE); Loading Loading
src/java/com/android/internal/telephony/satellite/SatelliteController.java +90 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.internal.telephony.satellite; import static android.provider.Settings.ACTION_SATELLITE_SETTING; import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL; import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT; Loading @@ -33,6 +34,10 @@ import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCC import android.annotation.ArrayRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.content.BroadcastReceiver; import android.content.ContentResolver; Loading @@ -42,6 +47,7 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.database.ContentObserver; import android.net.Uri; import android.net.wifi.WifiManager; import android.nfc.NfcAdapter; import android.os.AsyncResult; Loading @@ -62,6 +68,7 @@ import android.os.ResultReceiver; import android.os.ServiceSpecificException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.Rlog; Loading Loading @@ -335,6 +342,16 @@ public class SatelliteController extends Handler { @GuardedBy("mSupportedSatelliteServicesLock") private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>(); /** Key used to read/write satellite system notification done in shared preferences. */ private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = "satellite_system_notification_done_key"; // The notification tag used when showing a notification. The combination of notification tag // and notification id should be unique within the phone app. private static final String NOTIFICATION_TAG = "SatelliteController"; private static final int NOTIFICATION_ID = 1; private static final String NOTIFICATION_CHANNEL = "satelliteChannel"; private static final String NOTIFICATION_CHANNEL_ID = "satellite"; /** * @return The singleton instance of SatelliteController. */ Loading Loading @@ -3462,6 +3479,7 @@ public class SatelliteController extends Handler { private void handleEventServiceStateChanged() { handleServiceStateForSatelliteConnectionViaCarrier(); determineSystemNotification(); } private void handleServiceStateForSatelliteConnectionViaCarrier() { Loading Loading @@ -3598,6 +3616,78 @@ public class SatelliteController extends Handler { return true; } private void determineSystemNotification() { if (isUsingNonTerrestrialNetworkViaCarrier()) { if (mSharedPreferences == null) { try { mSharedPreferences = mContext.getSharedPreferences(SATELLITE_SHARED_PREF, Context.MODE_PRIVATE); } catch (Exception e) { loge("Cannot get default shared preferences: " + e); } } if (mSharedPreferences == null) { loge("handleEventServiceStateChanged: Cannot get default shared preferences"); return; } if (!mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)) { showSatelliteSystemNotification(); mSharedPreferences.edit().putBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, true).apply(); } } } private void showSatelliteSystemNotification() { logd("showSatelliteSystemNotification"); final NotificationChannel notificationChannel = new NotificationChannel( NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL, NotificationManager.IMPORTANCE_DEFAULT ); notificationChannel.setSound(null, null); NotificationManager notificationManager = mContext.getSystemService( NotificationManager.class); notificationManager.createNotificationChannel(notificationChannel); Notification.Builder notificationBuilder = new Notification.Builder(mContext) .setContentTitle(mContext.getResources().getString( R.string.satellite_notification_title)) .setContentText(mContext.getResources().getString( R.string.satellite_notification_summary)) .setSmallIcon(R.drawable.ic_satellite_alt_24px) .setChannelId(NOTIFICATION_CHANNEL_ID) .setAutoCancel(true) .setColor(mContext.getColor( com.android.internal.R.color.system_notification_accent_color)) .setVisibility(Notification.VISIBILITY_PUBLIC); // Add action to invoke `What to expect` dialog of Messaging application. Intent intentOpenMessage = new Intent(Intent.ACTION_VIEW); intentOpenMessage.setData(Uri.parse("sms:")); // TODO : b/322733285 add putExtra to invoke "What to expect" dialog. PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0, intentOpenMessage, PendingIntent.FLAG_IMMUTABLE); Notification.Action actionOpenMessage = new Notification.Action.Builder(0, mContext.getResources().getString(R.string.satellite_notification_open_message), pendingIntentOpenMessage).build(); notificationBuilder.addAction(actionOpenMessage); // Add action to invoke Satellite setting activity in Settings. Intent intentSatelliteSetting = new Intent(ACTION_SATELLITE_SETTING); PendingIntent pendingIntentSatelliteSetting = PendingIntent.getActivity(mContext, 0, intentSatelliteSetting, PendingIntent.FLAG_IMMUTABLE); Notification.Action actionOpenSatelliteSetting = new Notification.Action.Builder(null, mContext.getResources().getString(R.string.satellite_notification_how_it_works), pendingIntentSatelliteSetting).build(); notificationBuilder.addAction(actionOpenSatelliteSetting); notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID, notificationBuilder.build(), UserHandle.ALL); } private static void logd(@NonNull String log) { Rlog.d(TAG, log); } Loading
tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java +39 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.app.NotificationManager; import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncResult; Loading Loading @@ -159,7 +160,10 @@ public class SatelliteControllerTest extends TelephonyTest { private static final String TEST_NEXT_SATELLITE_TOKEN = "TEST_NEXT_SATELLITE_TOKEN"; private static final String[] EMPTY_STRING_ARRAY = {}; private static final List<String> EMPTY_STRING_LIST = new ArrayList<>(); private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY = "satellite_system_notification_done_key"; private static final int[] ACTIVE_SUB_IDS = {SUB_ID}; private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>> mCarrierConfigChangedListenerList = new ArrayList<>(); Loading @@ -176,6 +180,7 @@ public class SatelliteControllerTest extends TelephonyTest { @Mock private ProvisionMetricsStats mMockProvisionMetricsStats; @Mock private SessionMetricsStats mMockSessionMetricsStats; @Mock private SubscriptionManagerService mMockSubscriptionManagerService; @Mock private NotificationManager mMockNotificationManager; private List<Integer> mIIntegerConsumerResults = new ArrayList<>(); @Mock private ISatelliteTransmissionUpdateCallback mStartTransmissionUpdateCallback; @Mock private ISatelliteTransmissionUpdateCallback mStopTransmissionUpdateCallback; Loading Loading @@ -503,6 +508,13 @@ public class SatelliteControllerTest extends TelephonyTest { doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics(); doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt()); when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true); doReturn(mSST).when(mPhone).getServiceStateTracker(); doReturn(mSST).when(mPhone2).getServiceStateTracker(); doReturn(mServiceState).when(mSST).getServiceState(); doReturn(Context.NOTIFICATION_SERVICE).when(mContext).getSystemServiceName( NotificationManager.class); doReturn(mMockNotificationManager).when(mContext).getSystemService( Context.NOTIFICATION_SERVICE); mSatelliteControllerUT = new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags); verify(mMockSatelliteModemInterface).registerForSatelliteProvisionStateChanged( Loading Loading @@ -2869,6 +2881,33 @@ public class SatelliteControllerTest extends TelephonyTest { assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1)); } @Test public void testHandleEventServiceStateChanged() throws Exception { when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true); // Do nothing when the satellite is not connected doReturn(false).when(mServiceState).isUsingNonTerrestrialNetwork(); sendServiceStateChangedEvent(); processAllMessages(); assertEquals(false, mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)); verify(mMockNotificationManager, never()).notifyAsUser(anyString(), anyInt(), any(), any()); // Check sending a system notification when the satellite is connected doReturn(true).when(mServiceState).isUsingNonTerrestrialNetwork(); sendServiceStateChangedEvent(); processAllMessages(); verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(), any()); assertEquals(true, mSharedPreferences.getBoolean(SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY, false)); // Check don't display again after displayed already a system notification. sendServiceStateChangedEvent(); processAllMessages(); verify(mMockNotificationManager, times(1)).notifyAsUser(anyString(), anyInt(), any(), any()); } private void resetSatelliteControllerUTEnabledState() { logd("resetSatelliteControllerUTEnabledState"); setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE); Loading