Add API to listen to opportunistic subscriptions change.

Add a new set of APIs so that caller can listen to
opportunistic subscriptions changes.

Bug: 92796390
Test: build
Change-Id: Iaa741141bf1bd04c4b1618d5bfeac733a0690ed8
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index c44a81e..98b88cb 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -101,6 +101,7 @@
 
         IPhoneStateListener callback;
         IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
+        IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
 
         int callerUid;
         int callerPid;
@@ -119,6 +120,10 @@
             return (onSubscriptionsChangedListenerCallback != null);
         }
 
+        boolean matchOnOpportunisticSubscriptionsChangedListener() {
+            return (onOpportunisticSubscriptionsChangedListenerCallback != null);
+        }
+
         boolean canReadCallLog() {
             try {
                 return TelephonyPermissions.checkReadCallLog(
@@ -133,7 +138,9 @@
             return "{callingPackage=" + callingPackage + " binder=" + binder
                     + " callback=" + callback
                     + " onSubscriptionsChangedListenererCallback="
-                                            + onSubscriptionsChangedListenerCallback
+                    + onSubscriptionsChangedListenerCallback
+                    + " onOpportunisticSubscriptionsChangedListenererCallback="
+                    + onOpportunisticSubscriptionsChangedListenerCallback
                     + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
                     + " events=" + Integer.toHexString(events) + "}";
         }
@@ -149,7 +156,9 @@
 
     private final AppOpsManager mAppOps;
 
-    private boolean hasNotifySubscriptionInfoChangedOccurred = false;
+    private boolean mHasNotifySubscriptionInfoChangedOccurred = false;
+
+    private boolean mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = false;
 
     private int mNumPhones;
 
@@ -410,7 +419,7 @@
                 log("listen oscl:  Register r=" + r);
             }
             // Always notify when registration occurs if there has been a notification.
-            if (hasNotifySubscriptionInfoChangedOccurred) {
+            if (mHasNotifySubscriptionInfoChangedOccurred) {
                 try {
                     if (VDBG) log("listen oscl: send to r=" + r);
                     r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
@@ -420,7 +429,7 @@
                     remove(r.binder);
                 }
             } else {
-                log("listen oscl: hasNotifySubscriptionInfoChangedOccurred==false no callback");
+                log("listen oscl: mHasNotifySubscriptionInfoChangedOccurred==false no callback");
             }
         }
     }
@@ -432,15 +441,61 @@
         remove(callback.asBinder());
     }
 
+
+    @Override
+    public void addOnOpportunisticSubscriptionsChangedListener(String callingPackage,
+            IOnSubscriptionsChangedListener callback) {
+        int callerUserId = UserHandle.getCallingUserId();
+        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+        if (VDBG) {
+            log("listen ooscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
+                    + " callerUserId="  + callerUserId + " callback=" + callback
+                    + " callback.asBinder=" + callback.asBinder());
+        }
+
+        synchronized (mRecords) {
+            // register
+            IBinder b = callback.asBinder();
+            Record r = add(b);
+
+            if (r == null) {
+                return;
+            }
+
+            r.context = mContext;
+            r.onOpportunisticSubscriptionsChangedListenerCallback = callback;
+            r.callingPackage = callingPackage;
+            r.callerUid = Binder.getCallingUid();
+            r.callerPid = Binder.getCallingPid();
+            r.events = 0;
+            if (DBG) {
+                log("listen ooscl:  Register r=" + r);
+            }
+            // Always notify when registration occurs if there has been a notification.
+            if (mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
+                try {
+                    if (VDBG) log("listen ooscl: send to r=" + r);
+                    r.onOpportunisticSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
+                    if (VDBG) log("listen ooscl: sent to r=" + r);
+                } catch (RemoteException e) {
+                    if (VDBG) log("listen ooscl: remote exception sending to r=" + r + " e=" + e);
+                    remove(r.binder);
+                }
+            } else {
+                log("listen ooscl: hasNotifyOpptSubInfoChangedOccurred==false no callback");
+            }
+        }
+    }
+
     @Override
     public void notifySubscriptionInfoChanged() {
         if (VDBG) log("notifySubscriptionInfoChanged:");
         synchronized (mRecords) {
-            if (!hasNotifySubscriptionInfoChangedOccurred) {
+            if (!mHasNotifySubscriptionInfoChangedOccurred) {
                 log("notifySubscriptionInfoChanged: first invocation mRecords.size="
                         + mRecords.size());
             }
-            hasNotifySubscriptionInfoChangedOccurred = true;
+            mHasNotifySubscriptionInfoChangedOccurred = true;
             mRemoveList.clear();
             for (Record r : mRecords) {
                 if (r.matchOnSubscriptionsChangedListener()) {
@@ -459,6 +514,33 @@
     }
 
     @Override
+    public void notifyOpportunisticSubscriptionInfoChanged() {
+        if (VDBG) log("notifyOpptSubscriptionInfoChanged:");
+        synchronized (mRecords) {
+            if (!mHasNotifyOpportunisticSubscriptionInfoChangedOccurred) {
+                log("notifyOpptSubscriptionInfoChanged: first invocation mRecords.size="
+                        + mRecords.size());
+            }
+            mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = true;
+            mRemoveList.clear();
+            for (Record r : mRecords) {
+                if (r.matchOnOpportunisticSubscriptionsChangedListener()) {
+                    try {
+                        if (VDBG) log("notifyOpptSubChanged: call oosc to r=" + r);
+                        r.onOpportunisticSubscriptionsChangedListenerCallback
+                                .onSubscriptionsChanged();
+                        if (VDBG) log("notifyOpptSubChanged: done oosc to r=" + r);
+                    } catch (RemoteException ex) {
+                        if (VDBG) log("notifyOpptSubChanged: RemoteException r=" + r);
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
+    @Override
     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
             boolean notifyNow) {
         listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,