Merge "Baseline NewApi issues" into main
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index d8d8450..bed13e3 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -156,8 +156,8 @@
 import android.telephony.satellite.INtnSignalStrengthCallback;
 import android.telephony.satellite.ISatelliteCapabilitiesCallback;
 import android.telephony.satellite.ISatelliteDatagramCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
 import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteStateCallback;
 import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.NtnSignalStrength;
 import android.telephony.satellite.NtnSignalStrengthCallback;
@@ -411,6 +411,8 @@
     private static final int MIN_NULL_CIPHER_AND_INTEGRITY_VERSION = 201;
     // Cellular identifier disclosure transparency was added in IRadioNetwork 2.2
     private static final int MIN_IDENTIFIER_DISCLOSURE_VERSION = 202;
+    // Null cipher notification support was added in IRadioNetwork 2.2
+    private static final int MIN_NULL_CIPHER_NOTIFICATION_VERSION = 202;
 
     /** The singleton instance. */
     private static PhoneInterfaceManager sInstance;
@@ -12795,6 +12797,17 @@
         }
     }
 
+    private void checkForNullCipherNotificationSupport() {
+        if (getHalVersion(HAL_SERVICE_NETWORK) < MIN_NULL_CIPHER_NOTIFICATION_VERSION) {
+            throw new UnsupportedOperationException(
+                    "Null cipher notification operations require HAL 2.2 or above");
+        }
+        if (!getDefaultPhone().isNullCipherNotificationSupported()) {
+            throw new UnsupportedOperationException(
+                    "Null cipher notification operations unsupported by modem");
+        }
+    }
+
     /**
      * Get the SIM state for the slot index.
      * For Remote-SIMs, this method returns {@link IccCardConstants.State#UNKNOWN}
@@ -13195,7 +13208,7 @@
      */
     @Override
     @SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
-            @NonNull ISatelliteStateCallback callback) {
+            @NonNull ISatelliteModemStateCallback callback) {
         enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChanged");
         return mSatelliteController.registerForSatelliteModemStateChanged(subId, callback);
     }
@@ -13206,13 +13219,13 @@
      *
      * @param subId The subId of the subscription to unregister for satellite modem state changed.
      * @param callback The callback that was passed to
-     *                 {@link #registerForSatelliteModemStateChanged(int, ISatelliteStateCallback)}.
+     * {@link #registerForSatelliteModemStateChanged(int, ISatelliteModemStateCallback)}.
      *
      * @throws SecurityException if the caller doesn't have the required permission.
      */
     @Override
     public void unregisterForSatelliteModemStateChanged(int subId,
-            @NonNull ISatelliteStateCallback callback) {
+            @NonNull ISatelliteModemStateCallback callback) {
         enforceSatelliteCommunicationPermission("unregisterForSatelliteModemStateChanged");
         mSatelliteController.unregisterForSatelliteModemStateChanged(subId, callback);
     }
@@ -13760,6 +13773,49 @@
     }
 
     /**
+     * Enables or disables notifications sent when cellular null cipher or integrity algorithms
+     * are in use by the cellular modem.
+     *
+     * @throws IllegalStateException if the Telephony process is not currently available
+     * @throws SecurityException if the caller does not have the required privileges
+     * @throws UnsupportedOperationException if the modem does not support reporting on ciphering
+     * and integrity algorithms in use
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void setEnableNullCipherNotifications(boolean enable) {
+        enforceModifyPermission();
+        checkForNullCipherNotificationSupport();
+
+        SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
+        editor.putBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, enable);
+        editor.apply();
+
+        // Each phone instance is responsible for updating its respective modem immediately
+        // after a preference change.
+        for (Phone phone : PhoneFactory.getPhones()) {
+            phone.handleNullCipherNotificationPreferenceChanged();
+        }
+    }
+
+    /**
+     * Get whether notifications are enabled for null cipher or integrity algorithms in use by the
+     * cellular modem.
+     *
+     * @throws IllegalStateException if the Telephony process is not currently available
+     * @throws SecurityException if the caller does not have the required privileges
+     * @throws UnsupportedOperationException if the modem does not support reporting on ciphering
+     * and integrity algorithms in use
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public boolean isNullCipherNotificationsEnabled() {
+        enforceReadPrivilegedPermission("isNullCipherNotificationsEnabled");
+        checkForNullCipherNotificationSupport();
+        return getDefaultPhone().getNullCipherNotificationsPreferenceEnabled();
+    }
+
+    /**
      * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
      *
      * <p>This method behaves in one of the following ways:
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index adb07f9..91ecb93 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -31,7 +31,7 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.phone.ImsUtil;
 import com.android.phone.PhoneGlobals;
-import com.android.phone.common.R;
+import com.android.phone.R;
 
 public class DisconnectCauseUtil {
 
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
index 97f676f..8ffbc0a 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
@@ -33,7 +33,7 @@
 import android.telephony.satellite.SatelliteDatagram;
 import android.telephony.satellite.SatelliteDatagramCallback;
 import android.telephony.satellite.SatelliteManager;
-import android.telephony.satellite.SatelliteStateCallback;
+import android.telephony.satellite.SatelliteModemStateCallback;
 import android.telephony.satellite.SatelliteTransmissionUpdateCallback;
 import android.telephony.satellite.stub.SatelliteResult;
 import android.util.Log;
@@ -61,7 +61,7 @@
 
     private SatelliteManager mSatelliteManager;
     private SatelliteDatagramCallbackTestApp mDatagramCallback;
-    private SatelliteStateCallbackTestApp mStateCallback;
+    private SatelliteModemStateCallbackTestApp mStateCallback;
     private SatelliteTransmissionUpdateCallbackTestApp mCallback;
     private android.telephony.satellite.stub.SatelliteDatagram mReceivedDatagram;
 
@@ -75,7 +75,7 @@
         super.onCreate(savedInstanceState);
         mSatelliteManager = getSystemService(SatelliteManager.class);
         mDatagramCallback = new SatelliteDatagramCallbackTestApp();
-        mStateCallback = new SatelliteStateCallbackTestApp();
+        mStateCallback = new SatelliteModemStateCallbackTestApp();
         mCallback = new SatelliteTransmissionUpdateCallbackTestApp();
 
         mReceivedDatagram = new android.telephony.satellite.stub.SatelliteDatagram();
@@ -121,7 +121,7 @@
         }
     }
 
-    protected class SatelliteStateCallbackTestApp implements SatelliteStateCallback {
+    protected class SatelliteModemStateCallbackTestApp implements SatelliteModemStateCallback {
         @Override
         public void onSatelliteModemStateChanged(int state) {
             mModemState = state;
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index 611373f..b00a750 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -108,6 +108,7 @@
         TelephonyManager.setupISubForTest(mSubscriptionManagerService);
         mSharedPreferences = mPhoneInterfaceManager.getSharedPreferences();
         mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED).commit();
+        mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED).commit();
         mIIntegerConsumer = mock(IIntegerConsumer.class);
 
         // In order not to affect the existing implementation, define a telephony features
@@ -292,6 +293,108 @@
                 mPhoneInterfaceManager).getDefaultPhone();
     }
 
+    @Test
+    public void setEnableNullCipherNotifications_allReqsMet_successfullyEnabled() {
+        setModemSupportsNullCipherNotification(true);
+        doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED));
+
+        mPhoneInterfaceManager.setEnableNullCipherNotifications(true);
+
+        assertTrue(
+                mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, false));
+    }
+
+    @Test
+    public void setEnableNullCipherNotifications_allReqsMet_successfullyDisabled() {
+        setModemSupportsNullCipherNotification(true);
+        doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED));
+
+        mPhoneInterfaceManager.setEnableNullCipherNotifications(false);
+
+        assertFalse(
+                mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, true));
+    }
+
+    @Test
+    public void setEnableNullCipherNotifications_lackingNecessaryHal_throwsException() {
+        setModemSupportsNullCipherNotification(true);
+        doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+        doReturn(102).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+
+        assertThrows(UnsupportedOperationException.class,
+                () -> mPhoneInterfaceManager.setEnableNullCipherNotifications(true));
+    }
+
+    @Test
+    public void setEnableNullCipherNotifications_lackingModemSupport_throwsException() {
+        setModemSupportsNullCipherNotification(false);
+        doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+
+        assertThrows(UnsupportedOperationException.class,
+                () -> mPhoneInterfaceManager.setEnableNullCipherNotifications(true));
+    }
+
+    @Test
+    public void setEnableNullCipherNotifications_lackingPermissions_throwsException() {
+        setModemSupportsNullCipherNotification(true);
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceModifyPermission();
+
+        assertThrows(SecurityException.class, () ->
+                mPhoneInterfaceManager.setEnableNullCipherNotifications(true));
+    }
+
+    @Test
+    public void isNullCipherNotificationsEnabled_allReqsMet_returnsTrue() {
+        setModemSupportsNullCipherNotification(true);
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+        doReturn(true).when(mPhone).getNullCipherNotificationsPreferenceEnabled();
+
+        assertTrue(mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+    }
+
+    @Test
+    public void isNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException() {
+        setModemSupportsNullCipherNotification(true);
+        doReturn(102).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+
+        assertThrows(UnsupportedOperationException.class, () ->
+                mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+    }
+
+    @Test
+    public void isNullCipherNotificationsEnabled_lackingModemSupport_throwsException() {
+        setModemSupportsNullCipherNotification(false);
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+
+        assertThrows(UnsupportedOperationException.class, () ->
+                mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+    }
+
+    @Test
+    public void isNullCipherNotificationsEnabled_lackingPermissions_throwsException() {
+        setModemSupportsNullCipherNotification(true);
+        doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+        doThrow(SecurityException.class).when(
+                mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+
+        assertThrows(SecurityException.class, () ->
+                mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+    }
+
+    private void setModemSupportsNullCipherNotification(boolean enable) {
+        doReturn(enable).when(mPhone).isNullCipherNotificationSupported();
+        doReturn(mPhone).when(mPhoneInterfaceManager).getDefaultPhone();
+    }
+
     /**
      * Verify getCarrierRestrictionStatus throws exception for invalid caller package name.
      */
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 16a5cdb..e5f7fd3 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -41,7 +41,7 @@
 import com.android.internal.telephony.GsmCdmaPhone;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
-import com.android.phone.common.R;
+import com.android.phone.R;
 
 import org.junit.Before;
 import org.junit.Test;