Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 27829e2d authored by Malcolm Chen's avatar Malcolm Chen
Browse files

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
Merged-In: Iaa741141bf1bd04c4b1618d5bfeac733a0690ed8
parent ed8ce392
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -42440,6 +42440,7 @@ package android.telephony {
  }
  }
  public class SubscriptionManager {
  public class SubscriptionManager {
    method public void addOnOpportunisticSubscriptionsChangedListener(java.util.concurrent.Executor, android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
    method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
    method public void addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
    method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
    method public boolean canManageSubscription(android.telephony.SubscriptionInfo);
    method public static deprecated android.telephony.SubscriptionManager from(android.content.Context);
    method public static deprecated android.telephony.SubscriptionManager from(android.content.Context);
@@ -42456,6 +42457,7 @@ package android.telephony {
    method public static int[] getSubscriptionIds(int);
    method public static int[] getSubscriptionIds(int);
    method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
    method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
    method public boolean isNetworkRoaming(int);
    method public boolean isNetworkRoaming(int);
    method public void removeOnOpportunisticSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
    method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
    method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
    method public void setSubscriptionOverrideCongested(int, boolean, long);
    method public void setSubscriptionOverrideCongested(int, boolean, long);
    method public void setSubscriptionOverrideUnmetered(int, boolean, long);
    method public void setSubscriptionOverrideUnmetered(int, boolean, long);
@@ -42471,6 +42473,11 @@ package android.telephony {
    field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
    field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
  }
  }
  public static class SubscriptionManager.OnOpportunisticSubscriptionsChangedListener {
    ctor public SubscriptionManager.OnOpportunisticSubscriptionsChangedListener();
    method public void onOpportunisticSubscriptionsChanged();
  }
  public static class SubscriptionManager.OnSubscriptionsChangedListener {
  public static class SubscriptionManager.OnSubscriptionsChangedListener {
    ctor public SubscriptionManager.OnSubscriptionsChangedListener();
    ctor public SubscriptionManager.OnSubscriptionsChangedListener();
    method public void onSubscriptionsChanged();
    method public void onSubscriptionsChanged();
+88 −6
Original line number Original line Diff line number Diff line
@@ -99,6 +99,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {


        IPhoneStateListener callback;
        IPhoneStateListener callback;
        IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
        IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
        IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;


        int callerUid;
        int callerUid;
        int callerPid;
        int callerPid;
@@ -117,6 +118,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
            return (onSubscriptionsChangedListenerCallback != null);
            return (onSubscriptionsChangedListenerCallback != null);
        }
        }


        boolean matchOnOpportunisticSubscriptionsChangedListener() {
            return (onOpportunisticSubscriptionsChangedListenerCallback != null);
        }

        boolean canReadCallLog() {
        boolean canReadCallLog() {
            try {
            try {
                return TelephonyPermissions.checkReadCallLog(
                return TelephonyPermissions.checkReadCallLog(
@@ -132,6 +137,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
                    + " callback=" + callback
                    + " callback=" + callback
                    + " onSubscriptionsChangedListenererCallback="
                    + " onSubscriptionsChangedListenererCallback="
                    + onSubscriptionsChangedListenerCallback
                    + onSubscriptionsChangedListenerCallback
                    + " onOpportunisticSubscriptionsChangedListenererCallback="
                    + onOpportunisticSubscriptionsChangedListenerCallback
                    + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
                    + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
                    + " events=" + Integer.toHexString(events) + "}";
                    + " events=" + Integer.toHexString(events) + "}";
        }
        }
@@ -147,7 +154,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {


    private final AppOpsManager mAppOps;
    private final AppOpsManager mAppOps;


    private boolean hasNotifySubscriptionInfoChangedOccurred = false;
    private boolean mHasNotifySubscriptionInfoChangedOccurred = false;

    private boolean mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = false;


    private int mNumPhones;
    private int mNumPhones;


@@ -407,7 +416,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
                log("listen oscl:  Register r=" + r);
                log("listen oscl:  Register r=" + r);
            }
            }
            // Always notify when registration occurs if there has been a notification.
            // Always notify when registration occurs if there has been a notification.
            if (hasNotifySubscriptionInfoChangedOccurred) {
            if (mHasNotifySubscriptionInfoChangedOccurred) {
                try {
                try {
                    if (VDBG) log("listen oscl: send to r=" + r);
                    if (VDBG) log("listen oscl: send to r=" + r);
                    r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
                    r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
@@ -417,7 +426,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
                    remove(r.binder);
                    remove(r.binder);
                }
                }
            } else {
            } else {
                log("listen oscl: hasNotifySubscriptionInfoChangedOccurred==false no callback");
                log("listen oscl: mHasNotifySubscriptionInfoChangedOccurred==false no callback");
            }
            }
        }
        }
    }
    }
@@ -429,15 +438,61 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
        remove(callback.asBinder());
        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
    @Override
    public void notifySubscriptionInfoChanged() {
    public void notifySubscriptionInfoChanged() {
        if (VDBG) log("notifySubscriptionInfoChanged:");
        if (VDBG) log("notifySubscriptionInfoChanged:");
        synchronized (mRecords) {
        synchronized (mRecords) {
            if (!hasNotifySubscriptionInfoChangedOccurred) {
            if (!mHasNotifySubscriptionInfoChangedOccurred) {
                log("notifySubscriptionInfoChanged: first invocation mRecords.size="
                log("notifySubscriptionInfoChanged: first invocation mRecords.size="
                        + mRecords.size());
                        + mRecords.size());
            }
            }
            hasNotifySubscriptionInfoChangedOccurred = true;
            mHasNotifySubscriptionInfoChangedOccurred = true;
            mRemoveList.clear();
            mRemoveList.clear();
            for (Record r : mRecords) {
            for (Record r : mRecords) {
                if (r.matchOnSubscriptionsChangedListener()) {
                if (r.matchOnSubscriptionsChangedListener()) {
@@ -455,6 +510,33 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
        }
        }
    }
    }


    @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
    @Override
    public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
    public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
            boolean notifyNow) {
            boolean notifyNow) {
+115 −3
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package android.telephony;
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;


import android.annotation.CallbackExecutor;
import android.annotation.DurationMillisLong;
import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
@@ -47,6 +48,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager;
import android.telephony.euicc.EuiccManager;
import android.telephony.euicc.EuiccManager;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.util.Log;


import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ISub;
@@ -57,6 +59,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.Collections;
import java.util.Collections;
import java.util.List;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;


/**
/**
@@ -666,7 +669,7 @@ public class SubscriptionManager {
                tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
                tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
            }
            }
        } catch (RemoteException ex) {
        } catch (RemoteException ex) {
            // Should not happen
            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
        }
        }
    }
    }


@@ -684,7 +687,116 @@ public class SubscriptionManager {
                    + " listener=" + listener);
                    + " listener=" + listener);
        }
        }
        try {
        try {
            // We use the TelephonyRegistry as its runs in the system and thus is always
            // We use the TelephonyRegistry as it runs in the system and thus is always
            // available where as SubscriptionController could crash and not be available
            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                    "telephony.registry"));
            if (tr != null) {
                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
            }
        } catch (RemoteException ex) {
            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
        }
    }

    /**
     * A listener class for monitoring changes to {@link SubscriptionInfo} records of opportunistic
     * subscriptions.
     * <p>
     * Override the onOpportunisticSubscriptionsChanged method in the object that extends this
     * or {@link #addOnOpportunisticSubscriptionsChangedListener(
     * Executor, OnOpportunisticSubscriptionsChangedListener)}
     * to register your listener and to unregister invoke
     * {@link #removeOnOpportunisticSubscriptionsChangedListener(
     * OnOpportunisticSubscriptionsChangedListener)}
     * <p>
     * Permissions android.Manifest.permission.READ_PHONE_STATE is required
     * for #onOpportunisticSubscriptionsChanged to be invoked.
     */
    public static class OnOpportunisticSubscriptionsChangedListener {
        private Executor mExecutor;
        /**
         * Callback invoked when there is any change to any SubscriptionInfo. Typically
         * this method would invoke {@link #getActiveSubscriptionInfoList}
         */
        public void onOpportunisticSubscriptionsChanged() {
            if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN");
        }

        private void setExecutor(Executor executor) {
            mExecutor = executor;
        }

        /**
         * The callback methods need to be called on the handler thread where
         * this object was created.  If the binder did that for us it'd be nice.
         */
        IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
            @Override
            public void onSubscriptionsChanged() {
                if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
                mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
            }
        };

        private void log(String s) {
            Rlog.d(LOG_TAG, s);
        }
    }

    /**
     * Register for changes to the list of opportunistic subscription records or to the
     * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged
     * method of the listener will be invoked immediately if there has been a notification.
     *
     * @param listener an instance of {@link OnOpportunisticSubscriptionsChangedListener} with
     *                 onOpportunisticSubscriptionsChanged overridden.
     */
    public void addOnOpportunisticSubscriptionsChangedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OnOpportunisticSubscriptionsChangedListener listener) {
        if (executor == null || listener == null) {
            return;
        }

        String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
        if (DBG) {
            logd("register addOnOpportunisticSubscriptionsChangedListener pkgName=" + pkgName
                    + " listener=" + listener);
        }

        listener.setExecutor(executor);

        try {
            // We use the TelephonyRegistry as it runs in the system and thus is always
            // available. Where as SubscriptionController could crash and not be available
            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                    "telephony.registry"));
            if (tr != null) {
                tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback);
            }
        } catch (RemoteException ex) {
            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
        }
    }

    /**
     * Unregister the {@link OnOpportunisticSubscriptionsChangedListener} that is currently
     * listening opportunistic subscriptions change. This is not strictly necessary
     * as the listener will automatically be unregistered if an attempt to invoke the listener
     * fails.
     *
     * @param listener that is to be unregistered.
     */
    public void removeOnOpportunisticSubscriptionsChangedListener(
            OnOpportunisticSubscriptionsChangedListener listener) {
        String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
        if (DBG) {
            logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
                    + pkgForDebug + " listener=" + listener);
        }
        try {
            // We use the TelephonyRegistry as it runs in the system and thus is always
            // available where as SubscriptionController could crash and not be available
            // available where as SubscriptionController could crash and not be available
            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
            ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                    "telephony.registry"));
                    "telephony.registry"));
@@ -692,7 +804,7 @@ public class SubscriptionManager {
                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
                tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
            }
            }
        } catch (RemoteException ex) {
        } catch (RemoteException ex) {
            // Should not happen
            Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
        }
        }
    }
    }


+3 −0
Original line number Original line Diff line number Diff line
@@ -32,6 +32,8 @@ import com.android.internal.telephony.IOnSubscriptionsChangedListener;
interface ITelephonyRegistry {
interface ITelephonyRegistry {
    void addOnSubscriptionsChangedListener(String pkg,
    void addOnSubscriptionsChangedListener(String pkg,
            IOnSubscriptionsChangedListener callback);
            IOnSubscriptionsChangedListener callback);
    void addOnOpportunisticSubscriptionsChangedListener(String pkg,
            IOnSubscriptionsChangedListener callback);
    void removeOnSubscriptionsChangedListener(String pkg,
    void removeOnSubscriptionsChangedListener(String pkg,
            IOnSubscriptionsChangedListener callback);
            IOnSubscriptionsChangedListener callback);
    void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
    void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
@@ -73,6 +75,7 @@ interface ITelephonyRegistry {
            int activationState, int activationType);
            int activationState, int activationType);
    void notifyOemHookRawEventForSubscriber(in int subId, in byte[] rawData);
    void notifyOemHookRawEventForSubscriber(in int subId, in byte[] rawData);
    void notifySubscriptionInfoChanged();
    void notifySubscriptionInfoChanged();
    void notifyOpportunisticSubscriptionInfoChanged();
    void notifyCarrierNetworkChange(in boolean active);
    void notifyCarrierNetworkChange(in boolean active);
    void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
    void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
    void notifyPhoneCapabilityChanged(in PhoneCapability capability);
    void notifyPhoneCapabilityChanged(in PhoneCapability capability);