Merge commit '1d7a53da981b7d4281c58af7eb9b150163b344a6' into manual_merge_1d7a53da981b7d4281c58af7eb9b150163b344a6

Change-Id: Ie08d8bb30e48a9e7ade85334c6195a791ecc0d9b
This commit is contained in:
Hall Liu
2019-11-19 12:37:24 -08:00
10 changed files with 234 additions and 107 deletions

View File

@@ -5669,14 +5669,6 @@ package android.os.storage {
} }
package android.os.telephony {
public class TelephonyRegistryManager {
method public void notifyCarrierNetworkChange(boolean);
}
}
package android.permission { package android.permission {
public final class PermissionControllerManager { public final class PermissionControllerManager {
@@ -8367,6 +8359,15 @@ package android.telephony {
field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0 field public static final int SRVCC_STATE_HANDOVER_STARTED = 0; // 0x0
} }
public class TelephonyRegistryManager {
method public void addOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
method public void addOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener, @NonNull java.util.concurrent.Executor);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyCallStateChangedForAllSubscriptions(int, @Nullable String);
method public void notifyCarrierNetworkChange(boolean);
method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
method public void removeOnSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
}
public final class UiccAccessRule implements android.os.Parcelable { public final class UiccAccessRule implements android.os.Parcelable {
ctor public UiccAccessRule(byte[], @Nullable String, long); ctor public UiccAccessRule(byte[], @Nullable String, long);
method public int describeContents(); method public int describeContents();

View File

@@ -157,7 +157,7 @@ import android.os.health.SystemHealthManager;
import android.os.image.DynamicSystemManager; import android.os.image.DynamicSystemManager;
import android.os.image.IDynamicSystemService; import android.os.image.IDynamicSystemService;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.os.telephony.TelephonyRegistryManager; import android.telephony.TelephonyRegistryManager;
import android.permission.PermissionControllerManager; import android.permission.PermissionControllerManager;
import android.permission.PermissionManager; import android.permission.PermissionManager;
import android.print.IPrintManager; import android.print.IPrintManager;
@@ -611,7 +611,7 @@ final class SystemServiceRegistry {
new CachedServiceFetcher<TelephonyRegistryManager>() { new CachedServiceFetcher<TelephonyRegistryManager>() {
@Override @Override
public TelephonyRegistryManager createService(ContextImpl ctx) { public TelephonyRegistryManager createService(ContextImpl ctx) {
return new TelephonyRegistryManager(); return new TelephonyRegistryManager(ctx);
}}); }});
registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class, registerService(Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class,

View File

@@ -63,6 +63,7 @@ import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.telephony.TelephonyRegistryManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Display; import android.view.Display;
import android.view.DisplayAdjustments; import android.view.DisplayAdjustments;
@@ -4755,7 +4756,7 @@ public abstract class Context {
/** /**
* Use with {@link #getSystemService(String)} to retrieve an * Use with {@link #getSystemService(String)} to retrieve an
* {@link android.os.telephony.TelephonyRegistryManager}. * {@link TelephonyRegistryManager}.
* @hide * @hide
*/ */
@SystemApi @SystemApi

View File

@@ -22,7 +22,7 @@ import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.PersistableBundle; import android.os.PersistableBundle;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.telephony.TelephonyRegistryManager; import android.telephony.TelephonyRegistryManager;
import android.util.Log; import android.util.Log;
/** /**

View File

@@ -35,8 +35,8 @@ import android.telephony.Annotation.SrvccState;
import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsReasonInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.annotations.VisibleForTesting;
import dalvik.system.VMRuntime; import dalvik.system.VMRuntime;

View File

@@ -13,12 +13,20 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package android.os.telephony; package android.telephony;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi; import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
import android.net.LinkProperties; import android.net.LinkProperties;
import android.net.NetworkCapabilities; import android.net.NetworkCapabilities;
import android.os.Binder;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.telephony.Annotation; import android.telephony.Annotation;
@@ -41,8 +49,15 @@ import android.telephony.SignalStrength;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting; import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsReasonInfo;
import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.ITelephonyRegistry;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
/** /**
* A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update * A centralized place to notify telephony related status changes, e.g, {@link ServiceState} update
@@ -59,15 +74,139 @@ public class TelephonyRegistryManager {
private static final String TAG = "TelephonyRegistryManager"; private static final String TAG = "TelephonyRegistryManager";
private static ITelephonyRegistry sRegistry; private static ITelephonyRegistry sRegistry;
private final Context mContext;
/**
* A mapping between {@link SubscriptionManager.OnSubscriptionsChangedListener} and
* its callback IOnSubscriptionsChangedListener.
*/
private final Map<SubscriptionManager.OnSubscriptionsChangedListener,
IOnSubscriptionsChangedListener> mSubscriptionChangedListenerMap = new HashMap<>();
/**
* A mapping between {@link SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} and
* its callback IOnSubscriptionsChangedListener.
*/
private final Map<SubscriptionManager.OnOpportunisticSubscriptionsChangedListener,
IOnSubscriptionsChangedListener> mOpportunisticSubscriptionChangedListenerMap
= new HashMap<>();
/** @hide **/ /** @hide **/
public TelephonyRegistryManager() { public TelephonyRegistryManager(@NonNull Context context) {
mContext = context;
if (sRegistry == null) { if (sRegistry == null) {
sRegistry = ITelephonyRegistry.Stub.asInterface( sRegistry = ITelephonyRegistry.Stub.asInterface(
ServiceManager.getService("telephony.registry")); ServiceManager.getService("telephony.registry"));
} }
} }
/**
* Register for changes to the list of active {@link SubscriptionInfo} records or to the
* individual records themselves. When a change occurs the onSubscriptionsChanged method of
* the listener will be invoked immediately if there has been a notification. The
* onSubscriptionChanged method will also be triggered once initially when calling this
* function.
*
* @param listener an instance of {@link SubscriptionManager.OnSubscriptionsChangedListener}
* with onSubscriptionsChanged overridden.
* @param executor the executor that will execute callbacks.
*/
public void addOnSubscriptionsChangedListener(
@NonNull SubscriptionManager.OnSubscriptionsChangedListener listener,
@NonNull Executor executor) {
IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
@Override
public void onSubscriptionsChanged () {
Log.d(TAG, "onSubscriptionsChangedListener callback received.");
executor.execute(() -> listener.onSubscriptionsChanged());
}
};
mSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnSubscriptionsChangedListener(mContext.getOpPackageName(), callback);
} catch (RemoteException ex) {
// system server crash
}
}
/**
* Unregister the {@link SubscriptionManager.OnSubscriptionsChangedListener}. 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 removeOnSubscriptionsChangedListener(
@NonNull SubscriptionManager.OnSubscriptionsChangedListener listener) {
if (mSubscriptionChangedListenerMap.get(listener) == null) {
return;
}
try {
sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
mSubscriptionChangedListenerMap.get(listener));
mSubscriptionChangedListenerMap.remove(listener);
} catch (RemoteException ex) {
// system server crash
}
}
/**
* 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 SubscriptionManager.OnOpportunisticSubscriptionsChangedListener} with
* onOpportunisticSubscriptionsChanged overridden.
* @param executor an Executor that will execute callbacks.
*/
public void addOnOpportunisticSubscriptionsChangedListener(
@NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener,
@NonNull Executor executor) {
/**
* The callback methods need to be called on the executor 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() {
final long identity = Binder.clearCallingIdentity();
try {
Log.d(TAG, "onOpportunisticSubscriptionsChanged callback received.");
executor.execute(() -> listener.onOpportunisticSubscriptionsChanged());
} finally {
Binder.restoreCallingIdentity(identity);
}
}
};
mOpportunisticSubscriptionChangedListenerMap.put(listener, callback);
try {
sRegistry.addOnOpportunisticSubscriptionsChangedListener(mContext.getOpPackageName(),
callback);
} catch (RemoteException ex) {
// system server crash
}
}
/**
* Unregister the {@link SubscriptionManager.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(
@NonNull SubscriptionManager.OnOpportunisticSubscriptionsChangedListener listener) {
try {
sRegistry.removeOnSubscriptionsChangedListener(mContext.getOpPackageName(),
mOpportunisticSubscriptionChangedListenerMap.get(listener));
mOpportunisticSubscriptionChangedListenerMap.remove(listener);
} catch (RemoteException ex) {
// system server crash
}
}
/** /**
* Informs the system of an intentional upcoming carrier network change by a carrier app. * Informs the system of an intentional upcoming carrier network change by a carrier app.
* This call only used to allow the system to provide alternative UI while telephony is * This call only used to allow the system to provide alternative UI while telephony is
@@ -98,14 +237,33 @@ public class TelephonyRegistryManager {
* @param slotIndex for which call state changed. Can be derived from subId except when subId is * @param slotIndex for which call state changed. Can be derived from subId except when subId is
* invalid. * invalid.
* @param state latest call state. e.g, offhook, ringing * @param state latest call state. e.g, offhook, ringing
* @param incomingNumer incoming phone number. * @param incomingNumber incoming phone number.
* *
* @hide * @hide
*/ */
public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state, public void notifyCallStateChanged(int subId, int slotIndex, @CallState int state,
String incomingNumer) { String incomingNumber) {
try { try {
sRegistry.notifyCallState(slotIndex, subId, state, incomingNumer); sRegistry.notifyCallState(slotIndex, subId, state, incomingNumber);
} catch (RemoteException ex) {
// system server crash
}
}
/**
* Notify call state changed on all subscriptions.
*
* @param state latest call state. e.g, offhook, ringing
* @param incomingNumber incoming phone number.
* @hide
*/
@SystemApi
@TestApi
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void notifyCallStateChangedForAllSubscriptions(@CallState int state,
@Nullable String incomingNumber) {
try {
sRegistry.notifyCallStateForAllSubs(state, incomingNumber);
} catch (RemoteException ex) { } catch (RemoteException ex) {
// system server crash // system server crash
} }
@@ -545,4 +703,15 @@ public class TelephonyRegistryManager {
} }
} }
/**
* @param activeDataSubId
* @hide
*/
public void notifyActiveDataSubIdChanged(int activeDataSubId) {
try {
sRegistry.notifyActiveDataSubIdChanged(activeDataSubId);
} catch (RemoteException ex) {
}
}
} }

View File

@@ -29,6 +29,9 @@ import android.telephony.SignalStrength;
import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsReasonInfo;
/**
* {@hide}
*/
oneway interface IPhoneStateListener { oneway interface IPhoneStateListener {
void onServiceStateChanged(in ServiceState serviceState); void onServiceStateChanged(in ServiceState serviceState);
void onSignalStrengthChanged(int asu); void onSignalStrengthChanged(int asu);

View File

@@ -49,6 +49,7 @@ import android.net.Uri;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper; import android.os.Looper;
import android.os.Message; import android.os.Message;
import android.os.ParcelUuid; import android.os.ParcelUuid;
@@ -61,10 +62,8 @@ import android.telephony.ims.ImsMmTelManager;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.Log; import android.util.Log;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ISetOpportunisticDataCallback; import com.android.internal.telephony.ISetOpportunisticDataCallback;
import com.android.internal.telephony.ISub; import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
@@ -931,20 +930,24 @@ public class SubscriptionManager {
OnSubscriptionsChangedListenerHandler(Looper looper) { OnSubscriptionsChangedListenerHandler(Looper looper) {
super(looper); super(looper);
} }
@Override
public void handleMessage(Message msg) {
if (DBG) {
log("handleMessage: invoke the overriden onSubscriptionsChanged()");
}
OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
}
} }
private final Handler mHandler; /**
* Posted executor callback on the handler associated with a given looper.
* The looper can be the calling thread's looper or the looper passed from the
* constructor {@link #OnSubscriptionsChangedListener(Looper)}.
*/
private final HandlerExecutor mExecutor;
/**
* @hide
*/
public HandlerExecutor getHandlerExecutor() {
return mExecutor;
}
public OnSubscriptionsChangedListener() { public OnSubscriptionsChangedListener() {
mHandler = new OnSubscriptionsChangedListenerHandler(); mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler());
} }
/** /**
@@ -953,7 +956,7 @@ public class SubscriptionManager {
* @hide * @hide
*/ */
public OnSubscriptionsChangedListener(Looper looper) { public OnSubscriptionsChangedListener(Looper looper) {
mHandler = new OnSubscriptionsChangedListenerHandler(looper); mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper));
} }
/** /**
@@ -965,18 +968,6 @@ public class SubscriptionManager {
if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN"); if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN");
} }
/**
* 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("callback: received, sendEmptyMessage(0) to handler");
mHandler.sendEmptyMessage(0);
}
};
private void log(String s) { private void log(String s) {
Rlog.d(LOG_TAG, s); Rlog.d(LOG_TAG, s);
} }
@@ -1018,21 +1009,19 @@ public class SubscriptionManager {
* onSubscriptionsChanged overridden. * onSubscriptionsChanged overridden.
*/ */
public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
if (listener == null) return;
String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
if (DBG) { if (DBG) {
logd("register OnSubscriptionsChangedListener pkgName=" + pkgName logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
+ " listener=" + listener); + " listener=" + listener);
} }
try { // We use the TelephonyRegistry as it 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
// available. Where as SubscriptionController could crash and not be available TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
"telephony.registry")); if (telephonyRegistryManager != null) {
if (tr != null) { telephonyRegistryManager.addOnSubscriptionsChangedListener(listener,
tr.addOnSubscriptionsChangedListener(pkgName, listener.callback); listener.mExecutor);
}
} catch (RemoteException ex) {
Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
} }
} }
@@ -1044,21 +1033,18 @@ public class SubscriptionManager {
* @param listener that is to be unregistered. * @param listener that is to be unregistered.
*/ */
public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
if (listener == null) return;
String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
if (DBG) { if (DBG) {
logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
+ " listener=" + listener); + " listener=" + listener);
} }
try { // We use the TelephonyRegistry as it 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
// available where as SubscriptionController could crash and not be available TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
"telephony.registry")); if (telephonyRegistryManager != null) {
if (tr != null) { telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener);
tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
}
} catch (RemoteException ex) {
Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
} }
} }
@@ -1077,7 +1063,6 @@ public class SubscriptionManager {
* for #onOpportunisticSubscriptionsChanged to be invoked. * for #onOpportunisticSubscriptionsChanged to be invoked.
*/ */
public static class OnOpportunisticSubscriptionsChangedListener { public static class OnOpportunisticSubscriptionsChangedListener {
private Executor mExecutor;
/** /**
* Callback invoked when there is any change to any SubscriptionInfo. Typically * Callback invoked when there is any change to any SubscriptionInfo. Typically
* this method would invoke {@link #getActiveSubscriptionInfoList} * this method would invoke {@link #getActiveSubscriptionInfoList}
@@ -1086,27 +1071,6 @@ public class SubscriptionManager {
if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN"); 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() {
final long identity = Binder.clearCallingIdentity();
try {
if (DBG) log("onOpportunisticSubscriptionsChanged callback received.");
mExecutor.execute(() -> onOpportunisticSubscriptionsChanged());
} finally {
Binder.restoreCallingIdentity(identity);
}
}
};
private void log(String s) { private void log(String s) {
Rlog.d(LOG_TAG, s); Rlog.d(LOG_TAG, s);
} }
@@ -1133,18 +1097,13 @@ public class SubscriptionManager {
+ " listener=" + listener); + " listener=" + listener);
} }
listener.setExecutor(executor); // We use the TelephonyRegistry as it runs in the system and thus is always
// available where as SubscriptionController could crash and not be available
try { TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
// We use the TelephonyRegistry as it runs in the system and thus is always mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
// available. Where as SubscriptionController could crash and not be available if (telephonyRegistryManager != null) {
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener(
"telephony.registry")); listener, executor);
if (tr != null) {
tr.addOnOpportunisticSubscriptionsChangedListener(pkgName, listener.callback);
}
} catch (RemoteException ex) {
Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
} }
} }
@@ -1164,16 +1123,10 @@ public class SubscriptionManager {
logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug=" logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug="
+ pkgForDebug + " listener=" + listener); + pkgForDebug + " listener=" + listener);
} }
try { TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager)
// We use the TelephonyRegistry as it runs in the system and thus is always mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
// available where as SubscriptionController could crash and not be available if (telephonyRegistryManager != null) {
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener);
"telephony.registry"));
if (tr != null) {
tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
}
} catch (RemoteException ex) {
Log.e(LOG_TAG, "Remote exception ITelephonyRegistry " + ex);
} }
} }