Merge "Add API to listen to opportunistic subscriptions change."

am: 26e686a973

Change-Id: I20ba8865169a857e73b4094ac170f63bf41a66a3
This commit is contained in:
Xiangyu/Malcolm Chen
2018-09-11 13:11:24 -07:00
committed by android-build-merger
4 changed files with 213 additions and 9 deletions

View File

@@ -42440,6 +42440,7 @@ package android.telephony {
}
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 boolean canManageSubscription(android.telephony.SubscriptionInfo);
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 java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(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 setSubscriptionOverrideCongested(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
}
public static class SubscriptionManager.OnOpportunisticSubscriptionsChangedListener {
ctor public SubscriptionManager.OnOpportunisticSubscriptionsChangedListener();
method public void onOpportunisticSubscriptionsChanged();
}
public static class SubscriptionManager.OnSubscriptionsChangedListener {
ctor public SubscriptionManager.OnSubscriptionsChangedListener();
method public void onSubscriptionsChanged();

View File

@@ -99,6 +99,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
IOnSubscriptionsChangedListener onOpportunisticSubscriptionsChangedListenerCallback;
int callerUid;
int callerPid;
@@ -117,6 +118,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
return (onSubscriptionsChangedListenerCallback != null);
}
boolean matchOnOpportunisticSubscriptionsChangedListener() {
return (onOpportunisticSubscriptionsChangedListenerCallback != null);
}
boolean canReadCallLog() {
try {
return TelephonyPermissions.checkReadCallLog(
@@ -131,7 +136,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
return "{callingPackage=" + callingPackage + " binder=" + binder
+ " callback=" + callback
+ " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback
+ onSubscriptionsChangedListenerCallback
+ " onOpportunisticSubscriptionsChangedListenererCallback="
+ onOpportunisticSubscriptionsChangedListenerCallback
+ " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
+ " events=" + Integer.toHexString(events) + "}";
}
@@ -147,7 +154,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private final AppOpsManager mAppOps;
private boolean hasNotifySubscriptionInfoChangedOccurred = false;
private boolean mHasNotifySubscriptionInfoChangedOccurred = false;
private boolean mHasNotifyOpportunisticSubscriptionInfoChangedOccurred = false;
private int mNumPhones;
@@ -407,7 +416,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
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();
@@ -417,7 +426,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
} 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());
}
@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()) {
@@ -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
public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
boolean notifyNow) {

View File

@@ -19,6 +19,7 @@ package android.telephony;
import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
import android.annotation.CallbackExecutor;
import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -47,6 +48,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.euicc.EuiccManager;
import android.util.DisplayMetrics;
import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ISub;
@@ -57,6 +59,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
@@ -666,7 +669,7 @@ public class SubscriptionManager {
tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
}
} catch (RemoteException ex) {
// Should not happen
Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
}
}
@@ -684,7 +687,7 @@ public class SubscriptionManager {
+ " listener=" + listener);
}
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"));
@@ -692,7 +695,116 @@ public class SubscriptionManager {
tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
}
} catch (RemoteException ex) {
// Should not happen
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
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);
}
}

View File

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