Home | History | Annotate | Download | only in telephony
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.telephony;
     18 
     19 import static android.net.NetworkPolicyManager.OVERRIDE_CONGESTED;
     20 import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
     21 
     22 import android.annotation.DurationMillisLong;
     23 import android.annotation.NonNull;
     24 import android.annotation.Nullable;
     25 import android.annotation.RequiresPermission;
     26 import android.annotation.SdkConstant;
     27 import android.annotation.SdkConstant.SdkConstantType;
     28 import android.annotation.SuppressAutoDoc;
     29 import android.annotation.SystemApi;
     30 import android.annotation.SystemService;
     31 import android.app.BroadcastOptions;
     32 import android.content.Context;
     33 import android.content.Intent;
     34 import android.content.pm.PackageInfo;
     35 import android.content.pm.PackageManager;
     36 import android.content.res.Configuration;
     37 import android.content.res.Resources;
     38 import android.net.INetworkPolicyManager;
     39 import android.net.NetworkCapabilities;
     40 import android.net.Uri;
     41 import android.os.Handler;
     42 import android.os.Looper;
     43 import android.os.Message;
     44 import android.os.RemoteException;
     45 import android.os.ServiceManager;
     46 import android.util.DisplayMetrics;
     47 
     48 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
     49 import com.android.internal.telephony.ISub;
     50 import com.android.internal.telephony.ITelephonyRegistry;
     51 import com.android.internal.telephony.PhoneConstants;
     52 
     53 import java.util.ArrayList;
     54 import java.util.Arrays;
     55 import java.util.Collections;
     56 import java.util.List;
     57 import java.util.concurrent.TimeUnit;
     58 
     59 /**
     60  * SubscriptionManager is the application interface to SubscriptionController
     61  * and provides information about the current Telephony Subscriptions.
     62  */
     63 @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
     64 public class SubscriptionManager {
     65     private static final String LOG_TAG = "SubscriptionManager";
     66     private static final boolean DBG = false;
     67     private static final boolean VDBG = false;
     68 
     69     /** An invalid subscription identifier */
     70     public static final int INVALID_SUBSCRIPTION_ID = -1;
     71 
     72     /** Base value for Dummy SUBSCRIPTION_ID's. */
     73     /** FIXME: Remove DummySubId's, but for now have them map just below INVALID_SUBSCRIPTION_ID
     74      /** @hide */
     75     public static final int DUMMY_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1;
     76 
     77     /** An invalid phone identifier */
     78     /** @hide */
     79     public static final int INVALID_PHONE_INDEX = -1;
     80 
     81     /** An invalid slot identifier */
     82     /** @hide */
     83     public static final int INVALID_SIM_SLOT_INDEX = -1;
     84 
     85     /** Indicates the caller wants the default sub id. */
     86     /** @hide */
     87     public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE;
     88 
     89     /**
     90      * Indicates the caller wants the default phone id.
     91      * Used in SubscriptionController and Phone but do we really need it???
     92      * @hide
     93      */
     94     public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE;
     95 
     96     /** Indicates the caller wants the default slot id. NOT used remove? */
     97     /** @hide */
     98     public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE;
     99 
    100     /** Minimum possible subid that represents a subscription */
    101     /** @hide */
    102     public static final int MIN_SUBSCRIPTION_ID_VALUE = 0;
    103 
    104     /** Maximum possible subid that represents a subscription */
    105     /** @hide */
    106     public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1;
    107 
    108     /** @hide */
    109     public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
    110 
    111     /**
    112      * TelephonyProvider unique key column name is the subscription id.
    113      * <P>Type: TEXT (String)</P>
    114      */
    115     /** @hide */
    116     public static final String UNIQUE_KEY_SUBSCRIPTION_ID = "_id";
    117 
    118     /**
    119      * TelephonyProvider column name for SIM ICC Identifier
    120      * <P>Type: TEXT (String)</P>
    121      */
    122     /** @hide */
    123     public static final String ICC_ID = "icc_id";
    124 
    125     /**
    126      * TelephonyProvider column name for user SIM_SlOT_INDEX
    127      * <P>Type: INTEGER (int)</P>
    128      */
    129     /** @hide */
    130     public static final String SIM_SLOT_INDEX = "sim_id";
    131 
    132     /** SIM is not inserted */
    133     /** @hide */
    134     public static final int SIM_NOT_INSERTED = -1;
    135 
    136     /**
    137      * TelephonyProvider column name for user displayed name.
    138      * <P>Type: TEXT (String)</P>
    139      */
    140     /** @hide */
    141     public static final String DISPLAY_NAME = "display_name";
    142 
    143     /**
    144      * TelephonyProvider column name for the service provider name for the SIM.
    145      * <P>Type: TEXT (String)</P>
    146      */
    147     /** @hide */
    148     public static final String CARRIER_NAME = "carrier_name";
    149 
    150     /**
    151      * Default name resource
    152      * @hide
    153      */
    154     public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName;
    155 
    156     /**
    157      * TelephonyProvider column name for source of the user displayed name.
    158      * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below
    159      *
    160      * @hide
    161      */
    162     public static final String NAME_SOURCE = "name_source";
    163 
    164     /**
    165      * The name_source is undefined
    166      * @hide
    167      */
    168     public static final int NAME_SOURCE_UNDEFINDED = -1;
    169 
    170     /**
    171      * The name_source is the default
    172      * @hide
    173      */
    174     public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
    175 
    176     /**
    177      * The name_source is from the SIM
    178      * @hide
    179      */
    180     public static final int NAME_SOURCE_SIM_SOURCE = 1;
    181 
    182     /**
    183      * The name_source is from the user
    184      * @hide
    185      */
    186     public static final int NAME_SOURCE_USER_INPUT = 2;
    187 
    188     /**
    189      * TelephonyProvider column name for the color of a SIM.
    190      * <P>Type: INTEGER (int)</P>
    191      */
    192     /** @hide */
    193     public static final String COLOR = "color";
    194 
    195     /** @hide */
    196     public static final int COLOR_1 = 0;
    197 
    198     /** @hide */
    199     public static final int COLOR_2 = 1;
    200 
    201     /** @hide */
    202     public static final int COLOR_3 = 2;
    203 
    204     /** @hide */
    205     public static final int COLOR_4 = 3;
    206 
    207     /** @hide */
    208     public static final int COLOR_DEFAULT = COLOR_1;
    209 
    210     /**
    211      * TelephonyProvider column name for the phone number of a SIM.
    212      * <P>Type: TEXT (String)</P>
    213      */
    214     /** @hide */
    215     public static final String NUMBER = "number";
    216 
    217     /**
    218      * TelephonyProvider column name for the number display format of a SIM.
    219      * <P>Type: INTEGER (int)</P>
    220      */
    221     /** @hide */
    222     public static final String DISPLAY_NUMBER_FORMAT = "display_number_format";
    223 
    224     /** @hide */
    225     public static final int DISPLAY_NUMBER_NONE = 0;
    226 
    227     /** @hide */
    228     public static final int DISPLAY_NUMBER_FIRST = 1;
    229 
    230     /** @hide */
    231     public static final int DISPLAY_NUMBER_LAST = 2;
    232 
    233     /** @hide */
    234     public static final int DISPLAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
    235 
    236     /**
    237      * TelephonyProvider column name for permission for data roaming of a SIM.
    238      * <P>Type: INTEGER (int)</P>
    239      */
    240     /** @hide */
    241     public static final String DATA_ROAMING = "data_roaming";
    242 
    243     /** Indicates that data roaming is enabled for a subscription */
    244     public static final int DATA_ROAMING_ENABLE = 1;
    245 
    246     /** Indicates that data roaming is disabled for a subscription */
    247     public static final int DATA_ROAMING_DISABLE = 0;
    248 
    249     /** @hide */
    250     public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
    251 
    252     /** @hide */
    253     public static final int SIM_PROVISIONED = 0;
    254 
    255     /**
    256      * TelephonyProvider column name for the MCC associated with a SIM.
    257      * <P>Type: INTEGER (int)</P>
    258      * @hide
    259      */
    260     public static final String MCC = "mcc";
    261 
    262     /**
    263      * TelephonyProvider column name for the MNC associated with a SIM.
    264      * <P>Type: INTEGER (int)</P>
    265      * @hide
    266      */
    267     public static final String MNC = "mnc";
    268 
    269     /**
    270      * TelephonyProvider column name for the sim provisioning status associated with a SIM.
    271      * <P>Type: INTEGER (int)</P>
    272      * @hide
    273      */
    274     public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status";
    275 
    276     /**
    277      * TelephonyProvider column name for whether a subscription is embedded (that is, present on an
    278      * eSIM).
    279      * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded.
    280      * @hide
    281      */
    282     public static final String IS_EMBEDDED = "is_embedded";
    283 
    284     /**
    285      * TelephonyProvider column name for SIM card identifier. For UICC card it is the ICCID of the
    286      * current enabled profile on the card, while for eUICC card it is the EID of the card.
    287      * <P>Type: TEXT (String)</P>
    288      * @hide
    289      */
    290      public static final String CARD_ID = "card_id";
    291 
    292     /**
    293      * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
    294      * {@link UiccAccessRule#encodeRules}. Only present if {@link #IS_EMBEDDED} is 1.
    295      * <p>TYPE: BLOB
    296      * @hide
    297      */
    298     public static final String ACCESS_RULES = "access_rules";
    299 
    300     /**
    301      * TelephonyProvider column name identifying whether an embedded subscription is on a removable
    302      * card. Such subscriptions are marked inaccessible as soon as the current card is removed.
    303      * Otherwise, they will remain accessible unless explicitly deleted. Only present if
    304      * {@link #IS_EMBEDDED} is 1.
    305      * <p>TYPE: INTEGER (int), 1 for removable or 0 for non-removable.
    306      * @hide
    307      */
    308     public static final String IS_REMOVABLE = "is_removable";
    309 
    310     /**
    311      *  TelephonyProvider column name for extreme threat in CB settings
    312      * @hide
    313      */
    314     public static final String CB_EXTREME_THREAT_ALERT = "enable_cmas_extreme_threat_alerts";
    315 
    316     /**
    317      * TelephonyProvider column name for severe threat in CB settings
    318      *@hide
    319      */
    320     public static final String CB_SEVERE_THREAT_ALERT = "enable_cmas_severe_threat_alerts";
    321 
    322     /**
    323      * TelephonyProvider column name for amber alert in CB settings
    324      *@hide
    325      */
    326     public static final String CB_AMBER_ALERT = "enable_cmas_amber_alerts";
    327 
    328     /**
    329      * TelephonyProvider column name for emergency alert in CB settings
    330      *@hide
    331      */
    332     public static final String CB_EMERGENCY_ALERT = "enable_emergency_alerts";
    333 
    334     /**
    335      * TelephonyProvider column name for alert sound duration in CB settings
    336      *@hide
    337      */
    338     public static final String CB_ALERT_SOUND_DURATION = "alert_sound_duration";
    339 
    340     /**
    341      * TelephonyProvider column name for alert reminder interval in CB settings
    342      *@hide
    343      */
    344     public static final String CB_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
    345 
    346     /**
    347      * TelephonyProvider column name for enabling vibrate in CB settings
    348      *@hide
    349      */
    350     public static final String CB_ALERT_VIBRATE = "enable_alert_vibrate";
    351 
    352     /**
    353      * TelephonyProvider column name for enabling alert speech in CB settings
    354      *@hide
    355      */
    356     public static final String CB_ALERT_SPEECH = "enable_alert_speech";
    357 
    358     /**
    359      * TelephonyProvider column name for ETWS test alert in CB settings
    360      *@hide
    361      */
    362     public static final String CB_ETWS_TEST_ALERT = "enable_etws_test_alerts";
    363 
    364     /**
    365      * TelephonyProvider column name for enable channel50 alert in CB settings
    366      *@hide
    367      */
    368     public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts";
    369 
    370     /**
    371      * TelephonyProvider column name for CMAS test alert in CB settings
    372      *@hide
    373      */
    374     public static final String CB_CMAS_TEST_ALERT= "enable_cmas_test_alerts";
    375 
    376     /**
    377      * TelephonyProvider column name for Opt out dialog in CB settings
    378      *@hide
    379      */
    380     public static final String CB_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
    381 
    382     /**
    383      * TelephonyProvider column name for enable Volte.
    384      *
    385      * If this setting is not initialized (set to -1)  then we use the Carrier Config value
    386      * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
    387      *@hide
    388      */
    389     public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
    390 
    391     /**
    392      * TelephonyProvider column name for enable VT (Video Telephony over IMS)
    393      *@hide
    394      */
    395     public static final String VT_IMS_ENABLED = "vt_ims_enabled";
    396 
    397     /**
    398      * TelephonyProvider column name for enable Wifi calling
    399      *@hide
    400      */
    401     public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
    402 
    403     /**
    404      * TelephonyProvider column name for Wifi calling mode
    405      *@hide
    406      */
    407     public static final String WFC_IMS_MODE = "wfc_ims_mode";
    408 
    409     /**
    410      * TelephonyProvider column name for Wifi calling mode in roaming
    411      *@hide
    412      */
    413     public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
    414 
    415     /**
    416      * TelephonyProvider column name for enable Wifi calling in roaming
    417      *@hide
    418      */
    419     public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
    420 
    421     /**
    422      * Broadcast Action: The user has changed one of the default subs related to
    423      * data, phone calls, or sms</p>
    424      *
    425      * TODO: Change to a listener
    426      * @hide
    427      */
    428     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    429     public static final String SUB_DEFAULT_CHANGED_ACTION =
    430             "android.intent.action.SUB_DEFAULT_CHANGED";
    431 
    432     /**
    433      * Broadcast Action: The default subscription has changed.  This has the following
    434      * extra values:</p>
    435      * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index
    436      */
    437     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    438     public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED
    439             = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
    440 
    441     /**
    442      * Broadcast Action: The default sms subscription has changed.  This has the following
    443      * extra values:</p>
    444      * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms
    445      * subscription index
    446      */
    447     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    448     public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED
    449             = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
    450 
    451     /**
    452      * Activity Action: Display UI for managing the billing relationship plans
    453      * between a carrier and a specific subscriber.
    454      * <p>
    455      * Carrier apps are encouraged to implement this activity, and the OS will
    456      * provide an affordance to quickly enter this activity, typically via
    457      * Settings. This affordance will only be shown when the carrier app is
    458      * actively providing subscription plan information via
    459      * {@link #setSubscriptionPlans(int, List)}.
    460      * <p>
    461      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
    462      * the user is interested in.
    463      */
    464     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    465     @SystemApi
    466     public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS
    467             = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
    468 
    469     /**
    470      * Broadcast Action: Request a refresh of the billing relationship plans
    471      * between a carrier and a specific subscriber.
    472      * <p>
    473      * Carrier apps are encouraged to implement this receiver, and the OS will
    474      * provide an affordance to request a refresh. This affordance will only be
    475      * shown when the carrier app is actively providing subscription plan
    476      * information via {@link #setSubscriptionPlans(int, List)}.
    477      * <p>
    478      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
    479      * the user is interested in.
    480      * <p>
    481      * Receivers should protect themselves by checking that the sender holds the
    482      * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission.
    483      */
    484     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    485     @SystemApi
    486     public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS
    487             = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
    488 
    489     /**
    490      * Broadcast Action: The billing relationship plans between a carrier and a
    491      * specific subscriber has changed.
    492      * <p>
    493      * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
    494      * changed.
    495      *
    496      * @hide
    497      */
    498     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    499     @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS)
    500     public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED
    501             = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
    502 
    503     /**
    504      * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and
    505      * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription
    506      * which has changed.
    507      */
    508     public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
    509 
    510     private final Context mContext;
    511     private volatile INetworkPolicyManager mNetworkPolicy;
    512 
    513     /**
    514      * A listener class for monitoring changes to {@link SubscriptionInfo} records.
    515      * <p>
    516      * Override the onSubscriptionsChanged method in the object that extends this
    517      * class and pass it to {@link #addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)}
    518      * to register your listener and to unregister invoke
    519      * {@link #removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)}
    520      * <p>
    521      * Permissions android.Manifest.permission.READ_PHONE_STATE is required
    522      * for #onSubscriptionsChanged to be invoked.
    523      */
    524     public static class OnSubscriptionsChangedListener {
    525         private class OnSubscriptionsChangedListenerHandler extends Handler {
    526             OnSubscriptionsChangedListenerHandler() {
    527                 super();
    528             }
    529 
    530             OnSubscriptionsChangedListenerHandler(Looper looper) {
    531                 super(looper);
    532             }
    533 
    534             @Override
    535             public void handleMessage(Message msg) {
    536                 if (DBG) {
    537                     log("handleMessage: invoke the overriden onSubscriptionsChanged()");
    538                 }
    539                 OnSubscriptionsChangedListener.this.onSubscriptionsChanged();
    540             }
    541         }
    542 
    543         private final Handler mHandler;
    544 
    545         public OnSubscriptionsChangedListener() {
    546             mHandler = new OnSubscriptionsChangedListenerHandler();
    547         }
    548 
    549         /**
    550          * Allow a listener to be created with a custom looper
    551          * @param looper the looper that the underlining handler should run on
    552          * @hide
    553          */
    554         public OnSubscriptionsChangedListener(Looper looper) {
    555             mHandler = new OnSubscriptionsChangedListenerHandler(looper);
    556         }
    557 
    558         /**
    559          * Callback invoked when there is any change to any SubscriptionInfo. Typically
    560          * this method would invoke {@link #getActiveSubscriptionInfoList}
    561          */
    562         public void onSubscriptionsChanged() {
    563             if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN");
    564         }
    565 
    566         /**
    567          * The callback methods need to be called on the handler thread where
    568          * this object was created.  If the binder did that for us it'd be nice.
    569          */
    570         IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() {
    571             @Override
    572             public void onSubscriptionsChanged() {
    573                 if (DBG) log("callback: received, sendEmptyMessage(0) to handler");
    574                 mHandler.sendEmptyMessage(0);
    575             }
    576         };
    577 
    578         private void log(String s) {
    579             Rlog.d(LOG_TAG, s);
    580         }
    581     }
    582 
    583     /** @hide */
    584     public SubscriptionManager(Context context) {
    585         if (DBG) logd("SubscriptionManager created");
    586         mContext = context;
    587     }
    588 
    589     /**
    590      * @deprecated developers should always obtain references directly from
    591      *             {@link Context#getSystemService(Class)}.
    592      */
    593     @Deprecated
    594     public static SubscriptionManager from(Context context) {
    595         return (SubscriptionManager) context
    596                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
    597     }
    598 
    599     private final INetworkPolicyManager getNetworkPolicy() {
    600         if (mNetworkPolicy == null) {
    601             mNetworkPolicy = INetworkPolicyManager.Stub
    602                     .asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
    603         }
    604         return mNetworkPolicy;
    605     }
    606 
    607     /**
    608      * Register for changes to the list of active {@link SubscriptionInfo} records or to the
    609      * individual records themselves. When a change occurs the onSubscriptionsChanged method of
    610      * the listener will be invoked immediately if there has been a notification.
    611      *
    612      * @param listener an instance of {@link OnSubscriptionsChangedListener} with
    613      *                 onSubscriptionsChanged overridden.
    614      */
    615     public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
    616         String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>";
    617         if (DBG) {
    618             logd("register OnSubscriptionsChangedListener pkgName=" + pkgName
    619                     + " listener=" + listener);
    620         }
    621         try {
    622             // We use the TelephonyRegistry as it runs in the system and thus is always
    623             // available. Where as SubscriptionController could crash and not be available
    624             ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
    625                     "telephony.registry"));
    626             if (tr != null) {
    627                 tr.addOnSubscriptionsChangedListener(pkgName, listener.callback);
    628             }
    629         } catch (RemoteException ex) {
    630             // Should not happen
    631         }
    632     }
    633 
    634     /**
    635      * Unregister the {@link OnSubscriptionsChangedListener}. This is not strictly necessary
    636      * as the listener will automatically be unregistered if an attempt to invoke the listener
    637      * fails.
    638      *
    639      * @param listener that is to be unregistered.
    640      */
    641     public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) {
    642         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
    643         if (DBG) {
    644             logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug
    645                     + " listener=" + listener);
    646         }
    647         try {
    648             // We use the TelephonyRegistry as its runs in the system and thus is always
    649             // available where as SubscriptionController could crash and not be available
    650             ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
    651                     "telephony.registry"));
    652             if (tr != null) {
    653                 tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback);
    654             }
    655         } catch (RemoteException ex) {
    656             // Should not happen
    657         }
    658     }
    659 
    660     /**
    661      * Get the active SubscriptionInfo with the input subId.
    662      *
    663      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
    664      * or that the calling app has carrier privileges (see
    665      * {@link TelephonyManager#hasCarrierPrivileges}).
    666      *
    667      * @param subId The unique SubscriptionInfo key in database.
    668      * @return SubscriptionInfo, maybe null if its not active.
    669      */
    670     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
    671     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    672     public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
    673         if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId);
    674         if (!isValidSubscriptionId(subId)) {
    675             if (DBG) {
    676                 logd("[getActiveSubscriptionInfo]- invalid subId");
    677             }
    678             return null;
    679         }
    680 
    681         SubscriptionInfo subInfo = null;
    682 
    683         try {
    684             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    685             if (iSub != null) {
    686                 subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName());
    687             }
    688         } catch (RemoteException ex) {
    689             // ignore it
    690         }
    691 
    692         return subInfo;
    693 
    694     }
    695 
    696     /**
    697      * Get the active SubscriptionInfo associated with the iccId
    698      * @param iccId the IccId of SIM card
    699      * @return SubscriptionInfo, maybe null if its not active
    700      * @hide
    701      */
    702     public SubscriptionInfo getActiveSubscriptionInfoForIccIndex(String iccId) {
    703         if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId);
    704         if (iccId == null) {
    705             logd("[getActiveSubscriptionInfoForIccIndex]- null iccid");
    706             return null;
    707         }
    708 
    709         SubscriptionInfo result = null;
    710 
    711         try {
    712             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    713             if (iSub != null) {
    714                 result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName());
    715             }
    716         } catch (RemoteException ex) {
    717             // ignore it
    718         }
    719 
    720         return result;
    721     }
    722 
    723     /**
    724      * Get the active SubscriptionInfo associated with the slotIndex
    725      *
    726      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
    727      * or that the calling app has carrier privileges (see
    728      * {@link TelephonyManager#hasCarrierPrivileges}).
    729      *
    730      * @param slotIndex the slot which the subscription is inserted
    731      * @return SubscriptionInfo, maybe null if its not active
    732      */
    733     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
    734     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    735     public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
    736         if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
    737         if (!isValidSlotIndex(slotIndex)) {
    738             logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex");
    739             return null;
    740         }
    741 
    742         SubscriptionInfo result = null;
    743 
    744         try {
    745             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    746             if (iSub != null) {
    747                 result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
    748                         mContext.getOpPackageName());
    749             }
    750         } catch (RemoteException ex) {
    751             // ignore it
    752         }
    753 
    754         return result;
    755     }
    756 
    757     /**
    758      * @return List of all SubscriptionInfo records in database,
    759      * include those that were inserted before, maybe empty but not null.
    760      * @hide
    761      */
    762     public List<SubscriptionInfo> getAllSubscriptionInfoList() {
    763         if (VDBG) logd("[getAllSubscriptionInfoList]+");
    764 
    765         List<SubscriptionInfo> result = null;
    766 
    767         try {
    768             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    769             if (iSub != null) {
    770                 result = iSub.getAllSubInfoList(mContext.getOpPackageName());
    771             }
    772         } catch (RemoteException ex) {
    773             // ignore it
    774         }
    775 
    776         if (result == null) {
    777             result = new ArrayList<>();
    778         }
    779         return result;
    780     }
    781 
    782     /**
    783      * Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted
    784      * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
    785      *
    786      * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
    787      * or that the calling app has carrier privileges (see
    788      * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
    789      * to the calling app are returned.
    790      *
    791      * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
    792      * <ul>
    793      * <li>
    794      * If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener}
    795      * has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be
    796      * invoked in the future.
    797      * </li>
    798      * <li>
    799      * If the list is empty then there are no {@link SubscriptionInfo} records currently available.
    800      * </li>
    801      * <li>
    802      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
    803      * then by {@link SubscriptionInfo#getSubscriptionId}.
    804      * </li>
    805      * </ul>
    806      */
    807     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
    808     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    809     public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
    810         List<SubscriptionInfo> result = null;
    811 
    812         try {
    813             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    814             if (iSub != null) {
    815                 result = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName());
    816             }
    817         } catch (RemoteException ex) {
    818             // ignore it
    819         }
    820         return result;
    821     }
    822 
    823     /**
    824      * Gets the SubscriptionInfo(s) of all available subscriptions, if any.
    825      *
    826      * <p>Available subscriptions include active ones (those with a non-negative
    827      * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded
    828      * subscriptions.
    829      *
    830      * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
    831      * {@link SubscriptionInfo#getSubscriptionId}.
    832      *
    833      * @return Sorted list of the current {@link SubscriptionInfo} records available on the
    834      * device.
    835      * <ul>
    836      * <li>
    837      * If null is returned the current state is unknown but if a
    838      * {@link OnSubscriptionsChangedListener} has been registered
    839      * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future.
    840      * <li>
    841      * If the list is empty then there are no {@link SubscriptionInfo} records currently available.
    842      * <li>
    843      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
    844      * then by {@link SubscriptionInfo#getSubscriptionId}.
    845      * </ul>
    846      *
    847      * <p>
    848      * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required
    849      * for #getAvailableSubscriptionInfoList to be invoked.
    850      * @hide
    851      */
    852     @SystemApi
    853     public List<SubscriptionInfo> getAvailableSubscriptionInfoList() {
    854         List<SubscriptionInfo> result = null;
    855 
    856         try {
    857             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    858             if (iSub != null) {
    859                 result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName());
    860             }
    861         } catch (RemoteException ex) {
    862             // ignore it
    863         }
    864         return result;
    865     }
    866 
    867     /**
    868      * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if
    869      * any.
    870      *
    871      * <p>Only those subscriptions for which the calling app has carrier privileges per the
    872      * subscription metadata, if any, will be included in the returned list.
    873      *
    874      * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by
    875      * {@link SubscriptionInfo#getSubscriptionId}.
    876      *
    877      * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the
    878      * device which are accessible to the caller.
    879      * <ul>
    880      * <li>
    881      * If null is returned the current state is unknown but if a
    882      * {@link OnSubscriptionsChangedListener} has been registered
    883      * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future.
    884      * <li>
    885      * If the list is empty then there are no {@link SubscriptionInfo} records currently available.
    886      * <li>
    887      * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex}
    888      * then by {@link SubscriptionInfo#getSubscriptionId}.
    889      * </ul>
    890      */
    891     public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() {
    892         List<SubscriptionInfo> result = null;
    893 
    894         try {
    895             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    896             if (iSub != null) {
    897                 result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName());
    898             }
    899         } catch (RemoteException ex) {
    900             // ignore it
    901         }
    902         return result;
    903     }
    904 
    905     /**
    906      * Request a refresh of the platform cache of profile information.
    907      *
    908      * <p>Should be called by the EuiccService implementation whenever this information changes due
    909      * to an operation done outside the scope of a request initiated by the platform to the
    910      * EuiccService. There is no need to refresh for downloads, deletes, or other operations that
    911      * were made through the EuiccService.
    912      *
    913      * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission.
    914      * @hide
    915      */
    916     @SystemApi
    917     public void requestEmbeddedSubscriptionInfoListRefresh() {
    918         try {
    919             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    920             if (iSub != null) {
    921                 iSub.requestEmbeddedSubscriptionInfoListRefresh();
    922             }
    923         } catch (RemoteException ex) {
    924             // ignore it
    925         }
    926     }
    927 
    928     /**
    929      * @return the count of all subscriptions in the database, this includes
    930      * all subscriptions that have been seen.
    931      * @hide
    932      */
    933     public int getAllSubscriptionInfoCount() {
    934         if (VDBG) logd("[getAllSubscriptionInfoCount]+");
    935 
    936         int result = 0;
    937 
    938         try {
    939             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    940             if (iSub != null) {
    941                 result = iSub.getAllSubInfoCount(mContext.getOpPackageName());
    942             }
    943         } catch (RemoteException ex) {
    944             // ignore it
    945         }
    946 
    947         return result;
    948     }
    949 
    950     /**
    951      *
    952      * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
    953      * or that the calling app has carrier privileges (see
    954      * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include
    955      * only those subscriptions accessible to the caller.
    956      *
    957      * @return the current number of active subscriptions. There is no guarantee the value
    958      * returned by this method will be the same as the length of the list returned by
    959      * {@link #getActiveSubscriptionInfoList}.
    960      */
    961     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
    962     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    963     public int getActiveSubscriptionInfoCount() {
    964         int result = 0;
    965 
    966         try {
    967             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    968             if (iSub != null) {
    969                 result = iSub.getActiveSubInfoCount(mContext.getOpPackageName());
    970             }
    971         } catch (RemoteException ex) {
    972             // ignore it
    973         }
    974 
    975         return result;
    976     }
    977 
    978     /**
    979      * @return the maximum number of active subscriptions that will be returned by
    980      * {@link #getActiveSubscriptionInfoList} and the value returned by
    981      * {@link #getActiveSubscriptionInfoCount}.
    982      */
    983     public int getActiveSubscriptionInfoCountMax() {
    984         int result = 0;
    985 
    986         try {
    987             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
    988             if (iSub != null) {
    989                 result = iSub.getActiveSubInfoCountMax();
    990             }
    991         } catch (RemoteException ex) {
    992             // ignore it
    993         }
    994 
    995         return result;
    996     }
    997 
    998     /**
    999      * Add a new SubscriptionInfo to SubscriptionInfo database if needed
   1000      * @param iccId the IccId of the SIM card
   1001      * @param slotIndex the slot which the SIM is inserted
   1002      * @return the URL of the newly created row or the updated row
   1003      * @hide
   1004      */
   1005     public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) {
   1006         if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex);
   1007         if (iccId == null) {
   1008             logd("[addSubscriptionInfoRecord]- null iccId");
   1009         }
   1010         if (!isValidSlotIndex(slotIndex)) {
   1011             logd("[addSubscriptionInfoRecord]- invalid slotIndex");
   1012         }
   1013 
   1014         try {
   1015             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1016             if (iSub != null) {
   1017                 // FIXME: This returns 1 on success, 0 on error should should we return it?
   1018                 iSub.addSubInfoRecord(iccId, slotIndex);
   1019             } else {
   1020                 logd("[addSubscriptionInfoRecord]- ISub service is null");
   1021             }
   1022         } catch (RemoteException ex) {
   1023             // ignore it
   1024         }
   1025 
   1026         // FIXME: Always returns null?
   1027         return null;
   1028 
   1029     }
   1030 
   1031     /**
   1032      * Set SIM icon tint color by simInfo index
   1033      * @param tint the RGB value of icon tint color of the SIM
   1034      * @param subId the unique SubInfoRecord index in database
   1035      * @return the number of records updated
   1036      * @hide
   1037      */
   1038     public int setIconTint(int tint, int subId) {
   1039         if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId);
   1040         if (!isValidSubscriptionId(subId)) {
   1041             logd("[setIconTint]- fail");
   1042             return -1;
   1043         }
   1044 
   1045         int result = 0;
   1046 
   1047         try {
   1048             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1049             if (iSub != null) {
   1050                 result = iSub.setIconTint(tint, subId);
   1051             }
   1052         } catch (RemoteException ex) {
   1053             // ignore it
   1054         }
   1055 
   1056         return result;
   1057 
   1058     }
   1059 
   1060     /**
   1061      * Set display name by simInfo index
   1062      * @param displayName the display name of SIM card
   1063      * @param subId the unique SubscriptionInfo index in database
   1064      * @return the number of records updated
   1065      * @hide
   1066      */
   1067     public int setDisplayName(String displayName, int subId) {
   1068         return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED);
   1069     }
   1070 
   1071     /**
   1072      * Set display name by simInfo index with name source
   1073      * @param displayName the display name of SIM card
   1074      * @param subId the unique SubscriptionInfo index in database
   1075      * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE,
   1076      *                   2: NAME_SOURCE_USER_INPUT, -1 NAME_SOURCE_UNDEFINED
   1077      * @return the number of records updated or < 0 if invalid subId
   1078      * @hide
   1079      */
   1080     public int setDisplayName(String displayName, int subId, long nameSource) {
   1081         if (VDBG) {
   1082             logd("[setDisplayName]+  displayName:" + displayName + " subId:" + subId
   1083                     + " nameSource:" + nameSource);
   1084         }
   1085         if (!isValidSubscriptionId(subId)) {
   1086             logd("[setDisplayName]- fail");
   1087             return -1;
   1088         }
   1089 
   1090         int result = 0;
   1091 
   1092         try {
   1093             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1094             if (iSub != null) {
   1095                 result = iSub.setDisplayNameUsingSrc(displayName, subId, nameSource);
   1096             }
   1097         } catch (RemoteException ex) {
   1098             // ignore it
   1099         }
   1100 
   1101         return result;
   1102 
   1103     }
   1104 
   1105     /**
   1106      * Set phone number by subId
   1107      * @param number the phone number of the SIM
   1108      * @param subId the unique SubscriptionInfo index in database
   1109      * @return the number of records updated
   1110      * @hide
   1111      */
   1112     public int setDisplayNumber(String number, int subId) {
   1113         if (number == null || !isValidSubscriptionId(subId)) {
   1114             logd("[setDisplayNumber]- fail");
   1115             return -1;
   1116         }
   1117 
   1118         int result = 0;
   1119 
   1120         try {
   1121             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1122             if (iSub != null) {
   1123                 result = iSub.setDisplayNumber(number, subId);
   1124             }
   1125         } catch (RemoteException ex) {
   1126             // ignore it
   1127         }
   1128 
   1129         return result;
   1130 
   1131     }
   1132 
   1133     /**
   1134      * Set data roaming by simInfo index
   1135      * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming
   1136      * @param subId the unique SubscriptionInfo index in database
   1137      * @return the number of records updated
   1138      * @hide
   1139      */
   1140     public int setDataRoaming(int roaming, int subId) {
   1141         if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId);
   1142         if (roaming < 0 || !isValidSubscriptionId(subId)) {
   1143             logd("[setDataRoaming]- fail");
   1144             return -1;
   1145         }
   1146 
   1147         int result = 0;
   1148 
   1149         try {
   1150             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1151             if (iSub != null) {
   1152                 result = iSub.setDataRoaming(roaming, subId);
   1153             }
   1154         } catch (RemoteException ex) {
   1155             // ignore it
   1156         }
   1157 
   1158         return result;
   1159     }
   1160 
   1161     /**
   1162      * Get slotIndex associated with the subscription.
   1163      * @return slotIndex as a positive integer or a negative value if an error either
   1164      * SIM_NOT_INSERTED or < 0 if an invalid slot index
   1165      * @hide
   1166      */
   1167     public static int getSlotIndex(int subId) {
   1168         if (!isValidSubscriptionId(subId)) {
   1169             if (DBG) {
   1170                 logd("[getSlotIndex]- fail");
   1171             }
   1172         }
   1173 
   1174         int result = INVALID_SIM_SLOT_INDEX;
   1175 
   1176         try {
   1177             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1178             if (iSub != null) {
   1179                 result = iSub.getSlotIndex(subId);
   1180             }
   1181         } catch (RemoteException ex) {
   1182             // ignore it
   1183         }
   1184 
   1185         return result;
   1186 
   1187     }
   1188 
   1189     /** @hide */
   1190     public static int[] getSubId(int slotIndex) {
   1191         if (!isValidSlotIndex(slotIndex)) {
   1192             logd("[getSubId]- fail");
   1193             return null;
   1194         }
   1195 
   1196         int[] subId = null;
   1197 
   1198         try {
   1199             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1200             if (iSub != null) {
   1201                 subId = iSub.getSubId(slotIndex);
   1202             }
   1203         } catch (RemoteException ex) {
   1204             // ignore it
   1205         }
   1206 
   1207         return subId;
   1208     }
   1209 
   1210     /** @hide */
   1211     public static int getPhoneId(int subId) {
   1212         if (!isValidSubscriptionId(subId)) {
   1213             if (DBG) {
   1214                 logd("[getPhoneId]- fail");
   1215             }
   1216             return INVALID_PHONE_INDEX;
   1217         }
   1218 
   1219         int result = INVALID_PHONE_INDEX;
   1220 
   1221         try {
   1222             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1223             if (iSub != null) {
   1224                 result = iSub.getPhoneId(subId);
   1225             }
   1226         } catch (RemoteException ex) {
   1227             // ignore it
   1228         }
   1229 
   1230         if (VDBG) logd("[getPhoneId]- phoneId=" + result);
   1231         return result;
   1232 
   1233     }
   1234 
   1235     private static void logd(String msg) {
   1236         Rlog.d(LOG_TAG, msg);
   1237     }
   1238 
   1239     /**
   1240      * Returns the system's default subscription id.
   1241      *
   1242      * For a voice capable device, it will return getDefaultVoiceSubscriptionId.
   1243      * For a data only device, it will return the getDefaultDataSubscriptionId.
   1244      * May return an INVALID_SUBSCRIPTION_ID on error.
   1245      *
   1246      * @return the "system" default subscription id.
   1247      */
   1248     public static int getDefaultSubscriptionId() {
   1249         int subId = INVALID_SUBSCRIPTION_ID;
   1250 
   1251         try {
   1252             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1253             if (iSub != null) {
   1254                 subId = iSub.getDefaultSubId();
   1255             }
   1256         } catch (RemoteException ex) {
   1257             // ignore it
   1258         }
   1259 
   1260         if (VDBG) logd("getDefaultSubId=" + subId);
   1261         return subId;
   1262     }
   1263 
   1264     /**
   1265      * Returns the system's default voice subscription id.
   1266      *
   1267      * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID.
   1268      *
   1269      * @return the default voice subscription Id.
   1270      */
   1271     public static int getDefaultVoiceSubscriptionId() {
   1272         int subId = INVALID_SUBSCRIPTION_ID;
   1273 
   1274         try {
   1275             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1276             if (iSub != null) {
   1277                 subId = iSub.getDefaultVoiceSubId();
   1278             }
   1279         } catch (RemoteException ex) {
   1280             // ignore it
   1281         }
   1282 
   1283         if (VDBG) logd("getDefaultVoiceSubscriptionId, sub id = " + subId);
   1284         return subId;
   1285     }
   1286 
   1287     /** @hide */
   1288     public void setDefaultVoiceSubId(int subId) {
   1289         if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId);
   1290         try {
   1291             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1292             if (iSub != null) {
   1293                 iSub.setDefaultVoiceSubId(subId);
   1294             }
   1295         } catch (RemoteException ex) {
   1296             // ignore it
   1297         }
   1298     }
   1299 
   1300     /**
   1301      * Return the SubscriptionInfo for default voice subscription.
   1302      *
   1303      * Will return null on data only devices, or on error.
   1304      *
   1305      * @return the SubscriptionInfo for the default voice subscription.
   1306      * @hide
   1307      */
   1308     public SubscriptionInfo getDefaultVoiceSubscriptionInfo() {
   1309         return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId());
   1310     }
   1311 
   1312     /** @hide */
   1313     public static int getDefaultVoicePhoneId() {
   1314         return getPhoneId(getDefaultVoiceSubscriptionId());
   1315     }
   1316 
   1317     /**
   1318      * Returns the system's default SMS subscription id.
   1319      *
   1320      * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID.
   1321      *
   1322      * @return the default SMS subscription Id.
   1323      */
   1324     public static int getDefaultSmsSubscriptionId() {
   1325         int subId = INVALID_SUBSCRIPTION_ID;
   1326 
   1327         try {
   1328             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1329             if (iSub != null) {
   1330                 subId = iSub.getDefaultSmsSubId();
   1331             }
   1332         } catch (RemoteException ex) {
   1333             // ignore it
   1334         }
   1335 
   1336         if (VDBG) logd("getDefaultSmsSubscriptionId, sub id = " + subId);
   1337         return subId;
   1338     }
   1339 
   1340     /** @hide */
   1341     public void setDefaultSmsSubId(int subId) {
   1342         if (VDBG) logd("setDefaultSmsSubId sub id = " + subId);
   1343         try {
   1344             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1345             if (iSub != null) {
   1346                 iSub.setDefaultSmsSubId(subId);
   1347             }
   1348         } catch (RemoteException ex) {
   1349             // ignore it
   1350         }
   1351     }
   1352 
   1353     /**
   1354      * Return the SubscriptionInfo for default voice subscription.
   1355      *
   1356      * Will return null on data only devices, or on error.
   1357      *
   1358      * @return the SubscriptionInfo for the default SMS subscription.
   1359      * @hide
   1360      */
   1361     public SubscriptionInfo getDefaultSmsSubscriptionInfo() {
   1362         return getActiveSubscriptionInfo(getDefaultSmsSubscriptionId());
   1363     }
   1364 
   1365     /** @hide */
   1366     public int getDefaultSmsPhoneId() {
   1367         return getPhoneId(getDefaultSmsSubscriptionId());
   1368     }
   1369 
   1370     /**
   1371      * Returns the system's default data subscription id.
   1372      *
   1373      * On a voice only device or on error, will return INVALID_SUBSCRIPTION_ID.
   1374      *
   1375      * @return the default data subscription Id.
   1376      */
   1377     public static int getDefaultDataSubscriptionId() {
   1378         int subId = INVALID_SUBSCRIPTION_ID;
   1379 
   1380         try {
   1381             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1382             if (iSub != null) {
   1383                 subId = iSub.getDefaultDataSubId();
   1384             }
   1385         } catch (RemoteException ex) {
   1386             // ignore it
   1387         }
   1388 
   1389         if (VDBG) logd("getDefaultDataSubscriptionId, sub id = " + subId);
   1390         return subId;
   1391     }
   1392 
   1393     /** @hide */
   1394     public void setDefaultDataSubId(int subId) {
   1395         if (VDBG) logd("setDataSubscription sub id = " + subId);
   1396         try {
   1397             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1398             if (iSub != null) {
   1399                 iSub.setDefaultDataSubId(subId);
   1400             }
   1401         } catch (RemoteException ex) {
   1402             // ignore it
   1403         }
   1404     }
   1405 
   1406     /**
   1407      * Return the SubscriptionInfo for default data subscription.
   1408      *
   1409      * Will return null on voice only devices, or on error.
   1410      *
   1411      * @return the SubscriptionInfo for the default data subscription.
   1412      * @hide
   1413      */
   1414     public SubscriptionInfo getDefaultDataSubscriptionInfo() {
   1415         return getActiveSubscriptionInfo(getDefaultDataSubscriptionId());
   1416     }
   1417 
   1418     /** @hide */
   1419     public int getDefaultDataPhoneId() {
   1420         return getPhoneId(getDefaultDataSubscriptionId());
   1421     }
   1422 
   1423     /** @hide */
   1424     public void clearSubscriptionInfo() {
   1425         try {
   1426             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1427             if (iSub != null) {
   1428                 iSub.clearSubInfo();
   1429             }
   1430         } catch (RemoteException ex) {
   1431             // ignore it
   1432         }
   1433 
   1434         return;
   1435     }
   1436 
   1437     //FIXME this is vulnerable to race conditions
   1438     /** @hide */
   1439     public boolean allDefaultsSelected() {
   1440         if (!isValidSubscriptionId(getDefaultDataSubscriptionId())) {
   1441             return false;
   1442         }
   1443         if (!isValidSubscriptionId(getDefaultSmsSubscriptionId())) {
   1444             return false;
   1445         }
   1446         if (!isValidSubscriptionId(getDefaultVoiceSubscriptionId())) {
   1447             return false;
   1448         }
   1449         return true;
   1450     }
   1451 
   1452     /**
   1453      * If a default is set to subscription which is not active, this will reset that default back to
   1454      * an invalid subscription id, i.e. < 0.
   1455      * @hide
   1456      */
   1457     public void clearDefaultsForInactiveSubIds() {
   1458         if (VDBG) logd("clearDefaultsForInactiveSubIds");
   1459         try {
   1460             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1461             if (iSub != null) {
   1462                 iSub.clearDefaultsForInactiveSubIds();
   1463             }
   1464         } catch (RemoteException ex) {
   1465             // ignore it
   1466         }
   1467     }
   1468 
   1469     /**
   1470      * @return true if a valid subId else false
   1471      * @hide
   1472      */
   1473     public static boolean isValidSubscriptionId(int subId) {
   1474         return subId > INVALID_SUBSCRIPTION_ID ;
   1475     }
   1476 
   1477     /**
   1478      * @return true if subId is an usable subId value else false. A
   1479      * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID.
   1480      * @hide
   1481      */
   1482     public static boolean isUsableSubIdValue(int subId) {
   1483         return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE;
   1484     }
   1485 
   1486     /** @hide */
   1487     public static boolean isValidSlotIndex(int slotIndex) {
   1488         return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount();
   1489     }
   1490 
   1491     /** @hide */
   1492     public static boolean isValidPhoneId(int phoneId) {
   1493         return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount();
   1494     }
   1495 
   1496     /** @hide */
   1497     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
   1498         int[] subIds = SubscriptionManager.getSubId(phoneId);
   1499         if (subIds != null && subIds.length > 0) {
   1500             putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
   1501         } else {
   1502             logd("putPhoneIdAndSubIdExtra: no valid subs");
   1503         }
   1504     }
   1505 
   1506     /** @hide */
   1507     public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
   1508         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
   1509         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
   1510         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
   1511         intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
   1512         //FIXME this is using phoneId and slotIndex interchangeably
   1513         //Eventually, this should be removed as it is not the slot id
   1514         intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
   1515     }
   1516 
   1517     /**
   1518      * @return the list of subId's that are active,
   1519      *         is never null but the length maybe 0.
   1520      * @hide
   1521      */
   1522     public @NonNull int[] getActiveSubscriptionIdList() {
   1523         int[] subId = null;
   1524 
   1525         try {
   1526             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1527             if (iSub != null) {
   1528                 subId = iSub.getActiveSubIdList();
   1529             }
   1530         } catch (RemoteException ex) {
   1531             // ignore it
   1532         }
   1533 
   1534         if (subId == null) {
   1535             subId = new int[0];
   1536         }
   1537 
   1538         return subId;
   1539 
   1540     }
   1541 
   1542     /**
   1543      * Returns true if the device is considered roaming on the current
   1544      * network for a subscription.
   1545      * <p>
   1546      * Availability: Only when user registered to a network.
   1547      *
   1548      * @param subId The subscription ID
   1549      * @return true if the network for the subscription is roaming, false otherwise
   1550      */
   1551     public boolean isNetworkRoaming(int subId) {
   1552         final int phoneId = getPhoneId(subId);
   1553         if (phoneId < 0) {
   1554             // What else can we do?
   1555             return false;
   1556         }
   1557         return TelephonyManager.getDefault().isNetworkRoaming(subId);
   1558     }
   1559 
   1560     /**
   1561      * Returns a constant indicating the state of sim for the slot index.
   1562      *
   1563      * @param slotIndex
   1564      *
   1565      * {@See TelephonyManager#SIM_STATE_UNKNOWN}
   1566      * {@See TelephonyManager#SIM_STATE_ABSENT}
   1567      * {@See TelephonyManager#SIM_STATE_PIN_REQUIRED}
   1568      * {@See TelephonyManager#SIM_STATE_PUK_REQUIRED}
   1569      * {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED}
   1570      * {@See TelephonyManager#SIM_STATE_READY}
   1571      * {@See TelephonyManager#SIM_STATE_NOT_READY}
   1572      * {@See TelephonyManager#SIM_STATE_PERM_DISABLED}
   1573      * {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR}
   1574      *
   1575      * {@hide}
   1576      */
   1577     public static int getSimStateForSlotIndex(int slotIndex) {
   1578         int simState = TelephonyManager.SIM_STATE_UNKNOWN;
   1579 
   1580         try {
   1581             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1582             if (iSub != null) {
   1583                 simState = iSub.getSimStateForSlotIndex(slotIndex);
   1584             }
   1585         } catch (RemoteException ex) {
   1586         }
   1587 
   1588         return simState;
   1589     }
   1590 
   1591     /**
   1592      * Store properties associated with SubscriptionInfo in database
   1593      * @param subId Subscription Id of Subscription
   1594      * @param propKey Column name in database associated with SubscriptionInfo
   1595      * @param propValue Value to store in DB for particular subId & column name
   1596      * @hide
   1597      */
   1598     public static void setSubscriptionProperty(int subId, String propKey, String propValue) {
   1599         try {
   1600             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1601             if (iSub != null) {
   1602                 iSub.setSubscriptionProperty(subId, propKey, propValue);
   1603             }
   1604         } catch (RemoteException ex) {
   1605             // ignore it
   1606         }
   1607     }
   1608 
   1609     /**
   1610      * Store properties associated with SubscriptionInfo in database
   1611      * @param subId Subscription Id of Subscription
   1612      * @param propKey Column name in SubscriptionInfo database
   1613      * @return Value associated with subId and propKey column in database
   1614      * @hide
   1615      */
   1616     private static String getSubscriptionProperty(int subId, String propKey,
   1617             Context context) {
   1618         String resultValue = null;
   1619         try {
   1620             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1621             if (iSub != null) {
   1622                 resultValue = iSub.getSubscriptionProperty(subId, propKey,
   1623                         context.getOpPackageName());
   1624             }
   1625         } catch (RemoteException ex) {
   1626             // ignore it
   1627         }
   1628         return resultValue;
   1629     }
   1630 
   1631     /**
   1632      * Returns boolean value corresponding to query result.
   1633      * @param subId Subscription Id of Subscription
   1634      * @param propKey Column name in SubscriptionInfo database
   1635      * @param defValue Default boolean value to be returned
   1636      * @return boolean result value to be returned
   1637      * @hide
   1638      */
   1639     public static boolean getBooleanSubscriptionProperty(int subId, String propKey,
   1640             boolean defValue, Context context) {
   1641         String result = getSubscriptionProperty(subId, propKey, context);
   1642         if (result != null) {
   1643             try {
   1644                 return Integer.parseInt(result) == 1;
   1645             } catch (NumberFormatException err) {
   1646                 logd("getBooleanSubscriptionProperty NumberFormat exception");
   1647             }
   1648         }
   1649         return defValue;
   1650     }
   1651 
   1652     /**
   1653      * Returns integer value corresponding to query result.
   1654      * @param subId Subscription Id of Subscription
   1655      * @param propKey Column name in SubscriptionInfo database
   1656      * @param defValue Default integer value to be returned
   1657      * @return integer result value to be returned
   1658      * @hide
   1659      */
   1660     public static int getIntegerSubscriptionProperty(int subId, String propKey, int defValue,
   1661             Context context) {
   1662         String result = getSubscriptionProperty(subId, propKey, context);
   1663         if (result != null) {
   1664             try {
   1665                 return Integer.parseInt(result);
   1666             } catch (NumberFormatException err) {
   1667                 logd("getBooleanSubscriptionProperty NumberFormat exception");
   1668             }
   1669         }
   1670         return defValue;
   1671     }
   1672 
   1673     /**
   1674      * Returns the resources associated with Subscription.
   1675      * @param context Context object
   1676      * @param subId Subscription Id of Subscription who's resources are required
   1677      * @return Resources associated with Subscription.
   1678      * @hide
   1679      */
   1680     public static Resources getResourcesForSubId(Context context, int subId) {
   1681         final SubscriptionInfo subInfo =
   1682                 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId);
   1683 
   1684         Configuration config = context.getResources().getConfiguration();
   1685         Configuration newConfig = new Configuration();
   1686         newConfig.setTo(config);
   1687         if (subInfo != null) {
   1688             newConfig.mcc = subInfo.getMcc();
   1689             newConfig.mnc = subInfo.getMnc();
   1690             if (newConfig.mnc == 0) newConfig.mnc = Configuration.MNC_ZERO;
   1691         }
   1692         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
   1693         DisplayMetrics newMetrics = new DisplayMetrics();
   1694         newMetrics.setTo(metrics);
   1695         return new Resources(context.getResources().getAssets(), newMetrics, newConfig);
   1696     }
   1697 
   1698     /**
   1699      * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription
   1700      * and the SIM providing the subscription is present in a slot and in "LOADED" state.
   1701      * @hide
   1702      */
   1703     public boolean isActiveSubId(int subId) {
   1704         try {
   1705             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
   1706             if (iSub != null) {
   1707                 return iSub.isActiveSubId(subId);
   1708             }
   1709         } catch (RemoteException ex) {
   1710         }
   1711         return false;
   1712     }
   1713 
   1714     /**
   1715      * Get the description of the billing relationship plan between a carrier
   1716      * and a specific subscriber.
   1717      * <p>
   1718      * This method is only accessible to the following narrow set of apps:
   1719      * <ul>
   1720      * <li>The carrier app for this subscriberId, as determined by
   1721      * {@link TelephonyManager#hasCarrierPrivileges()}.
   1722      * <li>The carrier app explicitly delegated access through
   1723      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
   1724      * </ul>
   1725      *
   1726      * @param subId the subscriber this relationship applies to
   1727      * @throws SecurityException if the caller doesn't meet the requirements
   1728      *             outlined above.
   1729      */
   1730     @SystemApi
   1731     public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
   1732         try {
   1733             SubscriptionPlan[] subscriptionPlans =
   1734                     getNetworkPolicy().getSubscriptionPlans(subId, mContext.getOpPackageName());
   1735             return subscriptionPlans == null
   1736                     ? Collections.emptyList() : Arrays.asList(subscriptionPlans);
   1737         } catch (RemoteException e) {
   1738             throw e.rethrowFromSystemServer();
   1739         }
   1740     }
   1741 
   1742     /**
   1743      * Set the description of the billing relationship plan between a carrier
   1744      * and a specific subscriber.
   1745      * <p>
   1746      * This method is only accessible to the following narrow set of apps:
   1747      * <ul>
   1748      * <li>The carrier app for this subscriberId, as determined by
   1749      * {@link TelephonyManager#hasCarrierPrivileges()}.
   1750      * <li>The carrier app explicitly delegated access through
   1751      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
   1752      * </ul>
   1753      *
   1754      * @param subId the subscriber this relationship applies to. An empty list
   1755      *            may be sent to clear any existing plans.
   1756      * @param plans the list of plans. The first plan is always the primary and
   1757      *            most important plan. Any additional plans are secondary and
   1758      *            may not be displayed or used by decision making logic.
   1759      * @throws SecurityException if the caller doesn't meet the requirements
   1760      *             outlined above.
   1761      */
   1762     @SystemApi
   1763     public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
   1764         try {
   1765             getNetworkPolicy().setSubscriptionPlans(subId,
   1766                     plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName());
   1767         } catch (RemoteException e) {
   1768             throw e.rethrowFromSystemServer();
   1769         }
   1770     }
   1771 
   1772     /** @hide */
   1773     private String getSubscriptionPlansOwner(int subId) {
   1774         try {
   1775             return getNetworkPolicy().getSubscriptionPlansOwner(subId);
   1776         } catch (RemoteException e) {
   1777             throw e.rethrowFromSystemServer();
   1778         }
   1779     }
   1780 
   1781     /**
   1782      * Temporarily override the billing relationship plan between a carrier and
   1783      * a specific subscriber to be considered unmetered. This will be reflected
   1784      * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}.
   1785      * <p>
   1786      * This method is only accessible to the following narrow set of apps:
   1787      * <ul>
   1788      * <li>The carrier app for this subscriberId, as determined by
   1789      * {@link TelephonyManager#hasCarrierPrivileges()}.
   1790      * <li>The carrier app explicitly delegated access through
   1791      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
   1792      * </ul>
   1793      *
   1794      * @param subId the subscriber this override applies to.
   1795      * @param overrideUnmetered set if the billing relationship should be
   1796      *            considered unmetered.
   1797      * @param timeoutMillis the timeout after which the requested override will
   1798      *            be automatically cleared, or {@code 0} to leave in the
   1799      *            requested state until explicitly cleared, or the next reboot,
   1800      *            whichever happens first.
   1801      * @throws SecurityException if the caller doesn't meet the requirements
   1802      *             outlined above.
   1803      */
   1804     @SystemApi
   1805     public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
   1806             @DurationMillisLong long timeoutMillis) {
   1807         try {
   1808             final int overrideValue = overrideUnmetered ? OVERRIDE_UNMETERED : 0;
   1809             getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_UNMETERED, overrideValue,
   1810                     timeoutMillis, mContext.getOpPackageName());
   1811         } catch (RemoteException e) {
   1812             throw e.rethrowFromSystemServer();
   1813         }
   1814     }
   1815 
   1816     /**
   1817      * Temporarily override the billing relationship plan between a carrier and
   1818      * a specific subscriber to be considered congested. This will cause the
   1819      * device to delay certain network requests when possible, such as developer
   1820      * jobs that are willing to run in a flexible time window.
   1821      * <p>
   1822      * This method is only accessible to the following narrow set of apps:
   1823      * <ul>
   1824      * <li>The carrier app for this subscriberId, as determined by
   1825      * {@link TelephonyManager#hasCarrierPrivileges()}.
   1826      * <li>The carrier app explicitly delegated access through
   1827      * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
   1828      * </ul>
   1829      *
   1830      * @param subId the subscriber this override applies to.
   1831      * @param overrideCongested set if the subscription should be considered
   1832      *            congested.
   1833      * @param timeoutMillis the timeout after which the requested override will
   1834      *            be automatically cleared, or {@code 0} to leave in the
   1835      *            requested state until explicitly cleared, or the next reboot,
   1836      *            whichever happens first.
   1837      * @throws SecurityException if the caller doesn't meet the requirements
   1838      *             outlined above.
   1839      */
   1840     @SystemApi
   1841     public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
   1842             @DurationMillisLong long timeoutMillis) {
   1843         try {
   1844             final int overrideValue = overrideCongested ? OVERRIDE_CONGESTED : 0;
   1845             getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_CONGESTED, overrideValue,
   1846                     timeoutMillis, mContext.getOpPackageName());
   1847         } catch (RemoteException e) {
   1848             throw e.rethrowFromSystemServer();
   1849         }
   1850     }
   1851 
   1852     /**
   1853      * Create an {@link Intent} that can be launched towards the carrier app
   1854      * that is currently defining the billing relationship plan through
   1855      * {@link #setSubscriptionPlans(int, List)}.
   1856      *
   1857      * @return ready to launch Intent targeted towards the carrier app, or
   1858      *         {@code null} if no carrier app is defined, or if the defined
   1859      *         carrier app provides no management activity.
   1860      * @hide
   1861      */
   1862     public @Nullable Intent createManageSubscriptionIntent(int subId) {
   1863         // Bail if no owner
   1864         final String owner = getSubscriptionPlansOwner(subId);
   1865         if (owner == null) return null;
   1866 
   1867         // Bail if no plans
   1868         final List<SubscriptionPlan> plans = getSubscriptionPlans(subId);
   1869         if (plans.isEmpty()) return null;
   1870 
   1871         final Intent intent = new Intent(ACTION_MANAGE_SUBSCRIPTION_PLANS);
   1872         intent.setPackage(owner);
   1873         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
   1874 
   1875         // Bail if not implemented
   1876         if (mContext.getPackageManager().queryIntentActivities(intent,
   1877                 PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
   1878             return null;
   1879         }
   1880 
   1881         return intent;
   1882     }
   1883 
   1884     /** @hide */
   1885     private @Nullable Intent createRefreshSubscriptionIntent(int subId) {
   1886         // Bail if no owner
   1887         final String owner = getSubscriptionPlansOwner(subId);
   1888         if (owner == null) return null;
   1889 
   1890         // Bail if no plans
   1891         final List<SubscriptionPlan> plans = getSubscriptionPlans(subId);
   1892         if (plans.isEmpty()) return null;
   1893 
   1894         final Intent intent = new Intent(ACTION_REFRESH_SUBSCRIPTION_PLANS);
   1895         intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
   1896         intent.setPackage(owner);
   1897         intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
   1898 
   1899         // Bail if not implemented
   1900         if (mContext.getPackageManager().queryBroadcastReceivers(intent, 0).isEmpty()) {
   1901             return null;
   1902         }
   1903 
   1904         return intent;
   1905     }
   1906 
   1907     /**
   1908      * Check if there is a carrier app that is currently defining the billing
   1909      * relationship plan through {@link #setSubscriptionPlans(int, List)} that
   1910      * supports refreshing of subscription plans.
   1911      *
   1912      * @hide
   1913      */
   1914     public boolean isSubscriptionPlansRefreshSupported(int subId) {
   1915         return createRefreshSubscriptionIntent(subId) != null;
   1916     }
   1917 
   1918     /**
   1919      * Request that the carrier app that is currently defining the billing
   1920      * relationship plan through {@link #setSubscriptionPlans(int, List)}
   1921      * refresh its subscription plans.
   1922      * <p>
   1923      * If the app is able to successfully update the plans, you'll expect to
   1924      * receive the {@link #ACTION_SUBSCRIPTION_PLANS_CHANGED} broadcast.
   1925      *
   1926      * @hide
   1927      */
   1928     public void requestSubscriptionPlansRefresh(int subId) {
   1929         final Intent intent = createRefreshSubscriptionIntent(subId);
   1930         final BroadcastOptions options = BroadcastOptions.makeBasic();
   1931         options.setTemporaryAppWhitelistDuration(TimeUnit.MINUTES.toMillis(1));
   1932         mContext.sendBroadcast(intent, null, options.toBundle());
   1933     }
   1934 
   1935     /**
   1936      * Checks whether the app with the given context is authorized to manage the given subscription
   1937      * according to its metadata. Only supported for embedded subscriptions (if
   1938      * {@code SubscriptionInfo#isEmbedded} returns true).
   1939      *
   1940      * @param info The subscription to check.
   1941      * @return whether the app is authorized to manage this subscription per its metadata.
   1942      * @throws IllegalArgumentException if this subscription is not embedded.
   1943      */
   1944     public boolean canManageSubscription(SubscriptionInfo info) {
   1945         return canManageSubscription(info, mContext.getPackageName());
   1946     }
   1947 
   1948     /**
   1949      * Checks whether the given app is authorized to manage the given subscription. An app can only
   1950      * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
   1951      * {@link android.telephony.SubscriptionInfo} with the access status.
   1952      * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded}
   1953      * returns true).
   1954      *
   1955      * @param info The subscription to check.
   1956      * @param packageName Package name of the app to check.
   1957      * @return whether the app is authorized to manage this subscription per its access rules.
   1958      * @throws IllegalArgumentException if this subscription is not embedded.
   1959      * @hide
   1960      */
   1961     public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
   1962         if (!info.isEmbedded()) {
   1963             throw new IllegalArgumentException("Not an embedded subscription");
   1964         }
   1965         if (info.getAccessRules() == null) {
   1966             return false;
   1967         }
   1968         PackageManager packageManager = mContext.getPackageManager();
   1969         PackageInfo packageInfo;
   1970         try {
   1971             packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
   1972         } catch (PackageManager.NameNotFoundException e) {
   1973             throw new IllegalArgumentException("Unknown package: " + packageName, e);
   1974         }
   1975         for (UiccAccessRule rule : info.getAccessRules()) {
   1976             if (rule.getCarrierPrivilegeStatus(packageInfo)
   1977                     == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
   1978                 return true;
   1979             }
   1980         }
   1981         return false;
   1982     }
   1983 }
   1984