Implement cellular cipher transparency APIs

This commit provides the service-side implementation to support
null cipher notifications exposed through the TelephonyManager APIs.

Bug: 316592273
Test: atest android.telephony.cts.TelephonyManagerTest
Change-Id: Ib8e12b642c68f6de1f54bed29b862e08307f6d95
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 8f3281c..29c0642 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -403,6 +403,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;
@@ -12022,6 +12024,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}
@@ -12901,6 +12914,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: