Merge "Additional changes to SubscriptionManager API as per API council." into lmp-mr1-dev

This commit is contained in:
Wink Saville
2014-11-20 20:20:01 +00:00
committed by Android (Google) Code Review
15 changed files with 525 additions and 476 deletions

View File

@@ -372,8 +372,8 @@ LOCAL_SRC_FILES += \
telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \ telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \ telephony/java/com/android/internal/telephony/ITelephony.aidl \
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \ telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl \
telephony/java/com/android/internal/telephony/ISms.aidl \ telephony/java/com/android/internal/telephony/ISms.aidl \
telephony/java/com/android/internal/telephony/ISubscriptionListener.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
telephony/java/com/android/internal/telephony/ISub.aidl \ telephony/java/com/android/internal/telephony/ISub.aidl \
telephony/java/com/android/internal/telephony/IMms.aidl \ telephony/java/com/android/internal/telephony/IMms.aidl \

View File

@@ -7270,6 +7270,7 @@ package android.content {
field public static final java.lang.String STORAGE_SERVICE = "storage"; field public static final java.lang.String STORAGE_SERVICE = "storage";
field public static final java.lang.String TELECOM_SERVICE = "telecom"; field public static final java.lang.String TELECOM_SERVICE = "telecom";
field public static final java.lang.String TELEPHONY_SERVICE = "phone"; field public static final java.lang.String TELEPHONY_SERVICE = "phone";
field public static final java.lang.String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices"; field public static final java.lang.String TEXT_SERVICES_MANAGER_SERVICE = "textservices";
field public static final java.lang.String TV_INPUT_SERVICE = "tv_input"; field public static final java.lang.String TV_INPUT_SERVICE = "tv_input";
field public static final java.lang.String UI_MODE_SERVICE = "uimode"; field public static final java.lang.String UI_MODE_SERVICE = "uimode";
@@ -25576,7 +25577,7 @@ package android.provider {
field public static final java.lang.String STATUS = "st"; field public static final java.lang.String STATUS = "st";
field public static final java.lang.String SUBJECT = "sub"; field public static final java.lang.String SUBJECT = "sub";
field public static final java.lang.String SUBJECT_CHARSET = "sub_cs"; field public static final java.lang.String SUBJECT_CHARSET = "sub_cs";
field public static final java.lang.String SUB_ID = "sub_id"; field public static final java.lang.String SUBSCRIPTION_ID = "sub_id";
field public static final java.lang.String TEXT_ONLY = "text_only"; field public static final java.lang.String TEXT_ONLY = "text_only";
field public static final java.lang.String THREAD_ID = "thread_id"; field public static final java.lang.String THREAD_ID = "thread_id";
field public static final java.lang.String TRANSACTION_ID = "tr_id"; field public static final java.lang.String TRANSACTION_ID = "tr_id";
@@ -25609,7 +25610,7 @@ package android.provider {
field public static final java.lang.String PROXY = "proxy"; field public static final java.lang.String PROXY = "proxy";
field public static final java.lang.String ROAMING_PROTOCOL = "roaming_protocol"; field public static final java.lang.String ROAMING_PROTOCOL = "roaming_protocol";
field public static final java.lang.String SERVER = "server"; field public static final java.lang.String SERVER = "server";
field public static final java.lang.String SUB_ID = "sub_id"; field public static final java.lang.String SUBSCRIPTION_ID = "sub_id";
field public static final java.lang.String TYPE = "type"; field public static final java.lang.String TYPE = "type";
field public static final java.lang.String USER = "user"; field public static final java.lang.String USER = "user";
} }
@@ -25710,7 +25711,7 @@ package android.provider {
field public static final java.lang.String MSG_TYPE = "msg_type"; field public static final java.lang.String MSG_TYPE = "msg_type";
field public static final java.lang.String PROTO_TYPE = "proto_type"; field public static final java.lang.String PROTO_TYPE = "proto_type";
field public static final java.lang.String RETRY_INDEX = "retry_index"; field public static final java.lang.String RETRY_INDEX = "retry_index";
field public static final java.lang.String SUB_ID = "pending_sub_id"; field public static final java.lang.String SUBSCRIPTION_ID = "pending_sub_id";
} }
public static final class Telephony.Sms implements android.provider.BaseColumns android.provider.Telephony.TextBasedSmsColumns { public static final class Telephony.Sms implements android.provider.BaseColumns android.provider.Telephony.TextBasedSmsColumns {
@@ -25796,7 +25797,7 @@ package android.provider {
field public static final int STATUS_NONE = -1; // 0xffffffff field public static final int STATUS_NONE = -1; // 0xffffffff
field public static final int STATUS_PENDING = 32; // 0x20 field public static final int STATUS_PENDING = 32; // 0x20
field public static final java.lang.String SUBJECT = "subject"; field public static final java.lang.String SUBJECT = "subject";
field public static final java.lang.String SUB_ID = "sub_id"; field public static final java.lang.String SUBSCRIPTION_ID = "sub_id";
field public static final java.lang.String THREAD_ID = "thread_id"; field public static final java.lang.String THREAD_ID = "thread_id";
field public static final java.lang.String TYPE = "type"; field public static final java.lang.String TYPE = "type";
} }
@@ -28649,20 +28650,19 @@ package android.telephony {
field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR; field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionInfo> CREATOR;
} }
public class SubscriptionListener { public class SubscriptionManager {
ctor public SubscriptionListener(); method public static android.telephony.SubscriptionManager from(android.content.Context);
ctor public SubscriptionListener(android.os.Looper); method public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int);
method public void onSubscriptionInfoChanged(); method public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int);
field public static final int LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED = 1; // 0x1 method public java.util.List<android.telephony.SubscriptionInfo> getActiveSubscriptionInfoList();
method public void registerOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
method public void unregisterOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
} }
public class SubscriptionManager implements android.provider.BaseColumns { public static class SubscriptionManager.OnSubscriptionsChangedListener {
method public static java.util.List<android.telephony.SubscriptionInfo> getActiveSubscriptionInfoList(); ctor public SubscriptionManager.OnSubscriptionsChangedListener();
method public static android.telephony.SubscriptionInfo getSubscriptionInfoForSubscriber(int); method public void onSubscriptionsChanged();
method public static java.util.List<android.telephony.SubscriptionInfo> getSubscriptionInfoUsingSlotId(int);
method public static void register(android.content.Context, android.telephony.SubscriptionListener, int);
method public static void unregister(android.content.Context, android.telephony.SubscriptionListener);
field public static final int INVALID_SUB_ID = -1000; // 0xfffffc18
} }
public class TelephonyManager { public class TelephonyManager {

View File

@@ -20,9 +20,9 @@ import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManager;
import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetManager;
import android.os.Build; import android.os.Build;
import android.service.persistentdata.IPersistentDataBlockService; import android.service.persistentdata.IPersistentDataBlockService;
import android.service.persistentdata.PersistentDataBlockManager; import android.service.persistentdata.PersistentDataBlockManager;
import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.policy.PolicyManager; import com.android.internal.policy.PolicyManager;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
@@ -125,6 +125,7 @@ import android.print.PrintManager;
import android.service.fingerprint.IFingerprintService; import android.service.fingerprint.IFingerprintService;
import android.service.fingerprint.FingerprintManager; import android.service.fingerprint.FingerprintManager;
import android.telecom.TelecomManager; import android.telecom.TelecomManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.util.AndroidRuntimeException; import android.util.AndroidRuntimeException;
@@ -561,6 +562,11 @@ class ContextImpl extends Context {
return new TelephonyManager(ctx.getOuterContext()); return new TelephonyManager(ctx.getOuterContext());
}}); }});
registerService(TELEPHONY_SUBSCRIPTION_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return new SubscriptionManager(ctx.getOuterContext());
}});
registerService(TELECOM_SERVICE, new ServiceFetcher() { registerService(TELECOM_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) { public Object createService(ContextImpl ctx) {
return new TelecomManager(ctx.getOuterContext()); return new TelecomManager(ctx.getOuterContext());

View File

@@ -2245,6 +2245,8 @@ public abstract class Context {
* @see android.media.MediaRouter * @see android.media.MediaRouter
* @see #TELEPHONY_SERVICE * @see #TELEPHONY_SERVICE
* @see android.telephony.TelephonyManager * @see android.telephony.TelephonyManager
* @see #TELEPHONY_SUBSCRIPTION_SERVICE
* @see android.telephony.SubscriptionManager
* @see #INPUT_METHOD_SERVICE * @see #INPUT_METHOD_SERVICE
* @see android.view.inputmethod.InputMethodManager * @see android.view.inputmethod.InputMethodManager
* @see #UI_MODE_SERVICE * @see #UI_MODE_SERVICE
@@ -2587,6 +2589,16 @@ public abstract class Context {
*/ */
public static final String TELEPHONY_SERVICE = "phone"; public static final String TELEPHONY_SERVICE = "phone";
/**
* Use with {@link #getSystemService} to retrieve a
* {@link android.telephony.SubscriptionManager} for handling management the
* telephony subscriptions of the device.
*
* @see #getSystemService
* @see android.telephony.SubscriptionManager
*/
public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
/** /**
* Use with {@link #getSystemService} to retrieve a * Use with {@link #getSystemService} to retrieve a
* {@link android.telecom.TelecomManager} to manage telecom-related features * {@link android.telecom.TelecomManager} to manage telecom-related features

View File

@@ -387,7 +387,6 @@ public class CallLog {
public static Uri addCall(CallerInfo ci, Context context, String number, public static Uri addCall(CallerInfo ci, Context context, String number,
int presentation, int callType, int features, PhoneAccountHandle accountHandle, int presentation, int callType, int features, PhoneAccountHandle accountHandle,
long start, int duration, Long dataUsage) { long start, int duration, Long dataUsage) {
// FIXME using -1 as subId instead of SubscriptionManager.INVALID_SUB_ID
return addCall(ci, context, number, presentation, callType, features, accountHandle, return addCall(ci, context, number, presentation, callType, features, accountHandle,
start, duration, dataUsage, false); start, duration, dataUsage, false);
} }

View File

@@ -239,7 +239,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
mDaemonHandler = new Handler(FgThread.get().getLooper()); mDaemonHandler = new Handler(FgThread.get().getLooper());
mPhoneStateListener = new PhoneStateListener(SubscriptionManager.DEFAULT_SUB_ID, mPhoneStateListener = new PhoneStateListener(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
mDaemonHandler.getLooper()) { mDaemonHandler.getLooper()) {
@Override @Override
public void onDataConnectionRealTimeInfoChanged( public void onDataConnectionRealTimeInfoChanged(

View File

@@ -34,8 +34,6 @@ import android.os.UserHandle;
import android.telephony.CellLocation; import android.telephony.CellLocation;
import android.telephony.DataConnectionRealTimeInfo; import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.Rlog; import android.telephony.Rlog;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionListener;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.PhoneStateListener; import android.telephony.PhoneStateListener;
@@ -43,7 +41,6 @@ import android.telephony.ServiceState;
import android.telephony.SignalStrength; import android.telephony.SignalStrength;
import android.telephony.CellInfo; import android.telephony.CellInfo;
import android.telephony.VoLteServiceState; import android.telephony.VoLteServiceState;
import android.telephony.TelephonyManager;
import android.telephony.DisconnectCause; import android.telephony.DisconnectCause;
import android.telephony.PreciseCallState; import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState; import android.telephony.PreciseDataConnectionState;
@@ -52,13 +49,12 @@ import android.text.TextUtils;
import android.text.format.Time; import android.text.format.Time;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; import java.util.List;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import com.android.internal.app.IBatteryStats; import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.ISubscriptionListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.DefaultPhoneNotifier; import com.android.internal.telephony.DefaultPhoneNotifier;
@@ -93,28 +89,29 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
IBinder binder; IBinder binder;
IPhoneStateListener callback; IPhoneStateListener callback;
ISubscriptionListener subscriptionListenerCallback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
int callerUid; int callerUid;
int events; int events;
int subId = SubscriptionManager.INVALID_SUB_ID; int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
int phoneId = SubscriptionManager.INVALID_PHONE_ID; int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
boolean matchPhoneStateListenerEvent(int events) { boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0); return (callback != null) && ((events & this.events) != 0);
} }
boolean matchSubscriptionListenerEvent(int events) { boolean matchOnSubscriptionsChangedListener() {
return (subscriptionListenerCallback != null) && ((events & this.events) != 0); return (onSubscriptionsChangedListenerCallback != null);
} }
@Override @Override
public String toString() { public String toString() {
return "{pkgForDebug=" + pkgForDebug + " binder=" + binder + " callback=" + callback return "{pkgForDebug=" + pkgForDebug + " binder=" + binder + " callback=" + callback
+ " subscriptionListenererCallback=" + subscriptionListenerCallback + " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback
+ " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
+ " events=" + Integer.toHexString(events) + "}"; + " events=" + Integer.toHexString(events) + "}";
} }
@@ -128,6 +125,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private final IBatteryStats mBatteryStats; private final IBatteryStats mBatteryStats;
private boolean hasNotifySubscriptionInfoChangedOccurred = false;
private int mNumPhones; private int mNumPhones;
private int[] mCallState; private int[] mCallState;
@@ -168,9 +167,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private VoLteServiceState mVoLteServiceState = new VoLteServiceState(); private VoLteServiceState mVoLteServiceState = new VoLteServiceState();
private int mDefaultSubId = SubscriptionManager.INVALID_SUB_ID; private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_ID; private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
private DataConnectionRealTimeInfo mDcRtInfo = new DataConnectionRealTimeInfo(); private DataConnectionRealTimeInfo mDcRtInfo = new DataConnectionRealTimeInfo();
@@ -227,7 +226,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
//possible missed notify callback //possible missed notify callback
synchronized (mRecords) { synchronized (mRecords) {
for (Record r : mRecords) { for (Record r : mRecords) {
if(r.subId == SubscriptionManager.DEFAULT_SUB_ID) { if(r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
checkPossibleMissNotify(r, newDefaultPhoneId); checkPossibleMissNotify(r, newDefaultPhoneId);
} }
} }
@@ -339,19 +338,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
@Override @Override
public void registerSubscriptionListener(String pkgForDebug, ISubscriptionListener callback, public void registerOnSubscriptionsChangedListener(String pkgForDebug,
int events) { IOnSubscriptionsChangedListener callback) {
int callerUid = UserHandle.getCallingUserId(); int callerUid = UserHandle.getCallingUserId();
int myUid = UserHandle.myUserId(); int myUid = UserHandle.myUserId();
if (VDBG) { if (VDBG) {
log("listen sl: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events) log("listen oscl: E pkg=" + pkgForDebug + " myUid=" + myUid
+ " myUid=" + myUid + " callerUid=" + callerUid + " callback=" + callback + " callerUid=" + callerUid + " callback=" + callback
+ " callback.asBinder=" + callback.asBinder()); + " callback.asBinder=" + callback.asBinder());
} }
if (events != 0) {
/* Checks permission and throws Security exception */ /* Checks permission and throws Security exception */
checkSubscriptionListenerPermission(events); checkOnSubscriptionsChangedListenerPermission();
Record r = null; Record r = null;
synchronized (mRecords) { synchronized (mRecords) {
@@ -368,61 +366,57 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
r = new Record(); r = new Record();
r.binder = b; r.binder = b;
mRecords.add(r); mRecords.add(r);
if (DBG) log("listen sl: add new record"); if (DBG) log("listen oscl: add new record");
} }
r.subscriptionListenerCallback = callback; r.onSubscriptionsChangedListenerCallback = callback;
r.pkgForDebug = pkgForDebug; r.pkgForDebug = pkgForDebug;
r.callerUid = callerUid; r.callerUid = callerUid;
r.events = events; r.events = 0;
if (DBG) { if (DBG) {
log("listen sl: Register r=" + r); log("listen oscl: Register r=" + r);
} }
} // Always notify when registration occurs if there has been a notification.
if (hasNotifySubscriptionInfoChangedOccurred) {
// Always notify when a listen is established.
if (r.matchSubscriptionListenerEvent(
SubscriptionListener.LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED)) {
try { try {
if (VDBG) log("listen sl: send to r=" + r); if (VDBG) log("listen oscl: send to r=" + r);
r.subscriptionListenerCallback.onSubscriptionInfoChanged(); r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
if (VDBG) log("listen sl: sent to r=" + r); if (VDBG) log("listen oscl: sent to r=" + r);
} catch (RemoteException e) { } catch (RemoteException e) {
if (VDBG) log("listen sl: remote exception sending to r=" + r + " e=" + e); if (VDBG) log("listen oscl: remote exception sending to r=" + r + " e=" + e);
remove(r.binder); remove(r.binder);
} }
}
} else { } else {
if (DBG) log("listen sl: Unregister as event is LISTEN_NONE"); log("listen oscl: hasNotifySubscriptionInfoChangedOccurred==false no callback");
unregisterSubscriptionListener(pkgForDebug, callback); }
} }
} }
@Override @Override
public void unregisterSubscriptionListener(String pkgForDebug, ISubscriptionListener callback) { public void unregisterOnSubscriptionsChangedListener(String pkgForDebug,
if (DBG) log("listen sl: Unregister as event is LISTEN_NONE"); IOnSubscriptionsChangedListener callback) {
if (DBG) log("listen oscl: Unregister");
remove(callback.asBinder()); remove(callback.asBinder());
} }
private void checkSubscriptionListenerPermission(int events) { private void checkOnSubscriptionsChangedListenerPermission() {
if ((events & SubscriptionListener.LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED) != 0) {
mContext.enforceCallingOrSelfPermission( mContext.enforceCallingOrSelfPermission(
SubscriptionListener.PERMISSION_LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED, null); SubscriptionManager.OnSubscriptionsChangedListener
} .PERMISSION_ON_SUBSCRIPTIONS_CHANGED, null);
} }
@Override @Override
public void notifySubscriptionInfoChanged() { public void notifySubscriptionInfoChanged() {
if (VDBG) log("notifySubscriptionInfoChanged:"); if (VDBG) log("notifySubscriptionInfoChanged:");
synchronized (mRecords) { synchronized (mRecords) {
hasNotifySubscriptionInfoChangedOccurred = true;
mRemoveList.clear(); mRemoveList.clear();
for (Record r : mRecords) { for (Record r : mRecords) {
if (r.matchSubscriptionListenerEvent( if (r.matchOnSubscriptionsChangedListener()) {
SubscriptionListener.LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED)) {
try { try {
if (VDBG) log("notifySubscriptionInfoChanged: send to r=" + r); if (VDBG) log("notifySubscriptionInfoChanged: call osc to r=" + r);
r.subscriptionListenerCallback.onSubscriptionInfoChanged(); r.onSubscriptionsChangedListenerCallback.onSubscriptionsChanged();
if (VDBG) log("notifySubscriptionInfoChanged: sent to r=" + r); if (VDBG) log("notifySubscriptionInfoChanged: call osc to r=" + r);
} catch (RemoteException ex) { } catch (RemoteException ex) {
if (VDBG) log("notifySubscriptionInfoChanged: RemoteException r=" + r); if (VDBG) log("notifySubscriptionInfoChanged: RemoteException r=" + r);
mRemoveList.add(r.binder); mRemoveList.add(r.binder);
@@ -436,8 +430,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
@Override @Override
public void listen(String pkgForDebug, IPhoneStateListener callback, int events, public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
boolean notifyNow) { boolean notifyNow) {
listenForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, pkgForDebug, callback, events, listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, pkgForDebug, callback,
notifyNow); events, notifyNow);
} }
@Override @Override
@@ -483,7 +477,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
// force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
if (!SubscriptionManager.isValidSubId(subId)) { if (!SubscriptionManager.isValidSubId(subId)) {
r.subId = SubscriptionManager.DEFAULT_SUB_ID; r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
} else {//APP specify subID } else {//APP specify subID
r.subId = subId; r.subId = subId;
} }
@@ -642,7 +636,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) { synchronized (mRecords) {
for (Record r : mRecords) { for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
(r.subId == SubscriptionManager.DEFAULT_SUB_ID)) { (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try { try {
r.callback.onCallStateChanged(state, incomingNumber); r.callback.onCallStateChanged(state, incomingNumber);
} catch (RemoteException ex) { } catch (RemoteException ex) {
@@ -652,7 +646,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
handleRemoveListLocked(); handleRemoveListLocked();
} }
broadcastCallStateChanged(state, incomingNumber, SubscriptionManager.DEFAULT_SUB_ID); broadcastCallStateChanged(state, incomingNumber,
SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
} }
public void notifyCallStateForSubscriber(int subId, int state, String incomingNumber) { public void notifyCallStateForSubscriber(int subId, int state, String incomingNumber) {
@@ -671,7 +666,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) { for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
(r.subId == subId) && (r.subId == subId) &&
(r.subId != SubscriptionManager.DEFAULT_SUB_ID)) { (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try { try {
r.callback.onCallStateChanged(state, incomingNumber); r.callback.onCallStateChanged(state, incomingNumber);
} catch (RemoteException ex) { } catch (RemoteException ex) {
@@ -728,7 +723,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
public void notifySignalStrength(SignalStrength signalStrength) { public void notifySignalStrength(SignalStrength signalStrength) {
notifySignalStrengthForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, signalStrength); notifySignalStrengthForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
signalStrength);
} }
public void notifySignalStrengthForSubscriber(int subId, SignalStrength signalStrength) { public void notifySignalStrengthForSubscriber(int subId, SignalStrength signalStrength) {
@@ -789,7 +785,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
public void notifyCellInfo(List<CellInfo> cellInfo) { public void notifyCellInfo(List<CellInfo> cellInfo) {
notifyCellInfoForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cellInfo); notifyCellInfoForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellInfo);
} }
public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) { public void notifyCellInfoForSubscriber(int subId, List<CellInfo> cellInfo) {
@@ -877,7 +873,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
public void notifyCallForwardingChanged(boolean cfi) { public void notifyCallForwardingChanged(boolean cfi) {
notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cfi); notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cfi);
} }
public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) { public void notifyCallForwardingChangedForSubscriber(int subId, boolean cfi) {
@@ -909,7 +905,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
public void notifyDataActivity(int state) { public void notifyDataActivity(int state) {
notifyDataActivityForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, state); notifyDataActivityForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state);
} }
public void notifyDataActivityForSubscriber(int subId, int state) { public void notifyDataActivityForSubscriber(int subId, int state) {
@@ -918,6 +914,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
synchronized (mRecords) { synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId); int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
mDataActivity[phoneId] = state; mDataActivity[phoneId] = state;
for (Record r : mRecords) { for (Record r : mRecords) {
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY)) { if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY)) {
@@ -928,6 +925,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
} }
} }
}
handleRemoveListLocked(); handleRemoveListLocked();
} }
} }
@@ -935,7 +933,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
public void notifyDataConnection(int state, boolean isDataConnectivityPossible, public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String apnType, LinkProperties linkProperties, String reason, String apn, String apnType, LinkProperties linkProperties,
NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, state, notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state,
isDataConnectivityPossible,reason, apn, apnType, linkProperties, isDataConnectivityPossible,reason, apn, apnType, linkProperties,
networkCapabilities, networkType, roaming); networkCapabilities, networkType, roaming);
} }
@@ -956,6 +954,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
synchronized (mRecords) { synchronized (mRecords) {
int phoneId = SubscriptionManager.getPhoneId(subId); int phoneId = SubscriptionManager.getPhoneId(subId);
if (validatePhoneId(phoneId)) {
boolean modified = false; boolean modified = false;
if (state == TelephonyManager.DATA_CONNECTED) { if (state == TelephonyManager.DATA_CONNECTED) {
if (!mConnectedApns.contains(apnType)) { if (!mConnectedApns.contains(apnType)) {
@@ -1018,6 +1017,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
} }
} }
}
handleRemoveListLocked(); handleRemoveListLocked();
} }
broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
@@ -1027,7 +1027,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
public void notifyDataConnectionFailed(String reason, String apnType) { public void notifyDataConnectionFailed(String reason, String apnType) {
notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
reason, apnType); reason, apnType);
} }
@@ -1062,7 +1062,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
public void notifyCellLocation(Bundle cellLocation) { public void notifyCellLocation(Bundle cellLocation) {
notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cellLocation); notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
} }
public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) { public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
@@ -1226,7 +1226,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
if ((r.matchPhoneStateListenerEvent( if ((r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT)) && PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT)) &&
((r.subId == subId) || ((r.subId == subId) ||
(r.subId == SubscriptionManager.DEFAULT_SUB_ID))) { (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID))) {
try { try {
r.callback.onOemHookRawEvent(rawData); r.callback.onOemHookRawEvent(rawData);
} catch (RemoteException ex) { } catch (RemoteException ex) {
@@ -1399,14 +1399,17 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
private void broadcastPreciseDataConnectionStateChanged(int state, int networkType, private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) { String apnType, String apn, String reason, LinkProperties linkProperties,
String failCause) {
Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED); Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
intent.putExtra(PhoneConstants.STATE_KEY, state); intent.putExtra(PhoneConstants.STATE_KEY, state);
intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType); intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason); if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties); if (linkProperties != null) {
intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY,linkProperties);
}
if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause); if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL, mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
@@ -1506,7 +1509,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
@Override @Override
public String toString() { public String toString() {
return mS + " Time " + mTime.toString() + " mSubId " + mSubId + " mPhoneId " + mPhoneId + " mState " + mState; return mS + " Time " + mTime.toString() + " mSubId " + mSubId + " mPhoneId "
+ mPhoneId + " mState " + mState;
} }
} }
@@ -1550,7 +1554,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
} }
boolean idMatch(int rSubId, int subId, int phoneId) { boolean idMatch(int rSubId, int subId, int phoneId) {
if(rSubId == SubscriptionManager.DEFAULT_SUB_ID) { if(rSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
if(subId < 0) { if(subId < 0) {
// Invalid case, we need compare phoneId with default one. // Invalid case, we need compare phoneId with default one.
return (mDefaultPhoneId == phoneId); return (mDefaultPhoneId == phoneId);

View File

@@ -73,8 +73,8 @@ import android.provider.Telephony.Carriers;
import android.provider.Telephony.Sms.Intents; import android.provider.Telephony.Sms.Intents;
import android.telephony.SmsMessage; import android.telephony.SmsMessage;
import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionListener;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation; import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils; import android.text.TextUtils;
@@ -462,9 +462,10 @@ public class GpsLocationProvider implements LocationProviderInterface {
} }
}; };
private final SubscriptionListener mSubscriptionListener = new SubscriptionListener() { private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
new OnSubscriptionsChangedListener() {
@Override @Override
public void onSubscriptionInfoChanged() { public void onSubscriptionsChanged() {
subscriptionOrSimChanged(mContext); subscriptionOrSimChanged(mContext);
} }
}; };
@@ -640,14 +641,14 @@ public class GpsLocationProvider implements LocationProviderInterface {
mSuplEsEnabled); mSuplEsEnabled);
// TODO: When this object "finishes" we should unregister by invoking // TODO: When this object "finishes" we should unregister by invoking
// SubscriptionManager.unregister(mContext, mSubscriptionListener); // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
// This is not strictly necessary because it will be unregistered if the // This is not strictly necessary because it will be unregistered if the
// notification fails but it is good form. // notification fails but it is good form.
// Register for SubscriptionInfo list changes which is guaranteed // Register for SubscriptionInfo list changes which is guaranteed
// to invoke onSubscriptionInfoChanged the first time. // to invoke onSubscriptionsChanged the first time.
SubscriptionManager.register(mContext, mSubscriptionListener, SubscriptionManager.from(mContext)
SubscriptionListener.LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED); .registerOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
// construct handler, listen for events // construct handler, listen for events
mHandler = new ProviderHandler(looper); mHandler = new ProviderHandler(looper);

View File

@@ -227,7 +227,7 @@ public class PhoneStateListener {
* @hide * @hide
*/ */
/** @hide */ /** @hide */
protected int mSubId = SubscriptionManager.INVALID_SUB_ID; protected int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final Handler mHandler; private final Handler mHandler;
@@ -237,7 +237,7 @@ public class PhoneStateListener {
* own non-null looper use PhoneStateListener(Looper looper) below. * own non-null looper use PhoneStateListener(Looper looper) below.
*/ */
public PhoneStateListener() { public PhoneStateListener() {
this(SubscriptionManager.DEFAULT_SUB_ID, Looper.myLooper()); this(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, Looper.myLooper());
} }
/** /**
@@ -246,7 +246,7 @@ public class PhoneStateListener {
* @hide * @hide
*/ */
public PhoneStateListener(Looper looper) { public PhoneStateListener(Looper looper) {
this(SubscriptionManager.DEFAULT_SUB_ID, looper); this(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, looper);
} }
/** /**

View File

@@ -1,125 +0,0 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.ISubscriptionListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Rlog;
import java.util.List;
/**
* A listener class for monitoring changes to Subscription state
* changes on the device.
* <p>
* Override the onXxxx methods in this class and passing to the listen method
* bitwise-or of the corresponding LISTEN_Xxxx bit flags below.
* <p>
* Note that access to some of the information is permission-protected. Your
* application won't receive updates for protected information unless it has
* the appropriate permissions declared in its manifest file. Where permissions
* apply, they are noted in the appropriate LISTEN_ flags.
*/
public class SubscriptionListener {
private static final String LOG_TAG = "SubscriptionListener";
private static final boolean DBG = false; // STOPSHIP if true
/**
* Permission for LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED
*
* @hide
*/
public static final String PERMISSION_LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED =
android.Manifest.permission.READ_PHONE_STATE;
/**
* Listen for changes to the SubscriptionInoList when listening for this event
* it is guaranteed that on #onSubscriptionInfoChanged will be invoked. This initial
* invocation should be used to call SubscriptionManager.getActiveSubscriptionInfoList()
* to get the initial list.
*
* Permissions: android.Manifest.permission.READ_PHONE_STATE
* @see #onSubscriptionInfoChanged
*/
public static final int LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED = 0x00000001;
private final Handler mHandler;
/**
* Create a SubscriptionLitener for the device.
*
* This class requires Looper.myLooper() not return null. To supply your
* own non-null looper use PhoneStateListener(Looper looper) below.
*/
public SubscriptionListener() {
this(Looper.myLooper());
}
/**
* Create a PhoneStateListener for the Phone using the specified subscription
* and non-null Looper.
*/
public SubscriptionListener(Looper looper) {
if (DBG) log("ctor: looper=" + looper);
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
mHandler = new Handler(looper) {
@Override
public void handleMessage(Message msg) {
if (DBG) {
log("what=0x" + Integer.toHexString(msg.what) + " msg=" + msg);
}
switch (msg.what) {
case LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED:
SubscriptionListener.this.onSubscriptionInfoChanged();
break;
}
}
};
}
/**
* Callback invoked when there is any change to any SubscriptionInfo.
*/
public void onSubscriptionInfoChanged() {
// default implementation empty
}
/**
* 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.
*/
ISubscriptionListener callback = new ISubscriptionListener.Stub() {
@Override
public void onSubscriptionInfoChanged() {
Message msg = Message.obtain(mHandler, LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED);
msg.sendToTarget();
}
};
private void log(String s) {
Rlog.d(LOG_TAG, s);
}
}

View File

@@ -21,12 +21,14 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.provider.BaseColumns;
import android.telephony.Rlog; import android.telephony.Rlog;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.RemoteException; import android.os.RemoteException;
import com.android.internal.telephony.ISub; import com.android.internal.telephony.ISub;
import com.android.internal.telephony.IOnSubscriptionsChangedListener;
import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.PhoneConstants; import com.android.internal.telephony.PhoneConstants;
@@ -36,62 +38,79 @@ import java.util.List;
/** /**
* SubscriptionManager is the application interface to SubscriptionController * SubscriptionManager is the application interface to SubscriptionController
* and provides information about the current Telephony Subscriptions. * and provides information about the current Telephony Subscriptions.
* * * <p>
* The android.Manifest.permission.READ_PHONE_STATE to retrieve the information, except * You do not instantiate this class directly; instead, you retrieve
* getActiveSubIdList and getActiveSubIdCount for which no permission is needed. * a reference to an instance through {@link #from}.
* <p>
* All SDK public methods require android.Manifest.permission.READ_PHONE_STATE.
*/ */
public class SubscriptionManager implements BaseColumns { public class SubscriptionManager {
private static final String LOG_TAG = "SUB"; private static final String LOG_TAG = "SubscriptionManager";
private static final boolean DBG = true; private static final boolean DBG = true;
private static final boolean VDBG = false; private static final boolean VDBG = false;
/** An invalid subscription identifier */ /** An invalid subscription identifier */
public static final int INVALID_SUB_ID = -1000; public static final int INVALID_SUBSCRIPTION_ID = -1;
/** Base value for Dummy SUBSCRIPTION_ID's. */
/** FIXME: Remove DummySubId's, but for now have them map just below INVALID_SUBSCRIPTION_ID
/** @hide */
public static final int DUMMY_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1;
/** An invalid phone identifier */ /** An invalid phone identifier */
/** @hide */ /** @hide */
public static final int INVALID_PHONE_ID = -1; public static final int INVALID_PHONE_INDEX = -1;
/** An invalid slot identifier */ /** An invalid slot identifier */
/** @hide */ /** @hide */
public static final int INVALID_SLOT_ID = -1; public static final int INVALID_SIM_SLOT_INDEX = -1;
/** Indicates the caller wants the default sub id. */ /** Indicates the caller wants the default sub id. */
/** @hide */ /** @hide */
public static final int DEFAULT_SUB_ID = Integer.MAX_VALUE; public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
/** Indicates the caller wants the default phone id. */ /**
/** @hide */ * Indicates the caller wants the default phone id.
public static final int DEFAULT_PHONE_ID = Integer.MAX_VALUE; * Used in SubscriptionController and PhoneBase but do we really need it???
* @hide
*/
public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE;
/** Indicates the caller wants the default slot id. */ /** Indicates the caller wants the default slot id. NOT used remove? */
/** @hide */ /** @hide */
public static final int DEFAULT_SLOT_ID = Integer.MAX_VALUE; public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE;
/** Minimum possible subid that represents a subscription */ /** Minimum possible subid that represents a subscription */
/** @hide */ /** @hide */
public static final int MIN_SUB_ID_VALUE = 0; public static final int MIN_SUBSCRIPTION_ID_VALUE = 0;
/** Maximum possible subid that represents a subscription */ /** Maximum possible subid that represents a subscription */
/** @hide */ /** @hide */
public static final int MAX_SUB_ID_VALUE = DEFAULT_SUB_ID - 1; public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1;
/** @hide */ /** @hide */
public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo"); public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
/** /**
* The ICC ID of a SIM. * TelephonyProvider unique key column name is the subscription id.
* <P>Type: TEXT (String)</P>
*/
/** @hide */
public static final String UNIQUE_KEY_SUBSCRIPTION_ID = "_id";
/**
* TelephonyProvider column name for SIM ICC Identifier
* <P>Type: TEXT (String)</P> * <P>Type: TEXT (String)</P>
*/ */
/** @hide */ /** @hide */
public static final String ICC_ID = "icc_id"; public static final String ICC_ID = "icc_id";
/** /**
* TelephonyProvider column name for user SIM_SlOT_INDEX
* <P>Type: INTEGER (int)</P> * <P>Type: INTEGER (int)</P>
*/ */
/** @hide */ /** @hide */
public static final String SIM_ID = "sim_id"; public static final String SIM_SLOT_INDEX = "sim_id";
/** SIM is not inserted */ /** SIM is not inserted */
/** @hide */ /** @hide */
@@ -230,39 +249,107 @@ public class SubscriptionManager implements BaseColumns {
/** /**
* Broadcast Action: The user has changed one of the default subs related to * Broadcast Action: The user has changed one of the default subs related to
* data, phone calls, or sms</p> * data, phone calls, or sms</p>
*
* TODO: Change to a listener
* @hide * @hide
*/ */
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String SUB_DEFAULT_CHANGED_ACTION = public static final String SUB_DEFAULT_CHANGED_ACTION =
"android.intent.action.SUB_DEFAULT_CHANGED"; "android.intent.action.SUB_DEFAULT_CHANGED";
private final Context mContext;
/**
* A listener class for monitoring changes to {@link SubscriptionInfo} records.
* <p>
* Override the onSubscriptionsChanged method in the object that extends this
* class and pass it to {@link #registerOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)}
* to register your listener and to unregister invoke
* {@link #unregisterOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)}
* <p>
* Permissions android.Manifest.permission.READ_PHONE_STATE is required
* for #onSubscriptionsChanged to be invoked.
*/
public static class OnSubscriptionsChangedListener {
/** @hide */ /** @hide */
public SubscriptionManager() { public static final String PERMISSION_ON_SUBSCRIPTIONS_CHANGED =
if (DBG) logd("SubscriptionManager created"); android.Manifest.permission.READ_PHONE_STATE;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (DBG) {
log("handleMessage: invoke the overriden onSubscriptionsChanged()");
}
OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
}
};
/**
* Callback invoked when there is any change to any SubscriptionInfo. Typically
* this method would invoke {@link #getActiveSubscriptionInfoList}
*/
public void onSubscriptionsChanged() {
if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN");
} }
/** /**
* Register for changes to events defined by SubscriptionListener.LISTEN_Xxx. Some of * The callback methods need to be called on the handler thread where
* the events will fire as registration completes, this could be before or after * this object was created. If the binder did that for us it'd be nice.
* this method returns.
*
* @param listener an instance of SubscriptionListner with overridden methods the
* overridden method should match the bits defined in events.
* @param events is one or more of the SubscriptionListener.LISTEN_Xxx bits
*/ */
public static void register(Context context, SubscriptionListener listener, int events) { IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
String pkgForDebug = context != null ? context.getPackageName() : "<unknown>"; @Override
public void onSubscriptionsChanged() {
if (DBG) log("callbad: received, sendEmptyMessage(0) to handler");
mHandler.sendEmptyMessage(0);
}
};
private void log(String s) {
Rlog.d(LOG_TAG, s);
}
}
/** @hide */
public SubscriptionManager(Context context) {
if (DBG) logd("SubscriptionManager created");
mContext = context;
}
/**
* Get an instance of the SubscriptionManager from the Context.
* This invokes {@link android.content.Context#getSystemService
* Context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)}.
*
* @param context to use.
* @return SubscriptionManager instance
*/
public static SubscriptionManager from(Context context) {
return (SubscriptionManager) context.getSystemService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE);
}
/**
* 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.
*
* @param listener an instance of {@link OnSubscriptionsChangedListener} with
* onSubscriptionsChanged overridden.
*/
public void registerOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
if (DBG) { if (DBG) {
logd("SubscriptionManager listen pkgForDebug=" + pkgForDebug logd("register OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
+ " events=0x" + Integer.toHexString(events) + " 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 // 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"));
if (tr != null) { if (tr != null) {
tr.registerSubscriptionListener(pkgForDebug, listener.callback, events); tr.registerOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
} }
} catch (RemoteException ex) { } catch (RemoteException ex) {
// Should not happen // Should not happen
@@ -270,15 +357,16 @@ public class SubscriptionManager implements BaseColumns {
} }
/** /**
* Unregister the listener. * Unregister the {@link OnSubscriptionsChangedListener}. This is not strictly necessary
* as the listener will automatically be unregistered if an attempt to invoke the listener
* fails.
* *
* @param context * @param listener that is to be unregistered.
* @param listener
*/ */
public static void unregister(Context context, SubscriptionListener listener) { public void unregisterOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
String pkgForDebug = context != null ? context.getPackageName() : "<unknown>"; String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
if (DBG) { if (DBG) {
logd("SubscriptionManager unregister pkgForDebug=" + pkgForDebug logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
+ " listener=" + listener); + " listener=" + listener);
} }
try { try {
@@ -287,7 +375,7 @@ public class SubscriptionManager implements BaseColumns {
ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
"telephony.registry")); "telephony.registry"));
if (tr != null) { if (tr != null) {
tr.unregisterSubscriptionListener(pkgForDebug, listener.callback); tr.unregisterOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
} }
} catch (RemoteException ex) { } catch (RemoteException ex) {
// Should not happen // Should not happen
@@ -295,13 +383,14 @@ public class SubscriptionManager implements BaseColumns {
} }
/** /**
* Get the SubscriptionInfo associated with the subId * Get the active SubscriptionInfo with the subId key
* @param subId The unique SubscriptionInfo index in database * @param subId The unique SubscriptionInfo key in database
* @return SubscriptionInfo, maybe null * @return SubscriptionInfo, maybe null if its not active.
*/ */
public static SubscriptionInfo getSubscriptionInfoForSubscriber(int subId) { public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId);
if (!isValidSubId(subId)) { if (!isValidSubId(subId)) {
logd("[getSubscriptionInfoForSubscriber]- invalid subId"); logd("[getActiveSubscriptionInfo]- invalid subId");
return null; return null;
} }
@@ -310,7 +399,7 @@ public class SubscriptionManager implements BaseColumns {
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) { if (iSub != null) {
subInfo = iSub.getSubInfoForSubscriber(subId); subInfo = iSub.getActiveSubscriptionInfo(subId);
} }
} catch (RemoteException ex) { } catch (RemoteException ex) {
// ignore it // ignore it
@@ -321,73 +410,64 @@ public class SubscriptionManager implements BaseColumns {
} }
/** /**
* Get the SubscriptionInfo according to an IccId * Get the active SubscriptionInfo associated with the iccId
* @param iccId the IccId of SIM card * @param iccId the IccId of SIM card
* @return SubscriptionInfo List, maybe empty but not null * @return SubscriptionInfo, maybe null if its not active
* @hide * @hide
*/ */
public static List<SubscriptionInfo> getSubscriptionInfoUsingIccId(String iccId) { public SubscriptionInfo getActiveSubscriptionInfoForIccIndex(String iccId) {
if (VDBG) logd("[getSubscriptionInfoUsingIccId]+ iccId=" + iccId); if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId);
if (iccId == null) { if (iccId == null) {
logd("[getSubscriptionInfoUsingIccId]- null iccid"); logd("[getActiveSubscriptionInfoForIccIndex]- null iccid");
return null; return null;
} }
List<SubscriptionInfo> result = null; SubscriptionInfo result = null;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) { if (iSub != null) {
result = iSub.getSubInfoUsingIccId(iccId); result = iSub.getActiveSubscriptionInfoForIccId(iccId);
} }
} catch (RemoteException ex) { } catch (RemoteException ex) {
// ignore it // ignore it
} }
if (result == null) {
result = new ArrayList<SubscriptionInfo>();
}
return result; return result;
} }
/** /**
* Get the SubscriptionInfo according to slotId * Get the active SubscriptionInfo associated with the slotIdx
* @param slotId the slot which the SIM is inserted * @param slotIdx the slot which the subscription is inserted
* @return SubscriptionInfo list, maybe empty but not null * @return SubscriptionInfo, maybe null if its not active
*/ */
public static List<SubscriptionInfo> getSubscriptionInfoUsingSlotId(int slotId) { public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIdx) {
// FIXME: Consider never returning null if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIdx=" + slotIdx);
if (!isValidSlotId(slotId)) { if (!isValidSlotId(slotIdx)) {
logd("[getSubscriptionInfoUsingSlotId]- invalid slotId"); logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIdx");
return null; return null;
} }
List<SubscriptionInfo> result = null; SubscriptionInfo result = null;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) { if (iSub != null) {
result = iSub.getSubInfoUsingSlotId(slotId); result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIdx);
} }
} catch (RemoteException ex) { } catch (RemoteException ex) {
// ignore it // ignore it
} }
if (result == null) {
result = new ArrayList<SubscriptionInfo>();
}
return result; return result;
} }
/** /**
* Get all the SubscriptionInfo(s) in subInfo database * @return List of all SubscriptionInfo records in database,
* @return List of all SubscriptionInfos in database, include those that were inserted before * include those that were inserted before, maybe empty but not null.
* maybe empty but not null.
* @hide * @hide
*/ */
public static List<SubscriptionInfo> getAllSubscriptionInfoList() { public List<SubscriptionInfo> getAllSubscriptionInfoList() {
if (VDBG) logd("[getAllSubscriptionInfoList]+"); if (VDBG) logd("[getAllSubscriptionInfoList]+");
List<SubscriptionInfo> result = null; List<SubscriptionInfo> result = null;
@@ -408,33 +488,45 @@ public class SubscriptionManager implements BaseColumns {
} }
/** /**
* Get the SubscriptionInfo(s) of the currently inserted SIM(s) * Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted
* @return Array list of currently inserted SubscriptionInfo(s) maybe empty but not null * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
* If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener}
* has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be
* invoked in the future.
* </li>
* <li>
* If the list is empty then there are no {@link SubscriptionInfo} records currently available.
* </li>
* <li>
* if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
* then by {@link SubscriptionInfo#getSubscriptionId}.
* </li>
* </ul>
*/ */
public static List<SubscriptionInfo> getActiveSubscriptionInfoList() { public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
List<SubscriptionInfo> result = null; List<SubscriptionInfo> result = null;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) { if (iSub != null) {
result = iSub.getActiveSubInfoList(); result = iSub.getActiveSubscriptionInfoList();
} }
} catch (RemoteException ex) { } catch (RemoteException ex) {
// ignore it // ignore it
} }
if (result == null) {
result = new ArrayList<SubscriptionInfo>();
}
return result; return result;
} }
/** /**
* Get the SUB count of all SUB(s) in subinfo database * @return the count of all subscriptions in the database, this includes
* @return all SIM count in database, include what was inserted before * all subscriptions that have been seen.
* @hide * @hide
*/ */
public static int getAllSubscriptionInfoCount() { public int getAllSubscriptionInfoCount() {
if (VDBG) logd("[getAllSubscriptionInfoCount]+"); if (VDBG) logd("[getAllSubscriptionInfoCount]+");
int result = 0; int result = 0;
@@ -452,11 +544,10 @@ public class SubscriptionManager implements BaseColumns {
} }
/** /**
* Get the count of active SUB(s) * @return the number of active subscriptions
* @return active SIM count
* @hide * @hide
*/ */
public static int getActiveSubscriptionInfoCount() { public int getActiveSubscriptionInfoCount() {
int result = 0; int result = 0;
try { try {
@@ -471,6 +562,25 @@ public class SubscriptionManager implements BaseColumns {
return result; return result;
} }
/**
* @return the maximum number of subscriptions this device will support at any one time.
* @hide
*/
public int getActiveSubscriptionInfoCountMax() {
int result = 0;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
result = iSub.getActiveSubInfoCountMax();
}
} catch (RemoteException ex) {
// ignore it
}
return result;
}
/** /**
* Add a new SubscriptionInfo to subinfo database if needed * Add a new SubscriptionInfo to subinfo database if needed
* @param iccId the IccId of the SIM card * @param iccId the IccId of the SIM card
@@ -478,7 +588,7 @@ public class SubscriptionManager implements BaseColumns {
* @return the URL of the newly created row or the updated row * @return the URL of the newly created row or the updated row
* @hide * @hide
*/ */
public static Uri addSubscriptionInfoRecord(String iccId, int slotId) { public Uri addSubscriptionInfoRecord(String iccId, int slotId) {
if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotId:" + slotId); if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotId:" + slotId);
if (iccId == null) { if (iccId == null) {
logd("[addSubscriptionInfoRecord]- null iccId"); logd("[addSubscriptionInfoRecord]- null iccId");
@@ -509,7 +619,7 @@ public class SubscriptionManager implements BaseColumns {
* @return the number of records updated * @return the number of records updated
* @hide * @hide
*/ */
public static int setIconTint(int tint, int subId) { public int setIconTint(int tint, int subId) {
if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId); if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId);
if (!isValidSubId(subId)) { if (!isValidSubId(subId)) {
logd("[setIconTint]- fail"); logd("[setIconTint]- fail");
@@ -538,7 +648,7 @@ public class SubscriptionManager implements BaseColumns {
* @return the number of records updated * @return the number of records updated
* @hide * @hide
*/ */
public static int setDisplayName(String displayName, int subId) { public int setDisplayName(String displayName, int subId) {
return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED); return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED);
} }
@@ -551,7 +661,7 @@ public class SubscriptionManager implements BaseColumns {
* @return the number of records updated or -1 if invalid subId * @return the number of records updated or -1 if invalid subId
* @hide * @hide
*/ */
public static int setDisplayName(String displayName, int subId, long nameSource) { public int setDisplayName(String displayName, int subId, long nameSource) {
if (VDBG) { if (VDBG) {
logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId
+ " nameSource:" + nameSource); + " nameSource:" + nameSource);
@@ -583,7 +693,7 @@ public class SubscriptionManager implements BaseColumns {
* @return the number of records updated * @return the number of records updated
* @hide * @hide
*/ */
public static int setDisplayNumber(String number, int subId) { public int setDisplayNumber(String number, int subId) {
if (number == null || !isValidSubId(subId)) { if (number == null || !isValidSubId(subId)) {
logd("[setDisplayNumber]- fail"); logd("[setDisplayNumber]- fail");
return -1; return -1;
@@ -611,7 +721,7 @@ public class SubscriptionManager implements BaseColumns {
* @return the number of records updated * @return the number of records updated
* @hide * @hide
*/ */
public static int setDataRoaming(int roaming, int subId) { public int setDataRoaming(int roaming, int subId) {
if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId); if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
if (roaming < 0 || !isValidSubId(subId)) { if (roaming < 0 || !isValidSubId(subId)) {
logd("[setDataRoaming]- fail"); logd("[setDataRoaming]- fail");
@@ -643,7 +753,7 @@ public class SubscriptionManager implements BaseColumns {
logd("[getSlotId]- fail"); logd("[getSlotId]- fail");
} }
int result = INVALID_SLOT_ID; int result = INVALID_SIM_SLOT_INDEX;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -683,10 +793,10 @@ public class SubscriptionManager implements BaseColumns {
public static int getPhoneId(int subId) { public static int getPhoneId(int subId) {
if (!isValidSubId(subId)) { if (!isValidSubId(subId)) {
logd("[getPhoneId]- fail"); logd("[getPhoneId]- fail");
return INVALID_PHONE_ID; return INVALID_PHONE_INDEX;
} }
int result = INVALID_PHONE_ID; int result = INVALID_PHONE_INDEX;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -703,7 +813,7 @@ public class SubscriptionManager implements BaseColumns {
} }
private static void logd(String msg) { private static void logd(String msg) {
Rlog.d(LOG_TAG, "[SubManager] " + msg); Rlog.d(LOG_TAG, msg);
} }
/** /**
@@ -713,7 +823,7 @@ public class SubscriptionManager implements BaseColumns {
* @hide * @hide
*/ */
public static int getDefaultSubId() { public static int getDefaultSubId() {
int subId = INVALID_SUB_ID; int subId = INVALID_SUBSCRIPTION_ID;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -730,7 +840,7 @@ public class SubscriptionManager implements BaseColumns {
/** @hide */ /** @hide */
public static int getDefaultVoiceSubId() { public static int getDefaultVoiceSubId() {
int subId = INVALID_SUB_ID; int subId = INVALID_SUBSCRIPTION_ID;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -746,7 +856,7 @@ public class SubscriptionManager implements BaseColumns {
} }
/** @hide */ /** @hide */
public static void setDefaultVoiceSubId(int subId) { public void setDefaultVoiceSubId(int subId) {
if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId); if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId);
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -759,8 +869,8 @@ public class SubscriptionManager implements BaseColumns {
} }
/** @hide */ /** @hide */
public static SubscriptionInfo getDefaultVoiceSubscriptionInfo() { public SubscriptionInfo getDefaultVoiceSubscriptionInfo() {
return getSubscriptionInfoForSubscriber(getDefaultVoiceSubId()); return getActiveSubscriptionInfo(getDefaultVoiceSubId());
} }
/** @hide */ /** @hide */
@@ -769,11 +879,13 @@ public class SubscriptionManager implements BaseColumns {
} }
/** /**
* @return subId of the DefaultSms subscription or the value INVALID_SUB_ID if an error. * @return subId of the DefaultSms subscription or
* the value INVALID_SUBSCRIPTION_ID if an error.
*
* @hide * @hide
*/ */
public static int getDefaultSmsSubId() { public static int getDefaultSmsSubId() {
int subId = INVALID_SUB_ID; int subId = INVALID_SUBSCRIPTION_ID;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -789,7 +901,7 @@ public class SubscriptionManager implements BaseColumns {
} }
/** @hide */ /** @hide */
public static void setDefaultSmsSubId(int subId) { public void setDefaultSmsSubId(int subId) {
if (VDBG) logd("setDefaultSmsSubId sub id = " + subId); if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -802,18 +914,18 @@ public class SubscriptionManager implements BaseColumns {
} }
/** @hide */ /** @hide */
public static SubscriptionInfo getDefaultSmsSubscriptionInfo() { public SubscriptionInfo getDefaultSmsSubscriptionInfo() {
return getSubscriptionInfoForSubscriber(getDefaultSmsSubId()); return getActiveSubscriptionInfo(getDefaultSmsSubId());
} }
/** @hide */ /** @hide */
public static int getDefaultSmsPhoneId() { public int getDefaultSmsPhoneId() {
return getPhoneId(getDefaultSmsSubId()); return getPhoneId(getDefaultSmsSubId());
} }
/** @hide */ /** @hide */
public static int getDefaultDataSubId() { public static int getDefaultDataSubId() {
int subId = INVALID_SUB_ID; int subId = INVALID_SUBSCRIPTION_ID;
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -829,7 +941,7 @@ public class SubscriptionManager implements BaseColumns {
} }
/** @hide */ /** @hide */
public static void setDefaultDataSubId(int subId) { public void setDefaultDataSubId(int subId) {
if (VDBG) logd("setDataSubscription sub id = " + subId); if (VDBG) logd("setDataSubscription sub id = " + subId);
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -842,17 +954,17 @@ public class SubscriptionManager implements BaseColumns {
} }
/** @hide */ /** @hide */
public static SubscriptionInfo getDefaultDataSubscriptionInfo() { public SubscriptionInfo getDefaultDataSubscriptionInfo() {
return getSubscriptionInfoForSubscriber(getDefaultDataSubId()); return getActiveSubscriptionInfo(getDefaultDataSubId());
} }
/** @hide */ /** @hide */
public static int getDefaultDataPhoneId() { public int getDefaultDataPhoneId() {
return getPhoneId(getDefaultDataSubId()); return getPhoneId(getDefaultDataSubId());
} }
/** @hide */ /** @hide */
public static void clearSubscriptionInfo() { public void clearSubscriptionInfo() {
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) { if (iSub != null) {
@@ -867,14 +979,14 @@ public class SubscriptionManager implements BaseColumns {
//FIXME this is vulnerable to race conditions //FIXME this is vulnerable to race conditions
/** @hide */ /** @hide */
public static boolean allDefaultsSelected() { public boolean allDefaultsSelected() {
if (getDefaultDataSubId() == INVALID_SUB_ID) { if (getDefaultDataSubId() == INVALID_SUBSCRIPTION_ID) {
return false; return false;
} }
if (getDefaultSmsSubId() == INVALID_SUB_ID) { if (getDefaultSmsSubId() == INVALID_SUBSCRIPTION_ID) {
return false; return false;
} }
if (getDefaultVoiceSubId() == INVALID_SUB_ID) { if (getDefaultVoiceSubId() == INVALID_SUBSCRIPTION_ID) {
return false; return false;
} }
return true; return true;
@@ -882,10 +994,10 @@ public class SubscriptionManager implements BaseColumns {
/** /**
* If a default is set to subscription which is not active, this will reset that default back to * If a default is set to subscription which is not active, this will reset that default back to
* INVALID_SUB_ID. * INVALID_SUBSCRIPTION_ID.
* @hide * @hide
*/ */
public static void clearDefaultsForInactiveSubIds() { public void clearDefaultsForInactiveSubIds() {
if (VDBG) logd("clearDefaultsForInactiveSubIds"); if (VDBG) logd("clearDefaultsForInactiveSubIds");
try { try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
@@ -902,34 +1014,26 @@ public class SubscriptionManager implements BaseColumns {
* @hide * @hide
*/ */
public static boolean isValidSubId(int subId) { public static boolean isValidSubId(int subId) {
return subId > INVALID_SUB_ID ; return subId > INVALID_SUBSCRIPTION_ID ;
} }
/** /**
* @return true if subId is an usable subId value else false. A * @return true if subId is an usable subId value else false. A
* usable subId means its neither a INVALID_SUB_ID nor a DEFAUL_SUB_ID. * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAUL_SUB_ID.
* @hide * @hide
*/ */
public static boolean isUsableSubIdValue(int subId) { public static boolean isUsableSubIdValue(int subId) {
return subId >= MIN_SUB_ID_VALUE && subId <= MAX_SUB_ID_VALUE; return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
} }
/** @hide */ /** @hide */
public static boolean isValidSlotId(int slotId) { public static boolean isValidSlotId(int slotId) {
// We are testing INVALID_SLOT_ID and slotId >= 0 independently because we should return slotId >= 0 && slotId < TelephonyManager.getDefault().getSimCount();
// not assume that INVALID_SLOT_ID will always be a negative value. Any negative
// value is invalid.
return slotId != INVALID_SLOT_ID && slotId >= 0 &&
slotId < TelephonyManager.getDefault().getSimCount();
} }
/** @hide */ /** @hide */
public static boolean isValidPhoneId(int phoneId) { public static boolean isValidPhoneId(int phoneId) {
// We are testing INVALID_PHONE_ID and phoneId >= 0 independently because we should return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount();
// not assume that INVALID_PHONE_ID will always be a negative value. Any negative
// value is invalid.
return phoneId != INVALID_PHONE_ID && phoneId >= 0 &&
phoneId < TelephonyManager.getDefault().getPhoneCount();
} }
/** @hide */ /** @hide */
@@ -957,7 +1061,7 @@ public class SubscriptionManager implements BaseColumns {
* is never null but the length maybe 0. * is never null but the length maybe 0.
* @hide * @hide
*/ */
public static int[] getActiveSubIdList() { public int[] getActiveSubscriptionIdList() {
int[] subId = null; int[] subId = null;
try { try {
@@ -974,7 +1078,6 @@ public class SubscriptionManager implements BaseColumns {
} }
return subId; return subId;
} }
} }

View File

@@ -79,6 +79,7 @@ public class TelephonyManager {
} }
private final Context mContext; private final Context mContext;
private SubscriptionManager mSubscriptionManager;
private static String multiSimConfig = private static String multiSimConfig =
SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG); SystemProperties.get(TelephonyProperties.PROPERTY_MULTI_SIM_CONFIG);
@@ -104,6 +105,7 @@ public class TelephonyManager {
} else { } else {
mContext = context; mContext = context;
} }
mSubscriptionManager = SubscriptionManager.from(mContext);
if (sRegistry == null) { if (sRegistry == null) {
sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
@@ -157,6 +159,9 @@ public class TelephonyManager {
public int getPhoneCount() { public int getPhoneCount() {
int phoneCount = 1; int phoneCount = 1;
switch (getMultiSimConfiguration()) { switch (getMultiSimConfiguration()) {
case UNKNOWN:
phoneCount = 1;
break;
case DSDS: case DSDS:
case DSDA: case DSDA:
phoneCount = PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM; phoneCount = PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
@@ -1527,7 +1532,7 @@ public class TelephonyManager {
* @see #getSimState * @see #getSimState
*/ */
public String getSimOperator() { public String getSimOperator() {
int subId = SubscriptionManager.getDefaultDataSubId(); int subId = mSubscriptionManager.getDefaultDataSubId();
if (!SubscriptionManager.isUsableSubIdValue(subId)) { if (!SubscriptionManager.isUsableSubIdValue(subId)) {
subId = SubscriptionManager.getDefaultSmsSubId(); subId = SubscriptionManager.getDefaultSmsSubId();
if (!SubscriptionManager.isUsableSubIdValue(subId)) { if (!SubscriptionManager.isUsableSubIdValue(subId)) {
@@ -1989,7 +1994,7 @@ public class TelephonyManager {
* <p>Requires that the calling app has carrier privileges. * <p>Requires that the calling app has carrier privileges.
* @see #hasCarrierPrivileges * @see #hasCarrierPrivileges
* *
* @param subId The subscriber id. * @param subId The subscription id.
* @param alphaTag The alpha tag to display. * @param alphaTag The alpha tag to display.
* @param number The voicemail number. * @param number The voicemail number.
*/ */

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony;
oneway interface IOnSubscriptionsChangedListener {
void onSubscriptionsChanged();
}

View File

@@ -22,50 +22,70 @@ import com.android.internal.telephony.ISubscriptionListener;
interface ISub { interface ISub {
/** /**
* Get the SubscriptionInfo according to an index * @return a list of all subscriptions in the database, this includes
* @param subId The unique SubscriptionInfo index in database * all subscriptions that have been seen.
* @return SubscriptionInfo, maybe null
*/
SubscriptionInfo getSubInfoForSubscriber(int subId);
/**
* Get the SubscriptionInfo according to an IccId
* @param iccId the IccId of SIM card
* @return SubscriptionInfo, maybe null
*/
List<SubscriptionInfo> getSubInfoUsingIccId(String iccId);
/**
* Get the SubscriptionInfo according to slotId
* @param slotId the slot which the SIM is inserted
* @return SubscriptionInfo, maybe null
*/
List<SubscriptionInfo> getSubInfoUsingSlotId(int slotId);
/**
* Get all the SubscriptionInfo(s) in subinfo database
* @return Array list of all SubInfoRecords in database, include thsoe that were inserted before
*/ */
List<SubscriptionInfo> getAllSubInfoList(); List<SubscriptionInfo> getAllSubInfoList();
/** /**
* Get the SubscriptionInfo(s) of the currently inserted SIM(s) * @return the count of all subscriptions in the database, this includes
* @return Array list of currently inserted SubscriptionInfo(s) * all subscriptions that have been seen.
*/
List<SubscriptionInfo> getActiveSubInfoList();
/**
* Get the SUB count of all SUB(s) in subinfo database
* @return all SIM count in database, include what was inserted before
*/ */
int getAllSubInfoCount(); int getAllSubInfoCount();
/** /**
* Get the count of active SUB(s) * Get the active SubscriptionInfo with the subId key
* @return active SIM count * @param subId The unique SubscriptionInfo key in database
* @return SubscriptionInfo, maybe null if its not active
*/
SubscriptionInfo getActiveSubscriptionInfo(int subId);
/**
* Get the active SubscriptionInfo associated with the iccId
* @param iccId the IccId of SIM card
* @return SubscriptionInfo, maybe null if its not active
*/
SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId);
/**
* Get the active SubscriptionInfo associated with the slotIdx
* @param slotIdx the slot which the subscription is inserted
* @return SubscriptionInfo, maybe null if its not active
*/
SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIdx);
/**
* Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
* by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
*
* @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
* <ul>
* <li>
* If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener}
* has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be
* invoked in the future.
* </li>
* <li>
* If the list is empty then there are no {@link SubscriptionInfo} records currently available.
* </li>
* <li>
* if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
* then by {@link SubscriptionInfo#getSubscriptionId}.
* </li>
* </ul>
*/
List<SubscriptionInfo> getActiveSubscriptionInfoList();
/**
* @return the number of active subscriptions
*/ */
int getActiveSubInfoCount(); int getActiveSubInfoCount();
/**
* @return the maximum number of subscriptions this device will support at any one time.
*/
int getActiveSubInfoCountMax();
/** /**
* Add a new SubscriptionInfo to subinfo database if needed * Add a new SubscriptionInfo to subinfo database if needed
* @param iccId the IccId of the SIM card * @param iccId the IccId of the SIM card

View File

@@ -27,11 +27,13 @@ import android.telephony.SignalStrength;
import android.telephony.CellInfo; import android.telephony.CellInfo;
import android.telephony.VoLteServiceState; import android.telephony.VoLteServiceState;
import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.ISubscriptionListener; import com.android.internal.telephony.IOnSubscriptionsChangedListener;
interface ITelephonyRegistry { interface ITelephonyRegistry {
void registerSubscriptionListener(String pkg, ISubscriptionListener callback, int events); void registerOnSubscriptionsChangedListener(String pkg,
void unregisterSubscriptionListener(String pkg, ISubscriptionListener callback); IOnSubscriptionsChangedListener callback);
void unregisterOnSubscriptionsChangedListener(String pkg,
IOnSubscriptionsChangedListener callback);
void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow); void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events, void listenForSubscriber(in int subId, String pkg, IPhoneStateListener callback, int events,
boolean notifyNow); boolean notifyNow);