1 /*
2  * Copyright (C) 2006 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 com.android.phone;
18 
19 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
20 
21 import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
22 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
23 
24 import android.Manifest.permission;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.app.AppOpsManager;
28 import android.app.PendingIntent;
29 import android.content.ComponentName;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.SharedPreferences;
34 import android.content.pm.ApplicationInfo;
35 import android.content.pm.ComponentInfo;
36 import android.content.pm.PackageInfo;
37 import android.content.pm.PackageManager;
38 import android.net.Uri;
39 import android.os.AsyncResult;
40 import android.os.Binder;
41 import android.os.Build;
42 import android.os.Bundle;
43 import android.os.Handler;
44 import android.os.IBinder;
45 import android.os.Looper;
46 import android.os.Message;
47 import android.os.Messenger;
48 import android.os.ParcelFileDescriptor;
49 import android.os.ParcelUuid;
50 import android.os.PersistableBundle;
51 import android.os.Process;
52 import android.os.RemoteException;
53 import android.os.ResultReceiver;
54 import android.os.ServiceManager;
55 import android.os.ServiceSpecificException;
56 import android.os.ShellCallback;
57 import android.os.UserHandle;
58 import android.os.UserManager;
59 import android.os.WorkSource;
60 import android.preference.PreferenceManager;
61 import android.provider.DeviceConfig;
62 import android.provider.Settings;
63 import android.provider.Telephony;
64 import android.sysprop.TelephonyProperties;
65 import android.telecom.PhoneAccount;
66 import android.telecom.PhoneAccountHandle;
67 import android.telecom.TelecomManager;
68 import android.telephony.Annotation.ApnType;
69 import android.telephony.CallForwardingInfo;
70 import android.telephony.CarrierConfigManager;
71 import android.telephony.CarrierRestrictionRules;
72 import android.telephony.CellIdentity;
73 import android.telephony.CellIdentityCdma;
74 import android.telephony.CellIdentityGsm;
75 import android.telephony.CellInfo;
76 import android.telephony.CellInfoGsm;
77 import android.telephony.CellInfoWcdma;
78 import android.telephony.ClientRequestStats;
79 import android.telephony.ICellInfoCallback;
80 import android.telephony.IccOpenLogicalChannelResponse;
81 import android.telephony.LocationAccessPolicy;
82 import android.telephony.ModemActivityInfo;
83 import android.telephony.NeighboringCellInfo;
84 import android.telephony.NetworkScanRequest;
85 import android.telephony.PhoneCapability;
86 import android.telephony.PhoneNumberRange;
87 import android.telephony.RadioAccessFamily;
88 import android.telephony.RadioAccessSpecifier;
89 import android.telephony.ServiceState;
90 import android.telephony.SignalStrength;
91 import android.telephony.SubscriptionInfo;
92 import android.telephony.SubscriptionManager;
93 import android.telephony.TelephonyHistogram;
94 import android.telephony.TelephonyManager;
95 import android.telephony.TelephonyScanManager;
96 import android.telephony.UiccCardInfo;
97 import android.telephony.UiccSlotInfo;
98 import android.telephony.UssdResponse;
99 import android.telephony.VisualVoicemailSmsFilterSettings;
100 import android.telephony.data.ApnSetting;
101 import android.telephony.emergency.EmergencyNumber;
102 import android.telephony.ims.ImsException;
103 import android.telephony.ims.ProvisioningManager;
104 import android.telephony.ims.RegistrationManager;
105 import android.telephony.ims.aidl.IImsCapabilityCallback;
106 import android.telephony.ims.aidl.IImsConfig;
107 import android.telephony.ims.aidl.IImsConfigCallback;
108 import android.telephony.ims.aidl.IImsMmTelFeature;
109 import android.telephony.ims.aidl.IImsRcsFeature;
110 import android.telephony.ims.aidl.IImsRegistration;
111 import android.telephony.ims.aidl.IImsRegistrationCallback;
112 import android.telephony.ims.feature.ImsFeature;
113 import android.telephony.ims.feature.MmTelFeature;
114 import android.telephony.ims.feature.RcsFeature;
115 import android.telephony.ims.stub.ImsConfigImplBase;
116 import android.telephony.ims.stub.ImsRegistrationImplBase;
117 import android.text.TextUtils;
118 import android.util.ArraySet;
119 import android.util.Log;
120 import android.util.Pair;
121 
122 import com.android.ims.ImsManager;
123 import com.android.ims.internal.IImsServiceFeatureCallback;
124 import com.android.internal.annotations.VisibleForTesting;
125 import com.android.internal.telephony.CallForwardInfo;
126 import com.android.internal.telephony.CallManager;
127 import com.android.internal.telephony.CallStateException;
128 import com.android.internal.telephony.CarrierInfoManager;
129 import com.android.internal.telephony.CarrierResolver;
130 import com.android.internal.telephony.CellNetworkScanResult;
131 import com.android.internal.telephony.CommandException;
132 import com.android.internal.telephony.CommandsInterface;
133 import com.android.internal.telephony.DefaultPhoneNotifier;
134 import com.android.internal.telephony.HalVersion;
135 import com.android.internal.telephony.IBooleanConsumer;
136 import com.android.internal.telephony.IIntegerConsumer;
137 import com.android.internal.telephony.INumberVerificationCallback;
138 import com.android.internal.telephony.ITelephony;
139 import com.android.internal.telephony.IccCard;
140 import com.android.internal.telephony.LocaleTracker;
141 import com.android.internal.telephony.NetworkScanRequestTracker;
142 import com.android.internal.telephony.OperatorInfo;
143 import com.android.internal.telephony.Phone;
144 import com.android.internal.telephony.PhoneConfigurationManager;
145 import com.android.internal.telephony.PhoneConstantConversions;
146 import com.android.internal.telephony.PhoneConstants;
147 import com.android.internal.telephony.PhoneFactory;
148 import com.android.internal.telephony.ProxyController;
149 import com.android.internal.telephony.RIL;
150 import com.android.internal.telephony.RILConstants;
151 import com.android.internal.telephony.ServiceStateTracker;
152 import com.android.internal.telephony.SmsController;
153 import com.android.internal.telephony.SmsPermissions;
154 import com.android.internal.telephony.SubscriptionController;
155 import com.android.internal.telephony.TelephonyPermissions;
156 import com.android.internal.telephony.dataconnection.ApnSettingUtils;
157 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
158 import com.android.internal.telephony.euicc.EuiccConnector;
159 import com.android.internal.telephony.ims.ImsResolver;
160 import com.android.internal.telephony.imsphone.ImsPhone;
161 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
162 import com.android.internal.telephony.metrics.TelephonyMetrics;
163 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
164 import com.android.internal.telephony.uicc.IccIoResult;
165 import com.android.internal.telephony.uicc.IccRecords;
166 import com.android.internal.telephony.uicc.IccUtils;
167 import com.android.internal.telephony.uicc.SIMRecords;
168 import com.android.internal.telephony.uicc.UiccCard;
169 import com.android.internal.telephony.uicc.UiccCardApplication;
170 import com.android.internal.telephony.uicc.UiccController;
171 import com.android.internal.telephony.uicc.UiccProfile;
172 import com.android.internal.telephony.uicc.UiccSlot;
173 import com.android.internal.telephony.util.LocaleUtils;
174 import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
175 import com.android.internal.util.HexDump;
176 import com.android.phone.settings.PickSmsSubscriptionActivity;
177 import com.android.phone.vvm.PhoneAccountHandleConverter;
178 import com.android.phone.vvm.RemoteVvmTaskManager;
179 import com.android.phone.vvm.VisualVoicemailSettingsUtil;
180 import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
181 import com.android.telephony.Rlog;
182 
183 import java.io.FileDescriptor;
184 import java.io.PrintWriter;
185 import java.util.ArrayList;
186 import java.util.Arrays;
187 import java.util.HashMap;
188 import java.util.HashSet;
189 import java.util.List;
190 import java.util.Locale;
191 import java.util.Map;
192 import java.util.NoSuchElementException;
193 import java.util.Set;
194 import java.util.function.Consumer;
195 
196 /**
197  * Implementation of the ITelephony interface.
198  */
199 public class PhoneInterfaceManager extends ITelephony.Stub {
200     private static final String LOG_TAG = "PhoneInterfaceManager";
201     private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
202     private static final boolean DBG_LOC = false;
203     private static final boolean DBG_MERGE = false;
204 
205     // Message codes used with mMainThreadHandler
206     private static final int CMD_HANDLE_PIN_MMI = 1;
207     private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
208     private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
209     private static final int CMD_OPEN_CHANNEL = 9;
210     private static final int EVENT_OPEN_CHANNEL_DONE = 10;
211     private static final int CMD_CLOSE_CHANNEL = 11;
212     private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
213     private static final int CMD_NV_READ_ITEM = 13;
214     private static final int EVENT_NV_READ_ITEM_DONE = 14;
215     private static final int CMD_NV_WRITE_ITEM = 15;
216     private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
217     private static final int CMD_NV_WRITE_CDMA_PRL = 17;
218     private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
219     private static final int CMD_RESET_MODEM_CONFIG = 19;
220     private static final int EVENT_RESET_MODEM_CONFIG_DONE = 20;
221     private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
222     private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
223     private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
224     private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
225     private static final int CMD_SEND_ENVELOPE = 25;
226     private static final int EVENT_SEND_ENVELOPE_DONE = 26;
227     private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
228     private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
229     private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
230     private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
231     private static final int CMD_EXCHANGE_SIM_IO = 31;
232     private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
233     private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
234     private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
235     private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
236     private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
237     private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
238     private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
239     private static final int CMD_PERFORM_NETWORK_SCAN = 39;
240     private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
241     private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
242     private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
243     private static final int CMD_SET_ALLOWED_CARRIERS = 43;
244     private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
245     private static final int CMD_GET_ALLOWED_CARRIERS = 45;
246     private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
247     private static final int CMD_HANDLE_USSD_REQUEST = 47;
248     private static final int CMD_GET_FORBIDDEN_PLMNS = 48;
249     private static final int EVENT_GET_FORBIDDEN_PLMNS_DONE = 49;
250     private static final int CMD_SWITCH_SLOTS = 50;
251     private static final int EVENT_SWITCH_SLOTS_DONE = 51;
252     private static final int CMD_GET_NETWORK_SELECTION_MODE = 52;
253     private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 53;
254     private static final int CMD_GET_CDMA_ROAMING_MODE = 54;
255     private static final int EVENT_GET_CDMA_ROAMING_MODE_DONE = 55;
256     private static final int CMD_SET_CDMA_ROAMING_MODE = 56;
257     private static final int EVENT_SET_CDMA_ROAMING_MODE_DONE = 57;
258     private static final int CMD_SET_CDMA_SUBSCRIPTION_MODE = 58;
259     private static final int EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE = 59;
260     private static final int CMD_GET_ALL_CELL_INFO = 60;
261     private static final int EVENT_GET_ALL_CELL_INFO_DONE = 61;
262     private static final int CMD_GET_CELL_LOCATION = 62;
263     private static final int EVENT_GET_CELL_LOCATION_DONE = 63;
264     private static final int CMD_MODEM_REBOOT = 64;
265     private static final int EVENT_CMD_MODEM_REBOOT_DONE = 65;
266     private static final int CMD_REQUEST_CELL_INFO_UPDATE = 66;
267     private static final int EVENT_REQUEST_CELL_INFO_UPDATE_DONE = 67;
268     private static final int CMD_REQUEST_ENABLE_MODEM = 68;
269     private static final int EVENT_ENABLE_MODEM_DONE = 69;
270     private static final int CMD_GET_MODEM_STATUS = 70;
271     private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
272     private static final int CMD_SET_FORBIDDEN_PLMNS = 72;
273     private static final int EVENT_SET_FORBIDDEN_PLMNS_DONE = 73;
274     private static final int CMD_ERASE_MODEM_CONFIG = 74;
275     private static final int EVENT_ERASE_MODEM_CONFIG_DONE = 75;
276     private static final int CMD_CHANGE_ICC_LOCK_PASSWORD = 76;
277     private static final int EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE = 77;
278     private static final int CMD_SET_ICC_LOCK_ENABLED = 78;
279     private static final int EVENT_SET_ICC_LOCK_ENABLED_DONE = 79;
280     private static final int CMD_SET_SYSTEM_SELECTION_CHANNELS = 80;
281     private static final int EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE = 81;
282     private static final int CMD_GET_CALL_FORWARDING = 83;
283     private static final int EVENT_GET_CALL_FORWARDING_DONE = 84;
284     private static final int CMD_SET_CALL_FORWARDING = 85;
285     private static final int EVENT_SET_CALL_FORWARDING_DONE = 86;
286     private static final int CMD_GET_CALL_WAITING = 87;
287     private static final int EVENT_GET_CALL_WAITING_DONE = 88;
288     private static final int CMD_SET_CALL_WAITING = 89;
289     private static final int EVENT_SET_CALL_WAITING_DONE = 90;
290 
291     // Parameters of select command.
292     private static final int SELECT_COMMAND = 0xA4;
293     private static final int SELECT_P1 = 0x04;
294     private static final int SELECT_P2 = 0;
295     private static final int SELECT_P3 = 0x10;
296 
297     /** The singleton instance. */
298     private static PhoneInterfaceManager sInstance;
299 
300     private PhoneGlobals mApp;
301     private CallManager mCM;
302     private ImsResolver mImsResolver;
303     private UserManager mUserManager;
304     private AppOpsManager mAppOps;
305     private MainThreadHandler mMainThreadHandler;
306     private SubscriptionController mSubscriptionController;
307     private SharedPreferences mTelephonySharedPreferences;
308     private PhoneConfigurationManager mPhoneConfigurationManager;
309 
310     private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
311     private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
312     private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
313     private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
314 
315     // String to store multi SIM allowed
316     private static final String PREF_MULTI_SIM_RESTRICTED = "multisim_restricted";
317 
318     // The AID of ISD-R.
319     private static final String ISDR_AID = "A0000005591010FFFFFFFF8900000100";
320 
321     private NetworkScanRequestTracker mNetworkScanRequestTracker;
322 
323     private static final int TYPE_ALLOCATION_CODE_LENGTH = 8;
324     private static final int MANUFACTURER_CODE_LENGTH = 8;
325 
326     /**
327      * Experiment flag to enable erase modem config on reset network, default value is false
328      */
329     public static final String RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED =
330             "reset_network_erase_modem_config_enabled";
331 
332     /**
333      * A request object to use for transmitting data to an ICC.
334      */
335     private static final class IccAPDUArgument {
336         public int channel, cla, command, p1, p2, p3;
337         public String data;
338 
IccAPDUArgument(int channel, int cla, int command, int p1, int p2, int p3, String data)339         public IccAPDUArgument(int channel, int cla, int command,
340                 int p1, int p2, int p3, String data) {
341             this.channel = channel;
342             this.cla = cla;
343             this.command = command;
344             this.p1 = p1;
345             this.p2 = p2;
346             this.p3 = p3;
347             this.data = data;
348         }
349     }
350 
351     /**
352      * A request object to use for transmitting data to an ICC.
353      */
354     private static final class ManualNetworkSelectionArgument {
355         public OperatorInfo operatorInfo;
356         public boolean persistSelection;
357 
ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection)358         public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
359             this.operatorInfo = operatorInfo;
360             this.persistSelection = persistSelection;
361         }
362     }
363 
364     /**
365      * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
366      * request after sending. The main thread will notify the request when it is complete.
367      */
368     private static final class MainThreadRequest {
369         /** The argument to use for the request */
370         public Object argument;
371         /** The result of the request that is run on the main thread */
372         public Object result;
373         // The subscriber id that this request applies to. Defaults to
374         // SubscriptionManager.INVALID_SUBSCRIPTION_ID
375         public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
376 
377         // In cases where subId is unavailable, the caller needs to specify the phone.
378         public Phone phone;
379 
380         public WorkSource workSource;
381 
MainThreadRequest(Object argument)382         public MainThreadRequest(Object argument) {
383             this.argument = argument;
384         }
385 
MainThreadRequest(Object argument, Phone phone, WorkSource workSource)386         MainThreadRequest(Object argument, Phone phone, WorkSource workSource) {
387             this.argument = argument;
388             if (phone != null) {
389                 this.phone = phone;
390             }
391             this.workSource = workSource;
392         }
393 
MainThreadRequest(Object argument, Integer subId, WorkSource workSource)394         MainThreadRequest(Object argument, Integer subId, WorkSource workSource) {
395             this.argument = argument;
396             if (subId != null) {
397                 this.subId = subId;
398             }
399             this.workSource = workSource;
400         }
401     }
402 
403     private static final class IncomingThirdPartyCallArgs {
404         public final ComponentName component;
405         public final String callId;
406         public final String callerDisplayName;
407 
IncomingThirdPartyCallArgs(ComponentName component, String callId, String callerDisplayName)408         public IncomingThirdPartyCallArgs(ComponentName component, String callId,
409                 String callerDisplayName) {
410             this.component = component;
411             this.callId = callId;
412             this.callerDisplayName = callerDisplayName;
413         }
414     }
415 
416     /**
417      * A handler that processes messages on the main thread in the phone process. Since many
418      * of the Phone calls are not thread safe this is needed to shuttle the requests from the
419      * inbound binder threads to the main thread in the phone process.  The Binder thread
420      * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
421      * on, which will be notified when the operation completes and will contain the result of the
422      * request.
423      *
424      * <p>If a MainThreadRequest object is provided in the msg.obj field,
425      * note that request.result must be set to something non-null for the calling thread to
426      * unblock.
427      */
428     private final class MainThreadHandler extends Handler {
429         @Override
handleMessage(Message msg)430         public void handleMessage(Message msg) {
431             MainThreadRequest request;
432             Message onCompleted;
433             AsyncResult ar;
434             UiccCard uiccCard;
435             IccAPDUArgument iccArgument;
436             final Phone defaultPhone = getDefaultPhone();
437 
438             switch (msg.what) {
439                 case CMD_HANDLE_USSD_REQUEST: {
440                     request = (MainThreadRequest) msg.obj;
441                     final Phone phone = getPhoneFromRequest(request);
442                     Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
443                     String ussdRequest =  ussdObject.first;
444                     ResultReceiver wrappedCallback = ussdObject.second;
445 
446                     if (!isUssdApiAllowed(request.subId)) {
447                         // Carrier does not support use of this API, return failure.
448                         Rlog.w(LOG_TAG, "handleUssdRequest: carrier does not support USSD apis.");
449                         UssdResponse response = new UssdResponse(ussdRequest, null);
450                         Bundle returnData = new Bundle();
451                         returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
452                         wrappedCallback.send(TelephonyManager.USSD_RETURN_FAILURE, returnData);
453 
454                         request.result = true;
455                         notifyRequester(request);
456                         return;
457                     }
458 
459                     try {
460                         request.result = phone != null
461                                 ? phone.handleUssdRequest(ussdRequest, wrappedCallback) : false;
462                     } catch (CallStateException cse) {
463                         request.result = false;
464                     }
465                     // Wake up the requesting thread
466                     notifyRequester(request);
467                     break;
468                 }
469 
470                 case CMD_HANDLE_PIN_MMI: {
471                     request = (MainThreadRequest) msg.obj;
472                     final Phone phone = getPhoneFromRequest(request);
473                     request.result = phone != null ?
474                             getPhoneFromRequest(request).handlePinMmi((String) request.argument)
475                             : false;
476                     // Wake up the requesting thread
477                     notifyRequester(request);
478                     break;
479                 }
480 
481                 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
482                     request = (MainThreadRequest) msg.obj;
483                     iccArgument = (IccAPDUArgument) request.argument;
484                     uiccCard = getUiccCardFromRequest(request);
485                     if (uiccCard == null) {
486                         loge("iccTransmitApduLogicalChannel: No UICC");
487                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
488                         notifyRequester(request);
489                     } else {
490                         onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
491                             request);
492                         uiccCard.iccTransmitApduLogicalChannel(
493                             iccArgument.channel, iccArgument.cla, iccArgument.command,
494                             iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
495                             onCompleted);
496                     }
497                     break;
498 
499                 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
500                     ar = (AsyncResult) msg.obj;
501                     request = (MainThreadRequest) ar.userObj;
502                     if (ar.exception == null && ar.result != null) {
503                         request.result = ar.result;
504                     } else {
505                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
506                         if (ar.result == null) {
507                             loge("iccTransmitApduLogicalChannel: Empty response");
508                         } else if (ar.exception instanceof CommandException) {
509                             loge("iccTransmitApduLogicalChannel: CommandException: " +
510                                     ar.exception);
511                         } else {
512                             loge("iccTransmitApduLogicalChannel: Unknown exception");
513                         }
514                     }
515                     notifyRequester(request);
516                     break;
517 
518                 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
519                     request = (MainThreadRequest) msg.obj;
520                     iccArgument = (IccAPDUArgument) request.argument;
521                     uiccCard = getUiccCardFromRequest(request);
522                     if (uiccCard == null) {
523                         loge("iccTransmitApduBasicChannel: No UICC");
524                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
525                         notifyRequester(request);
526                     } else {
527                         onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
528                             request);
529                         uiccCard.iccTransmitApduBasicChannel(
530                             iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
531                             iccArgument.p3, iccArgument.data, onCompleted);
532                     }
533                     break;
534 
535                 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
536                     ar = (AsyncResult) msg.obj;
537                     request = (MainThreadRequest) ar.userObj;
538                     if (ar.exception == null && ar.result != null) {
539                         request.result = ar.result;
540                     } else {
541                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
542                         if (ar.result == null) {
543                             loge("iccTransmitApduBasicChannel: Empty response");
544                         } else if (ar.exception instanceof CommandException) {
545                             loge("iccTransmitApduBasicChannel: CommandException: " +
546                                     ar.exception);
547                         } else {
548                             loge("iccTransmitApduBasicChannel: Unknown exception");
549                         }
550                     }
551                     notifyRequester(request);
552                     break;
553 
554                 case CMD_EXCHANGE_SIM_IO:
555                     request = (MainThreadRequest) msg.obj;
556                     iccArgument = (IccAPDUArgument) request.argument;
557                     uiccCard = getUiccCardFromRequest(request);
558                     if (uiccCard == null) {
559                         loge("iccExchangeSimIO: No UICC");
560                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
561                         notifyRequester(request);
562                     } else {
563                         onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
564                                 request);
565                         uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
566                                 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
567                                 iccArgument.data, onCompleted);
568                     }
569                     break;
570 
571                 case EVENT_EXCHANGE_SIM_IO_DONE:
572                     ar = (AsyncResult) msg.obj;
573                     request = (MainThreadRequest) ar.userObj;
574                     if (ar.exception == null && ar.result != null) {
575                         request.result = ar.result;
576                     } else {
577                         request.result = new IccIoResult(0x6f, 0, (byte[])null);
578                     }
579                     notifyRequester(request);
580                     break;
581 
582                 case CMD_SEND_ENVELOPE:
583                     request = (MainThreadRequest) msg.obj;
584                     uiccCard = getUiccCardFromRequest(request);
585                     if (uiccCard == null) {
586                         loge("sendEnvelopeWithStatus: No UICC");
587                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
588                         notifyRequester(request);
589                     } else {
590                         onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
591                         uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
592                     }
593                     break;
594 
595                 case EVENT_SEND_ENVELOPE_DONE:
596                     ar = (AsyncResult) msg.obj;
597                     request = (MainThreadRequest) ar.userObj;
598                     if (ar.exception == null && ar.result != null) {
599                         request.result = ar.result;
600                     } else {
601                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
602                         if (ar.result == null) {
603                             loge("sendEnvelopeWithStatus: Empty response");
604                         } else if (ar.exception instanceof CommandException) {
605                             loge("sendEnvelopeWithStatus: CommandException: " +
606                                     ar.exception);
607                         } else {
608                             loge("sendEnvelopeWithStatus: exception:" + ar.exception);
609                         }
610                     }
611                     notifyRequester(request);
612                     break;
613 
614                 case CMD_OPEN_CHANNEL:
615                     request = (MainThreadRequest) msg.obj;
616                     uiccCard = getUiccCardFromRequest(request);
617                     Pair<String, Integer> openChannelArgs = (Pair<String, Integer>) request.argument;
618                     if (uiccCard == null) {
619                         loge("iccOpenLogicalChannel: No UICC");
620                         request.result = new IccOpenLogicalChannelResponse(-1,
621                             IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
622                         notifyRequester(request);
623                     } else {
624                         onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
625                         uiccCard.iccOpenLogicalChannel(openChannelArgs.first,
626                                 openChannelArgs.second, onCompleted);
627                     }
628                     break;
629 
630                 case EVENT_OPEN_CHANNEL_DONE:
631                     ar = (AsyncResult) msg.obj;
632                     request = (MainThreadRequest) ar.userObj;
633                     IccOpenLogicalChannelResponse openChannelResp;
634                     if (ar.exception == null && ar.result != null) {
635                         int[] result = (int[]) ar.result;
636                         int channelId = result[0];
637                         byte[] selectResponse = null;
638                         if (result.length > 1) {
639                             selectResponse = new byte[result.length - 1];
640                             for (int i = 1; i < result.length; ++i) {
641                                 selectResponse[i - 1] = (byte) result[i];
642                             }
643                         }
644                         openChannelResp = new IccOpenLogicalChannelResponse(channelId,
645                             IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
646                     } else {
647                         if (ar.result == null) {
648                             loge("iccOpenLogicalChannel: Empty response");
649                         }
650                         if (ar.exception != null) {
651                             loge("iccOpenLogicalChannel: Exception: " + ar.exception);
652                         }
653 
654                         int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
655                         if (ar.exception instanceof CommandException) {
656                             CommandException.Error error =
657                                 ((CommandException) (ar.exception)).getCommandError();
658                             if (error == CommandException.Error.MISSING_RESOURCE) {
659                                 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
660                             } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
661                                 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
662                             }
663                         }
664                         openChannelResp = new IccOpenLogicalChannelResponse(
665                             IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
666                     }
667                     request.result = openChannelResp;
668                     notifyRequester(request);
669                     break;
670 
671                 case CMD_CLOSE_CHANNEL:
672                     request = (MainThreadRequest) msg.obj;
673                     uiccCard = getUiccCardFromRequest(request);
674                     if (uiccCard == null) {
675                         loge("iccCloseLogicalChannel: No UICC");
676                         request.result = false;
677                         notifyRequester(request);
678                     } else {
679                         onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
680                         uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
681                     }
682                     break;
683 
684                 case EVENT_CLOSE_CHANNEL_DONE:
685                     handleNullReturnEvent(msg, "iccCloseLogicalChannel");
686                     break;
687 
688                 case CMD_NV_READ_ITEM:
689                     request = (MainThreadRequest) msg.obj;
690                     onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
691                     defaultPhone.nvReadItem((Integer) request.argument, onCompleted,
692                             request.workSource);
693                     break;
694 
695                 case EVENT_NV_READ_ITEM_DONE:
696                     ar = (AsyncResult) msg.obj;
697                     request = (MainThreadRequest) ar.userObj;
698                     if (ar.exception == null && ar.result != null) {
699                         request.result = ar.result;     // String
700                     } else {
701                         request.result = "";
702                         if (ar.result == null) {
703                             loge("nvReadItem: Empty response");
704                         } else if (ar.exception instanceof CommandException) {
705                             loge("nvReadItem: CommandException: " +
706                                     ar.exception);
707                         } else {
708                             loge("nvReadItem: Unknown exception");
709                         }
710                     }
711                     notifyRequester(request);
712                     break;
713 
714                 case CMD_NV_WRITE_ITEM:
715                     request = (MainThreadRequest) msg.obj;
716                     onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
717                     Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
718                     defaultPhone.nvWriteItem(idValue.first, idValue.second, onCompleted,
719                             request.workSource);
720                     break;
721 
722                 case EVENT_NV_WRITE_ITEM_DONE:
723                     handleNullReturnEvent(msg, "nvWriteItem");
724                     break;
725 
726                 case CMD_NV_WRITE_CDMA_PRL:
727                     request = (MainThreadRequest) msg.obj;
728                     onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
729                     defaultPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
730                     break;
731 
732                 case EVENT_NV_WRITE_CDMA_PRL_DONE:
733                     handleNullReturnEvent(msg, "nvWriteCdmaPrl");
734                     break;
735 
736                 case CMD_RESET_MODEM_CONFIG:
737                     request = (MainThreadRequest) msg.obj;
738                     onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
739                     defaultPhone.resetModemConfig(onCompleted);
740                     break;
741 
742                 case EVENT_RESET_MODEM_CONFIG_DONE:
743                     handleNullReturnEvent(msg, "resetModemConfig");
744                     break;
745 
746                 case CMD_GET_PREFERRED_NETWORK_TYPE:
747                     request = (MainThreadRequest) msg.obj;
748                     onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
749                     getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
750                     break;
751 
752                 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
753                     ar = (AsyncResult) msg.obj;
754                     request = (MainThreadRequest) ar.userObj;
755                     if (ar.exception == null && ar.result != null) {
756                         request.result = ar.result;     // Integer
757                     } else {
758                         request.result = null;
759                         if (ar.result == null) {
760                             loge("getPreferredNetworkType: Empty response");
761                         } else if (ar.exception instanceof CommandException) {
762                             loge("getPreferredNetworkType: CommandException: " +
763                                     ar.exception);
764                         } else {
765                             loge("getPreferredNetworkType: Unknown exception");
766                         }
767                     }
768                     notifyRequester(request);
769                     break;
770 
771                 case CMD_SET_PREFERRED_NETWORK_TYPE:
772                     request = (MainThreadRequest) msg.obj;
773                     onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
774                     int networkType = (Integer) request.argument;
775                     getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
776                     break;
777 
778                 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
779                     handleNullReturnEvent(msg, "setPreferredNetworkType");
780                     break;
781 
782                 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
783                     request = (MainThreadRequest)msg.obj;
784                     onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
785                     defaultPhone.invokeOemRilRequestRaw((byte[]) request.argument, onCompleted);
786                     break;
787 
788                 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
789                     ar = (AsyncResult)msg.obj;
790                     request = (MainThreadRequest)ar.userObj;
791                     request.result = ar;
792                     notifyRequester(request);
793                     break;
794 
795                 case CMD_SET_VOICEMAIL_NUMBER:
796                     request = (MainThreadRequest) msg.obj;
797                     onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
798                     Pair<String, String> tagNum = (Pair<String, String>) request.argument;
799                     getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
800                             onCompleted);
801                     break;
802 
803                 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
804                     handleNullReturnEvent(msg, "setVoicemailNumber");
805                     break;
806 
807                 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
808                     request = (MainThreadRequest) msg.obj;
809                     onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
810                             request);
811                     getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
812                     break;
813 
814                 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
815                     handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
816                     break;
817 
818                 case CMD_PERFORM_NETWORK_SCAN:
819                     request = (MainThreadRequest) msg.obj;
820                     onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
821                     getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
822                     break;
823 
824                 case CMD_GET_CALL_FORWARDING:
825                     request = (MainThreadRequest) msg.obj;
826                     onCompleted = obtainMessage(EVENT_GET_CALL_FORWARDING_DONE, request);
827                     int callForwardingReason = (Integer) request.argument;
828                     getPhoneFromRequest(request).getCallForwardingOption(
829                             callForwardingReason, onCompleted);
830                     break;
831 
832                 case EVENT_GET_CALL_FORWARDING_DONE:
833                     ar = (AsyncResult) msg.obj;
834                     request = (MainThreadRequest) ar.userObj;
835                     CallForwardingInfo callForwardingInfo = null;
836                     if (ar.exception == null && ar.result != null) {
837                         CallForwardInfo[] callForwardInfos = (CallForwardInfo[]) ar.result;
838                         for (CallForwardInfo callForwardInfo : callForwardInfos) {
839                             // Service Class is a bit mask per 3gpp 27.007. Search for
840                             // any service for voice call.
841                             if ((callForwardInfo.serviceClass
842                                     & CommandsInterface.SERVICE_CLASS_VOICE) > 0) {
843                                 callForwardingInfo = new CallForwardingInfo(
844                                         callForwardInfo.serviceClass, callForwardInfo.reason,
845                                                 callForwardInfo.number,
846                                                         callForwardInfo.timeSeconds);
847                                 break;
848                             }
849                         }
850                         // Didn't find a call forward info for voice call.
851                         if (callForwardingInfo == null) {
852                             callForwardingInfo = new CallForwardingInfo(
853                                     CallForwardingInfo.STATUS_UNKNOWN_ERROR,
854                                             0 /* reason */, null /* number */, 0 /* timeout */);
855                         }
856                     } else {
857                         if (ar.result == null) {
858                             loge("EVENT_GET_CALL_FORWARDING_DONE: Empty response");
859                         }
860                         if (ar.exception != null) {
861                             loge("EVENT_GET_CALL_FORWARDING_DONE: Exception: " + ar.exception);
862                         }
863                         int errorCode = CallForwardingInfo.STATUS_UNKNOWN_ERROR;
864                         if (ar.exception instanceof CommandException) {
865                             CommandException.Error error =
866                                     ((CommandException) (ar.exception)).getCommandError();
867                             if (error == CommandException.Error.FDN_CHECK_FAILURE) {
868                                 errorCode = CallForwardingInfo.STATUS_FDN_CHECK_FAILURE;
869                             } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
870                                 errorCode = CallForwardingInfo.STATUS_NOT_SUPPORTED;
871                             }
872                         }
873                         callForwardingInfo = new CallForwardingInfo(
874                                 errorCode, 0 /* reason */, null /* number */, 0 /* timeout */);
875                     }
876                     request.result = callForwardingInfo;
877                     notifyRequester(request);
878                     break;
879 
880                 case CMD_SET_CALL_FORWARDING:
881                     request = (MainThreadRequest) msg.obj;
882                     onCompleted = obtainMessage(EVENT_SET_CALL_FORWARDING_DONE, request);
883                     CallForwardingInfo callForwardingInfoToSet =
884                             (CallForwardingInfo) request.argument;
885                     getPhoneFromRequest(request).setCallForwardingOption(
886                             callForwardingInfoToSet.getStatus(),
887                             callForwardingInfoToSet.getReason(),
888                             callForwardingInfoToSet.getNumber(),
889                             callForwardingInfoToSet.getTimeoutSeconds(), onCompleted);
890                     break;
891 
892                 case EVENT_SET_CALL_FORWARDING_DONE:
893                     ar = (AsyncResult) msg.obj;
894                     request = (MainThreadRequest) ar.userObj;
895                     if (ar.exception == null) {
896                         request.result = true;
897                     } else {
898                         request.result = false;
899                         loge("setCallForwarding exception: " + ar.exception);
900                     }
901                     notifyRequester(request);
902                     break;
903 
904                 case CMD_GET_CALL_WAITING:
905                     request = (MainThreadRequest) msg.obj;
906                     onCompleted = obtainMessage(EVENT_GET_CALL_WAITING_DONE, request);
907                     getPhoneFromRequest(request).getCallWaiting(onCompleted);
908                     break;
909 
910                 case EVENT_GET_CALL_WAITING_DONE:
911                     ar = (AsyncResult) msg.obj;
912                     request = (MainThreadRequest) ar.userObj;
913                     int callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
914                     if (ar.exception == null && ar.result != null) {
915                         int[] callForwardResults = (int[]) ar.result;
916                         // Service Class is a bit mask per 3gpp 27.007.
917                         // Search for any service for voice call.
918                         if (callForwardResults.length > 1
919                                 && ((callForwardResults[1]
920                                         & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
921                             callForwardingStatus = callForwardResults[0] == 0
922                                     ? TelephonyManager.CALL_WAITING_STATUS_INACTIVE
923                                             : TelephonyManager.CALL_WAITING_STATUS_ACTIVE;
924                         } else {
925                             callForwardingStatus = TelephonyManager.CALL_WAITING_STATUS_INACTIVE;
926                         }
927                     } else {
928                         if (ar.result == null) {
929                             loge("EVENT_GET_CALL_WAITING_DONE: Empty response");
930                         }
931                         if (ar.exception != null) {
932                             loge("EVENT_GET_CALL_WAITING_DONE: Exception: " + ar.exception);
933                         }
934                         if (ar.exception instanceof CommandException) {
935                             CommandException.Error error =
936                                     ((CommandException) (ar.exception)).getCommandError();
937                             if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
938                                 callForwardingStatus =
939                                         TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED;
940                             }
941                         }
942                     }
943                     request.result = callForwardingStatus;
944                     notifyRequester(request);
945                     break;
946 
947                 case CMD_SET_CALL_WAITING:
948                     request = (MainThreadRequest) msg.obj;
949                     onCompleted = obtainMessage(EVENT_SET_CALL_WAITING_DONE, request);
950                     boolean isEnable = (Boolean) request.argument;
951                     getPhoneFromRequest(request).setCallWaiting(isEnable, onCompleted);
952                     break;
953 
954                 case EVENT_SET_CALL_WAITING_DONE:
955                     ar = (AsyncResult) msg.obj;
956                     request = (MainThreadRequest) ar.userObj;
957                     if (ar.exception == null) {
958                         request.result = true;
959                     } else {
960                         request.result = false;
961                         loge("setCallWaiting exception: " + ar.exception);
962                     }
963                     notifyRequester(request);
964                     break;
965 
966                 case EVENT_PERFORM_NETWORK_SCAN_DONE:
967                     ar = (AsyncResult) msg.obj;
968                     request = (MainThreadRequest) ar.userObj;
969                     CellNetworkScanResult cellScanResult;
970                     if (ar.exception == null && ar.result != null) {
971                         cellScanResult = new CellNetworkScanResult(
972                                 CellNetworkScanResult.STATUS_SUCCESS,
973                                 (List<OperatorInfo>) ar.result);
974                     } else {
975                         if (ar.result == null) {
976                             loge("getCellNetworkScanResults: Empty response");
977                         }
978                         if (ar.exception != null) {
979                             loge("getCellNetworkScanResults: Exception: " + ar.exception);
980                         }
981                         int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
982                         if (ar.exception instanceof CommandException) {
983                             CommandException.Error error =
984                                 ((CommandException) (ar.exception)).getCommandError();
985                             if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
986                                 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
987                             } else if (error == CommandException.Error.GENERIC_FAILURE) {
988                                 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
989                             }
990                         }
991                         cellScanResult = new CellNetworkScanResult(errorCode, null);
992                     }
993                     request.result = cellScanResult;
994                     notifyRequester(request);
995                     break;
996 
997                 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
998                     request = (MainThreadRequest) msg.obj;
999                     ManualNetworkSelectionArgument selArg =
1000                             (ManualNetworkSelectionArgument) request.argument;
1001                     onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
1002                             request);
1003                     getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
1004                             selArg.persistSelection, onCompleted);
1005                     break;
1006 
1007                 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
1008                     ar = (AsyncResult) msg.obj;
1009                     request = (MainThreadRequest) ar.userObj;
1010                     if (ar.exception == null) {
1011                         request.result = true;
1012                     } else {
1013                         request.result = false;
1014                         loge("setNetworkSelectionModeManual " + ar.exception);
1015                     }
1016                     notifyRequester(request);
1017                     mApp.onNetworkSelectionChanged(request.subId);
1018                     break;
1019 
1020                 case CMD_GET_MODEM_ACTIVITY_INFO:
1021                     request = (MainThreadRequest) msg.obj;
1022                     onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
1023                     if (defaultPhone != null) {
1024                         defaultPhone.getModemActivityInfo(onCompleted, request.workSource);
1025                     } else {
1026                         ResultReceiver result = (ResultReceiver) request.argument;
1027                         Bundle bundle = new Bundle();
1028                         bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY,
1029                                 new ModemActivityInfo(0, 0, 0, new int[0], 0));
1030                         result.send(0, bundle);
1031                     }
1032                     break;
1033 
1034                 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
1035                     ar = (AsyncResult) msg.obj;
1036                     request = (MainThreadRequest) ar.userObj;
1037                     ResultReceiver result = (ResultReceiver) request.argument;
1038 
1039                     ModemActivityInfo ret = new ModemActivityInfo(0, 0, 0, new int[0], 0);
1040                     if (ar.exception == null && ar.result != null) {
1041                         // Update the last modem activity info and the result of the request.
1042                         ModemActivityInfo info = (ModemActivityInfo) ar.result;
1043                         if (isModemActivityInfoValid(info)) {
1044                             int[] mergedTxTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
1045                             int[] txTimeMs = info.getTransmitTimeMillis();
1046                             int[] lastModemTxTimeMs = mLastModemActivityInfo
1047                                     .getTransmitTimeMillis();
1048                             for (int i = 0; i < mergedTxTimeMs.length; i++) {
1049                                 mergedTxTimeMs[i] = txTimeMs[i] + lastModemTxTimeMs[i];
1050                             }
1051                             mLastModemActivityInfo.setTimestamp(info.getTimestamp());
1052                             mLastModemActivityInfo.setSleepTimeMillis(info.getSleepTimeMillis()
1053                                     + mLastModemActivityInfo.getSleepTimeMillis());
1054                             mLastModemActivityInfo.setIdleTimeMillis(info.getIdleTimeMillis()
1055                                     + mLastModemActivityInfo.getIdleTimeMillis());
1056                             mLastModemActivityInfo.setTransmitTimeMillis(mergedTxTimeMs);
1057                             mLastModemActivityInfo.setReceiveTimeMillis(
1058                                     info.getReceiveTimeMillis()
1059                                             + mLastModemActivityInfo.getReceiveTimeMillis());
1060                         }
1061                         ret = new ModemActivityInfo(mLastModemActivityInfo.getTimestamp(),
1062                                 mLastModemActivityInfo.getSleepTimeMillis(),
1063                                 mLastModemActivityInfo.getIdleTimeMillis(),
1064                                 mLastModemActivityInfo.getTransmitTimeMillis(),
1065                                 mLastModemActivityInfo.getReceiveTimeMillis());
1066                     } else {
1067                         if (ar.result == null) {
1068                             loge("queryModemActivityInfo: Empty response");
1069                         } else if (ar.exception instanceof CommandException) {
1070                             loge("queryModemActivityInfo: CommandException: " +
1071                                     ar.exception);
1072                         } else {
1073                             loge("queryModemActivityInfo: Unknown exception");
1074                         }
1075                     }
1076                     Bundle bundle = new Bundle();
1077                     bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, ret);
1078                     result.send(0, bundle);
1079                     notifyRequester(request);
1080                     break;
1081 
1082                 case CMD_SET_ALLOWED_CARRIERS:
1083                     request = (MainThreadRequest) msg.obj;
1084                     CarrierRestrictionRules argument =
1085                             (CarrierRestrictionRules) request.argument;
1086                     onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
1087                     defaultPhone.setAllowedCarriers(argument, onCompleted, request.workSource);
1088                     break;
1089 
1090                 case EVENT_SET_ALLOWED_CARRIERS_DONE:
1091                     ar = (AsyncResult) msg.obj;
1092                     request = (MainThreadRequest) ar.userObj;
1093                     if (ar.exception == null && ar.result != null) {
1094                         request.result = ar.result;
1095                     } else {
1096                         request.result = TelephonyManager.SET_CARRIER_RESTRICTION_ERROR;
1097                         if (ar.exception instanceof CommandException) {
1098                             loge("setAllowedCarriers: CommandException: " + ar.exception);
1099                             CommandException.Error error =
1100                                     ((CommandException) (ar.exception)).getCommandError();
1101                             if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1102                                 request.result =
1103                                         TelephonyManager.SET_CARRIER_RESTRICTION_NOT_SUPPORTED;
1104                             }
1105                         } else {
1106                             loge("setAllowedCarriers: Unknown exception");
1107                         }
1108                     }
1109                     notifyRequester(request);
1110                     break;
1111 
1112                 case CMD_GET_ALLOWED_CARRIERS:
1113                     request = (MainThreadRequest) msg.obj;
1114                     onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
1115                     defaultPhone.getAllowedCarriers(onCompleted, request.workSource);
1116                     break;
1117 
1118                 case EVENT_GET_ALLOWED_CARRIERS_DONE:
1119                     ar = (AsyncResult) msg.obj;
1120                     request = (MainThreadRequest) ar.userObj;
1121                     if (ar.exception == null && ar.result != null) {
1122                         request.result = ar.result;
1123                     } else {
1124                         request.result = new IllegalStateException(
1125                             "Failed to get carrier restrictions");
1126                         if (ar.result == null) {
1127                             loge("getAllowedCarriers: Empty response");
1128                         } else if (ar.exception instanceof CommandException) {
1129                             loge("getAllowedCarriers: CommandException: " +
1130                                     ar.exception);
1131                         } else {
1132                             loge("getAllowedCarriers: Unknown exception");
1133                         }
1134                     }
1135                     notifyRequester(request);
1136                     break;
1137 
1138                 case EVENT_GET_FORBIDDEN_PLMNS_DONE:
1139                     ar = (AsyncResult) msg.obj;
1140                     request = (MainThreadRequest) ar.userObj;
1141                     if (ar.exception == null && ar.result != null) {
1142                         request.result = ar.result;
1143                     } else {
1144                         request.result = new IllegalArgumentException(
1145                                 "Failed to retrieve Forbidden Plmns");
1146                         if (ar.result == null) {
1147                             loge("getForbiddenPlmns: Empty response");
1148                         } else {
1149                             loge("getForbiddenPlmns: Unknown exception");
1150                         }
1151                     }
1152                     notifyRequester(request);
1153                     break;
1154 
1155                 case CMD_GET_FORBIDDEN_PLMNS:
1156                     request = (MainThreadRequest) msg.obj;
1157                     uiccCard = getUiccCardFromRequest(request);
1158                     if (uiccCard == null) {
1159                         loge("getForbiddenPlmns() UiccCard is null");
1160                         request.result = new IllegalArgumentException(
1161                                 "getForbiddenPlmns() UiccCard is null");
1162                         notifyRequester(request);
1163                         break;
1164                     }
1165                     Integer appType = (Integer) request.argument;
1166                     UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
1167                     if (uiccApp == null) {
1168                         loge("getForbiddenPlmns() no app with specified type -- "
1169                                 + appType);
1170                         request.result = new IllegalArgumentException("Failed to get UICC App");
1171                         notifyRequester(request);
1172                         break;
1173                     } else {
1174                         if (DBG) logv("getForbiddenPlmns() found app " + uiccApp.getAid()
1175                                 + " specified type -- " + appType);
1176                     }
1177                     onCompleted = obtainMessage(EVENT_GET_FORBIDDEN_PLMNS_DONE, request);
1178                     ((SIMRecords) uiccApp.getIccRecords()).getForbiddenPlmns(
1179                               onCompleted);
1180                     break;
1181 
1182                 case CMD_SWITCH_SLOTS:
1183                     request = (MainThreadRequest) msg.obj;
1184                     int[] physicalSlots = (int[]) request.argument;
1185                     onCompleted = obtainMessage(EVENT_SWITCH_SLOTS_DONE, request);
1186                     UiccController.getInstance().switchSlots(physicalSlots, onCompleted);
1187                     break;
1188 
1189                 case EVENT_SWITCH_SLOTS_DONE:
1190                     ar = (AsyncResult) msg.obj;
1191                     request = (MainThreadRequest) ar.userObj;
1192                     request.result = (ar.exception == null);
1193                     notifyRequester(request);
1194                     break;
1195                 case CMD_GET_NETWORK_SELECTION_MODE:
1196                     request = (MainThreadRequest) msg.obj;
1197                     onCompleted = obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, request);
1198                     getPhoneFromRequest(request).getNetworkSelectionMode(onCompleted);
1199                     break;
1200 
1201                 case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
1202                     ar = (AsyncResult) msg.obj;
1203                     request = (MainThreadRequest) ar.userObj;
1204                     if (ar.exception != null) {
1205                         request.result = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
1206                     } else {
1207                         int mode = ((int[]) ar.result)[0];
1208                         if (mode == 0) {
1209                             request.result = TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
1210                         } else {
1211                             request.result = TelephonyManager.NETWORK_SELECTION_MODE_MANUAL;
1212                         }
1213                     }
1214                     notifyRequester(request);
1215                     break;
1216                 case CMD_GET_CDMA_ROAMING_MODE:
1217                     request = (MainThreadRequest) msg.obj;
1218                     onCompleted = obtainMessage(EVENT_GET_CDMA_ROAMING_MODE_DONE, request);
1219                     getPhoneFromRequest(request).queryCdmaRoamingPreference(onCompleted);
1220                     break;
1221                 case EVENT_GET_CDMA_ROAMING_MODE_DONE:
1222                     ar = (AsyncResult) msg.obj;
1223                     request = (MainThreadRequest) ar.userObj;
1224                     if (ar.exception != null) {
1225                         request.result = TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT;
1226                     } else {
1227                         request.result = ((int[]) ar.result)[0];
1228                     }
1229                     notifyRequester(request);
1230                     break;
1231                 case CMD_SET_CDMA_ROAMING_MODE:
1232                     request = (MainThreadRequest) msg.obj;
1233                     onCompleted = obtainMessage(EVENT_SET_CDMA_ROAMING_MODE_DONE, request);
1234                     int mode = (int) request.argument;
1235                     getPhoneFromRequest(request).setCdmaRoamingPreference(mode, onCompleted);
1236                     break;
1237                 case EVENT_SET_CDMA_ROAMING_MODE_DONE:
1238                     ar = (AsyncResult) msg.obj;
1239                     request = (MainThreadRequest) ar.userObj;
1240                     request.result = ar.exception == null;
1241                     notifyRequester(request);
1242                     break;
1243                 case CMD_SET_CDMA_SUBSCRIPTION_MODE:
1244                     request = (MainThreadRequest) msg.obj;
1245                     onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
1246                     int subscriptionMode = (int) request.argument;
1247                     getPhoneFromRequest(request).setCdmaSubscription(subscriptionMode, onCompleted);
1248                     break;
1249                 case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
1250                     ar = (AsyncResult) msg.obj;
1251                     request = (MainThreadRequest) ar.userObj;
1252                     request.result = ar.exception == null;
1253                     notifyRequester(request);
1254                     break;
1255                 case CMD_GET_ALL_CELL_INFO:
1256                     request = (MainThreadRequest) msg.obj;
1257                     onCompleted = obtainMessage(EVENT_GET_ALL_CELL_INFO_DONE, request);
1258                     request.phone.requestCellInfoUpdate(request.workSource, onCompleted);
1259                     break;
1260                 case EVENT_GET_ALL_CELL_INFO_DONE:
1261                     ar = (AsyncResult) msg.obj;
1262                     request = (MainThreadRequest) ar.userObj;
1263                     // If a timeout occurs, the response will be null
1264                     request.result = (ar.exception == null && ar.result != null)
1265                             ? ar.result : new ArrayList<CellInfo>();
1266                     synchronized (request) {
1267                         request.notifyAll();
1268                     }
1269                     break;
1270                 case CMD_REQUEST_CELL_INFO_UPDATE:
1271                     request = (MainThreadRequest) msg.obj;
1272                     request.phone.requestCellInfoUpdate(request.workSource,
1273                             obtainMessage(EVENT_REQUEST_CELL_INFO_UPDATE_DONE, request));
1274                     break;
1275                 case EVENT_REQUEST_CELL_INFO_UPDATE_DONE:
1276                     ar = (AsyncResult) msg.obj;
1277                     request = (MainThreadRequest) ar.userObj;
1278                     ICellInfoCallback cb = (ICellInfoCallback) request.argument;
1279                     try {
1280                         if (ar.exception != null) {
1281                             Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
1282                             cb.onError(
1283                                     TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
1284                                     ar.exception.getClass().getName(),
1285                                     ar.exception.toString());
1286                         } else if (ar.result == null) {
1287                             Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
1288                             cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null, null);
1289                         } else {
1290                             // use the result as returned
1291                             cb.onCellInfo((List<CellInfo>) ar.result);
1292                         }
1293                     } catch (RemoteException re) {
1294                         Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
1295                     }
1296                     break;
1297                 case CMD_GET_CELL_LOCATION:
1298                     request = (MainThreadRequest) msg.obj;
1299                     WorkSource ws = (WorkSource) request.argument;
1300                     Phone phone = getPhoneFromRequest(request);
1301                     phone.getCellIdentity(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
1302                     break;
1303                 case EVENT_GET_CELL_LOCATION_DONE:
1304                     ar = (AsyncResult) msg.obj;
1305                     request = (MainThreadRequest) ar.userObj;
1306                     if (ar.exception == null) {
1307                         request.result = ar.result;
1308                     } else {
1309                         phone = getPhoneFromRequest(request);
1310                         request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
1311                                 ? new CellIdentityCdma() : new CellIdentityGsm();
1312                     }
1313 
1314                     synchronized (request) {
1315                         request.notifyAll();
1316                     }
1317                     break;
1318                 case CMD_MODEM_REBOOT:
1319                     request = (MainThreadRequest) msg.obj;
1320                     onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
1321                     defaultPhone.rebootModem(onCompleted);
1322                     break;
1323                 case EVENT_CMD_MODEM_REBOOT_DONE:
1324                     handleNullReturnEvent(msg, "rebootModem");
1325                     break;
1326                 case CMD_REQUEST_ENABLE_MODEM:
1327                     request = (MainThreadRequest) msg.obj;
1328                     boolean enable = (boolean) request.argument;
1329                     onCompleted = obtainMessage(EVENT_ENABLE_MODEM_DONE, request);
1330                     onCompleted.arg1 = enable ? 1 : 0;
1331                     PhoneConfigurationManager.getInstance()
1332                             .enablePhone(request.phone, enable, onCompleted);
1333                     break;
1334                 case EVENT_ENABLE_MODEM_DONE:
1335                     ar = (AsyncResult) msg.obj;
1336                     request = (MainThreadRequest) ar.userObj;
1337                     request.result = (ar.exception == null);
1338                     int phoneId = request.phone.getPhoneId();
1339                     //update the cache as modem status has changed
1340                     if ((boolean) request.result) {
1341                         mPhoneConfigurationManager.addToPhoneStatusCache(phoneId, msg.arg1 == 1);
1342                         updateModemStateMetrics();
1343                     } else {
1344                         Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
1345                                 + ar.exception);
1346                     }
1347                     notifyRequester(request);
1348                     break;
1349                 case CMD_GET_MODEM_STATUS:
1350                     request = (MainThreadRequest) msg.obj;
1351                     onCompleted = obtainMessage(EVENT_GET_MODEM_STATUS_DONE, request);
1352                     PhoneConfigurationManager.getInstance()
1353                             .getPhoneStatusFromModem(request.phone, onCompleted);
1354                     break;
1355                 case EVENT_GET_MODEM_STATUS_DONE:
1356                     ar = (AsyncResult) msg.obj;
1357                     request = (MainThreadRequest) ar.userObj;
1358                     int id = request.phone.getPhoneId();
1359                     if (ar.exception == null && ar.result != null) {
1360                         request.result = ar.result;
1361                         //update the cache as modem status has changed
1362                         mPhoneConfigurationManager.addToPhoneStatusCache(id,
1363                                 (boolean) request.result);
1364                     } else {
1365                         // Return true if modem status cannot be retrieved. For most cases,
1366                         // modem status is on. And for older version modems, GET_MODEM_STATUS
1367                         // and disable modem are not supported. Modem is always on.
1368                         // TODO: this should be fixed in R to support a third
1369                         // status UNKNOWN b/131631629
1370                         request.result = true;
1371                         Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
1372                                 + ar.exception);
1373                     }
1374                     notifyRequester(request);
1375                     break;
1376                 case CMD_SET_SYSTEM_SELECTION_CHANNELS: {
1377                     request = (MainThreadRequest) msg.obj;
1378                     onCompleted = obtainMessage(EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE, request);
1379                     Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> args =
1380                             (Pair<List<RadioAccessSpecifier>, Consumer<Boolean>>) request.argument;
1381                     request.phone.setSystemSelectionChannels(args.first, onCompleted);
1382                     break;
1383                 }
1384                 case EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE: {
1385                     ar = (AsyncResult) msg.obj;
1386                     request = (MainThreadRequest) ar.userObj;
1387                     Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> args =
1388                             (Pair<List<RadioAccessSpecifier>, Consumer<Boolean>>) request.argument;
1389                     args.second.accept(ar.exception == null);
1390                     notifyRequester(request);
1391                     break;
1392                 }
1393                 case EVENT_SET_FORBIDDEN_PLMNS_DONE:
1394                     ar = (AsyncResult) msg.obj;
1395                     request = (MainThreadRequest) ar.userObj;
1396                     if (ar.exception == null && ar.result != null) {
1397                         request.result = ar.result;
1398                     } else {
1399                         request.result = -1;
1400                         loge("Failed to set Forbidden Plmns");
1401                         if (ar.result == null) {
1402                             loge("setForbidenPlmns: Empty response");
1403                         } else if (ar.exception != null) {
1404                             loge("setForbiddenPlmns: Exception: " + ar.exception);
1405                             request.result = -1;
1406                         } else {
1407                             loge("setForbiddenPlmns: Unknown exception");
1408                         }
1409                     }
1410                     notifyRequester(request);
1411                     break;
1412                 case CMD_SET_FORBIDDEN_PLMNS:
1413                     request = (MainThreadRequest) msg.obj;
1414                     uiccCard = getUiccCardFromRequest(request);
1415                     if (uiccCard == null) {
1416                         loge("setForbiddenPlmns: UiccCard is null");
1417                         request.result = -1;
1418                         notifyRequester(request);
1419                         break;
1420                     }
1421                     Pair<Integer, List<String>> setFplmnsArgs =
1422                             (Pair<Integer, List<String>>) request.argument;
1423                     appType = setFplmnsArgs.first;
1424                     List<String> fplmns = setFplmnsArgs.second;
1425                     uiccApp = uiccCard.getApplicationByType(appType);
1426                     if (uiccApp == null) {
1427                         loge("setForbiddenPlmns: no app with specified type -- " + appType);
1428                         request.result = -1;
1429                         loge("Failed to get UICC App");
1430                         notifyRequester(request);
1431                     } else {
1432                         onCompleted = obtainMessage(EVENT_SET_FORBIDDEN_PLMNS_DONE, request);
1433                         ((SIMRecords) uiccApp.getIccRecords())
1434                                 .setForbiddenPlmns(onCompleted, fplmns);
1435                     }
1436                     break;
1437                 case CMD_ERASE_MODEM_CONFIG:
1438                     request = (MainThreadRequest) msg.obj;
1439                     onCompleted = obtainMessage(EVENT_ERASE_MODEM_CONFIG_DONE, request);
1440                     defaultPhone.eraseModemConfig(onCompleted);
1441                     break;
1442                 case EVENT_ERASE_MODEM_CONFIG_DONE:
1443                     handleNullReturnEvent(msg, "eraseModemConfig");
1444                     break;
1445 
1446                 case CMD_CHANGE_ICC_LOCK_PASSWORD:
1447                     request = (MainThreadRequest) msg.obj;
1448                     onCompleted = obtainMessage(EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE, request);
1449                     Pair<String, String> changed = (Pair<String, String>) request.argument;
1450                     getPhoneFromRequest(request).getIccCard().changeIccLockPassword(
1451                             changed.first, changed.second, onCompleted);
1452                     break;
1453                 case EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE:
1454                     ar = (AsyncResult) msg.obj;
1455                     request = (MainThreadRequest) ar.userObj;
1456                     if (ar.exception == null) {
1457                         request.result = TelephonyManager.CHANGE_ICC_LOCK_SUCCESS;
1458                     } else {
1459                         request.result = msg.arg1;
1460                     }
1461                     notifyRequester(request);
1462                     break;
1463 
1464                 case CMD_SET_ICC_LOCK_ENABLED:
1465                     request = (MainThreadRequest) msg.obj;
1466                     onCompleted = obtainMessage(EVENT_SET_ICC_LOCK_ENABLED_DONE, request);
1467                     Pair<Boolean, String> enabled = (Pair<Boolean, String>) request.argument;
1468                     getPhoneFromRequest(request).getIccCard().setIccLockEnabled(
1469                             enabled.first, enabled.second, onCompleted);
1470                     break;
1471                 case EVENT_SET_ICC_LOCK_ENABLED_DONE:
1472                     ar = (AsyncResult) msg.obj;
1473                     request = (MainThreadRequest) ar.userObj;
1474                     if (ar.exception == null) {
1475                         request.result = TelephonyManager.CHANGE_ICC_LOCK_SUCCESS;
1476                     } else {
1477                         request.result = msg.arg1;
1478                     }
1479                     notifyRequester(request);
1480                     break;
1481 
1482                 default:
1483                     Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
1484                     break;
1485             }
1486         }
1487 
notifyRequester(MainThreadRequest request)1488         private void notifyRequester(MainThreadRequest request) {
1489             synchronized (request) {
1490                 request.notifyAll();
1491             }
1492         }
1493 
handleNullReturnEvent(Message msg, String command)1494         private void handleNullReturnEvent(Message msg, String command) {
1495             AsyncResult ar = (AsyncResult) msg.obj;
1496             MainThreadRequest request = (MainThreadRequest) ar.userObj;
1497             if (ar.exception == null) {
1498                 request.result = true;
1499             } else {
1500                 request.result = false;
1501                 if (ar.exception instanceof CommandException) {
1502                     loge(command + ": CommandException: " + ar.exception);
1503                 } else {
1504                     loge(command + ": Unknown exception");
1505                 }
1506             }
1507             notifyRequester(request);
1508         }
1509     }
1510 
1511     /**
1512      * Posts the specified command to be executed on the main thread,
1513      * waits for the request to complete, and returns the result.
1514      * @see #sendRequestAsync
1515      */
sendRequest(int command, Object argument)1516     private Object sendRequest(int command, Object argument) {
1517         return sendRequest(
1518                 command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, null, null);
1519     }
1520 
1521     /**
1522      * Posts the specified command to be executed on the main thread,
1523      * waits for the request to complete, and returns the result.
1524      * @see #sendRequestAsync
1525      */
sendRequest(int command, Object argument, WorkSource workSource)1526     private Object sendRequest(int command, Object argument, WorkSource workSource) {
1527         return sendRequest(command, argument,  SubscriptionManager.INVALID_SUBSCRIPTION_ID,
1528                 null, workSource);
1529     }
1530 
1531     /**
1532      * Posts the specified command to be executed on the main thread,
1533      * waits for the request to complete, and returns the result.
1534      * @see #sendRequestAsync
1535      */
sendRequest(int command, Object argument, Integer subId)1536     private Object sendRequest(int command, Object argument, Integer subId) {
1537         return sendRequest(command, argument, subId, null, null);
1538     }
1539 
1540     /**
1541      * Posts the specified command to be executed on the main thread,
1542      * waits for the request to complete, and returns the result.
1543      * @see #sendRequestAsync
1544      */
sendRequest(int command, Object argument, int subId, WorkSource workSource)1545     private Object sendRequest(int command, Object argument, int subId, WorkSource workSource) {
1546         return sendRequest(command, argument, subId, null, workSource);
1547     }
1548 
1549     /**
1550      * Posts the specified command to be executed on the main thread,
1551      * waits for the request to complete, and returns the result.
1552      * @see #sendRequestAsync
1553      */
sendRequest(int command, Object argument, Phone phone, WorkSource workSource)1554     private Object sendRequest(int command, Object argument, Phone phone, WorkSource workSource) {
1555         return sendRequest(
1556                 command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phone, workSource);
1557     }
1558 
1559     /**
1560      * Posts the specified command to be executed on the main thread,
1561      * waits for the request to complete, and returns the result.
1562      * @see #sendRequestAsync
1563      */
sendRequest( int command, Object argument, Integer subId, Phone phone, WorkSource workSource)1564     private Object sendRequest(
1565             int command, Object argument, Integer subId, Phone phone, WorkSource workSource) {
1566         if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
1567             throw new RuntimeException("This method will deadlock if called from the main thread.");
1568         }
1569 
1570         MainThreadRequest request = null;
1571         if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && phone != null) {
1572             throw new IllegalArgumentException("subId and phone cannot both be specified!");
1573         } else if (phone != null) {
1574             request = new MainThreadRequest(argument, phone, workSource);
1575         } else {
1576             request = new MainThreadRequest(argument, subId, workSource);
1577         }
1578 
1579         Message msg = mMainThreadHandler.obtainMessage(command, request);
1580         msg.sendToTarget();
1581 
1582         // Wait for the request to complete
1583         synchronized (request) {
1584             while (request.result == null) {
1585                 try {
1586                     request.wait();
1587                 } catch (InterruptedException e) {
1588                     // Do nothing, go back and wait until the request is complete
1589                 }
1590             }
1591         }
1592         return request.result;
1593     }
1594 
1595     /**
1596      * Asynchronous ("fire and forget") version of sendRequest():
1597      * Posts the specified command to be executed on the main thread, and
1598      * returns immediately.
1599      * @see #sendRequest
1600      */
sendRequestAsync(int command)1601     private void sendRequestAsync(int command) {
1602         mMainThreadHandler.sendEmptyMessage(command);
1603     }
1604 
1605     /**
1606      * Same as {@link #sendRequestAsync(int)} except it takes an argument.
1607      * @see {@link #sendRequest(int)}
1608      */
sendRequestAsync(int command, Object argument)1609     private void sendRequestAsync(int command, Object argument) {
1610         sendRequestAsync(command, argument, null, null);
1611     }
1612 
1613     /**
1614      * Same as {@link #sendRequestAsync(int,Object)} except it takes a Phone and WorkSource.
1615      * @see {@link #sendRequest(int,Object)}
1616      */
sendRequestAsync( int command, Object argument, Phone phone, WorkSource workSource)1617     private void sendRequestAsync(
1618             int command, Object argument, Phone phone, WorkSource workSource) {
1619         MainThreadRequest request = new MainThreadRequest(argument, phone, workSource);
1620         Message msg = mMainThreadHandler.obtainMessage(command, request);
1621         msg.sendToTarget();
1622     }
1623 
1624     /**
1625      * Initialize the singleton PhoneInterfaceManager instance.
1626      * This is only done once, at startup, from PhoneApp.onCreate().
1627      */
init(PhoneGlobals app)1628     /* package */ static PhoneInterfaceManager init(PhoneGlobals app) {
1629         synchronized (PhoneInterfaceManager.class) {
1630             if (sInstance == null) {
1631                 sInstance = new PhoneInterfaceManager(app);
1632             } else {
1633                 Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
1634             }
1635             return sInstance;
1636         }
1637     }
1638 
1639     /** Private constructor; @see init() */
1640     @VisibleForTesting
PhoneInterfaceManager(PhoneGlobals app)1641     /* package */ PhoneInterfaceManager(PhoneGlobals app) {
1642         mApp = app;
1643         mCM = PhoneGlobals.getInstance().mCM;
1644         mImsResolver = PhoneGlobals.getInstance().getImsResolver();
1645         mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
1646         mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
1647         mMainThreadHandler = new MainThreadHandler();
1648         mSubscriptionController = SubscriptionController.getInstance();
1649         mTelephonySharedPreferences =
1650                 PreferenceManager.getDefaultSharedPreferences(mApp);
1651         mNetworkScanRequestTracker = new NetworkScanRequestTracker();
1652         mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
1653 
1654         publish();
1655     }
1656 
getDefaultPhone()1657     private Phone getDefaultPhone() {
1658         Phone thePhone = getPhone(getDefaultSubscription());
1659         return (thePhone != null) ? thePhone : PhoneFactory.getDefaultPhone();
1660     }
1661 
publish()1662     private void publish() {
1663         if (DBG) log("publish: " + this);
1664 
1665         ServiceManager.addService("phone", this);
1666     }
1667 
getPhoneFromRequest(MainThreadRequest request)1668     private Phone getPhoneFromRequest(MainThreadRequest request) {
1669         if (request.phone != null) {
1670             return request.phone;
1671         } else {
1672             return getPhoneFromSubId(request.subId);
1673         }
1674     }
1675 
getPhoneFromSubId(int subId)1676     private Phone getPhoneFromSubId(int subId) {
1677         return (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
1678                 ? getDefaultPhone() : getPhone(subId);
1679     }
1680 
getUiccCardFromRequest(MainThreadRequest request)1681     private UiccCard getUiccCardFromRequest(MainThreadRequest request) {
1682         Phone phone = getPhoneFromRequest(request);
1683         return phone == null ? null :
1684                 UiccController.getInstance().getUiccCard(phone.getPhoneId());
1685     }
1686 
1687     // returns phone associated with the subId.
getPhone(int subId)1688     private Phone getPhone(int subId) {
1689         return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
1690     }
1691 
sendEraseModemConfig(Phone phone)1692     private void sendEraseModemConfig(Phone phone) {
1693         if (phone != null) {
1694             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
1695                   mApp, phone.getSubId(), "eraseModemConfig");
1696             final long identity = Binder.clearCallingIdentity();
1697             try {
1698                 Boolean success = (Boolean) sendRequest(CMD_ERASE_MODEM_CONFIG, null);
1699                 if (DBG) log("eraseModemConfig:" + ' ' + (success ? "ok" : "fail"));
1700             } finally {
1701                 Binder.restoreCallingIdentity(identity);
1702             }
1703         }
1704     }
1705 
isImsAvailableOnDevice()1706     private boolean isImsAvailableOnDevice() {
1707         PackageManager pm = getDefaultPhone().getContext().getPackageManager();
1708         if (pm == null) {
1709             // For some reason package manger is not available.. This will fail internally anyway,
1710             // so do not throw error and allow.
1711             return true;
1712         }
1713         return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
1714     }
1715 
dial(String number)1716     public void dial(String number) {
1717         dialForSubscriber(getPreferredVoiceSubscription(), number);
1718     }
1719 
dialForSubscriber(int subId, String number)1720     public void dialForSubscriber(int subId, String number) {
1721         if (DBG) log("dial: " + number);
1722         // No permission check needed here: This is just a wrapper around the
1723         // ACTION_DIAL intent, which is available to any app since it puts up
1724         // the UI before it does anything.
1725 
1726         final long identity = Binder.clearCallingIdentity();
1727         try {
1728             String url = createTelUrl(number);
1729             if (url == null) {
1730                 return;
1731             }
1732 
1733             // PENDING: should we just silently fail if phone is offhook or ringing?
1734             PhoneConstants.State state = mCM.getState(subId);
1735             if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
1736                 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
1737                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1738                 mApp.startActivity(intent);
1739             }
1740         } finally {
1741             Binder.restoreCallingIdentity(identity);
1742         }
1743     }
1744 
call(String callingPackage, String number)1745     public void call(String callingPackage, String number) {
1746         callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
1747     }
1748 
callForSubscriber(int subId, String callingPackage, String number)1749     public void callForSubscriber(int subId, String callingPackage, String number) {
1750         if (DBG) log("call: " + number);
1751 
1752         // This is just a wrapper around the ACTION_CALL intent, but we still
1753         // need to do a permission check since we're calling startActivity()
1754         // from the context of the phone app.
1755         enforceCallPermission();
1756 
1757         if (mAppOps.noteOp(AppOpsManager.OPSTR_CALL_PHONE, Binder.getCallingUid(), callingPackage)
1758                 != AppOpsManager.MODE_ALLOWED) {
1759             return;
1760         }
1761 
1762         final long identity = Binder.clearCallingIdentity();
1763         try {
1764             String url = createTelUrl(number);
1765             if (url == null) {
1766                 return;
1767             }
1768 
1769             boolean isValid = false;
1770             final List<SubscriptionInfo> slist = getActiveSubscriptionInfoListPrivileged();
1771             if (slist != null) {
1772                 for (SubscriptionInfo subInfoRecord : slist) {
1773                     if (subInfoRecord.getSubscriptionId() == subId) {
1774                         isValid = true;
1775                         break;
1776                     }
1777                 }
1778             }
1779             if (!isValid) {
1780                 return;
1781             }
1782 
1783             Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
1784             intent.putExtra(SUBSCRIPTION_KEY, subId);
1785             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1786             mApp.startActivity(intent);
1787         } finally {
1788             Binder.restoreCallingIdentity(identity);
1789         }
1790     }
1791 
supplyPinForSubscriber(int subId, String pin)1792     public boolean supplyPinForSubscriber(int subId, String pin) {
1793         int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
1794         return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1795     }
1796 
supplyPukForSubscriber(int subId, String puk, String pin)1797     public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
1798         int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
1799         return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1800     }
1801 
supplyPinReportResultForSubscriber(int subId, String pin)1802     public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
1803         enforceModifyPermission();
1804 
1805         final long identity = Binder.clearCallingIdentity();
1806         try {
1807             final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
1808             checkSimPin.start();
1809             return checkSimPin.unlockSim(null, pin);
1810         } finally {
1811             Binder.restoreCallingIdentity(identity);
1812         }
1813     }
1814 
supplyPukReportResultForSubscriber(int subId, String puk, String pin)1815     public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
1816         enforceModifyPermission();
1817 
1818         final long identity = Binder.clearCallingIdentity();
1819         try {
1820             final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
1821             checkSimPuk.start();
1822             return checkSimPuk.unlockSim(puk, pin);
1823         } finally {
1824             Binder.restoreCallingIdentity(identity);
1825         }
1826     }
1827 
1828     /**
1829      * Helper thread to turn async call to SimCard#supplyPin into
1830      * a synchronous one.
1831      */
1832     private static class UnlockSim extends Thread {
1833 
1834         private final IccCard mSimCard;
1835 
1836         private boolean mDone = false;
1837         private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1838         private int mRetryCount = -1;
1839 
1840         // For replies from SimCard interface
1841         private Handler mHandler;
1842 
1843         // For async handler to identify request type
1844         private static final int SUPPLY_PIN_COMPLETE = 100;
1845 
UnlockSim(IccCard simCard)1846         public UnlockSim(IccCard simCard) {
1847             mSimCard = simCard;
1848         }
1849 
1850         @Override
run()1851         public void run() {
1852             Looper.prepare();
1853             synchronized (UnlockSim.this) {
1854                 mHandler = new Handler() {
1855                     @Override
1856                     public void handleMessage(Message msg) {
1857                         AsyncResult ar = (AsyncResult) msg.obj;
1858                         switch (msg.what) {
1859                             case SUPPLY_PIN_COMPLETE:
1860                                 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
1861                                 synchronized (UnlockSim.this) {
1862                                     mRetryCount = msg.arg1;
1863                                     if (ar.exception != null) {
1864                                         if (ar.exception instanceof CommandException &&
1865                                                 ((CommandException)(ar.exception)).getCommandError()
1866                                                 == CommandException.Error.PASSWORD_INCORRECT) {
1867                                             mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1868                                         } //When UiccCardApp dispose,handle message and return exception
1869                                           else if (ar.exception instanceof CommandException &&
1870                                                 ((CommandException) (ar.exception)).getCommandError()
1871                                                         == CommandException.Error.ABORTED) {
1872                                             mResult = PhoneConstants.PIN_OPERATION_ABORTED;
1873                                         } else {
1874                                             mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1875                                         }
1876                                     } else {
1877                                         mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1878                                     }
1879                                     mDone = true;
1880                                     UnlockSim.this.notifyAll();
1881                                 }
1882                                 break;
1883                         }
1884                     }
1885                 };
1886                 UnlockSim.this.notifyAll();
1887             }
1888             Looper.loop();
1889         }
1890 
1891         /*
1892          * Use PIN or PUK to unlock SIM card
1893          *
1894          * If PUK is null, unlock SIM card with PIN
1895          *
1896          * If PUK is not null, unlock SIM card with PUK and set PIN code
1897          */
unlockSim(String puk, String pin)1898         synchronized int[] unlockSim(String puk, String pin) {
1899 
1900             while (mHandler == null) {
1901                 try {
1902                     wait();
1903                 } catch (InterruptedException e) {
1904                     Thread.currentThread().interrupt();
1905                 }
1906             }
1907             Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1908 
1909             if (puk == null) {
1910                 mSimCard.supplyPin(pin, callback);
1911             } else {
1912                 mSimCard.supplyPuk(puk, pin, callback);
1913             }
1914 
1915             while (!mDone) {
1916                 try {
1917                     Log.d(LOG_TAG, "wait for done");
1918                     wait();
1919                 } catch (InterruptedException e) {
1920                     // Restore the interrupted status
1921                     Thread.currentThread().interrupt();
1922                 }
1923             }
1924             Log.d(LOG_TAG, "done");
1925             int[] resultArray = new int[2];
1926             resultArray[0] = mResult;
1927             resultArray[1] = mRetryCount;
1928             return resultArray;
1929         }
1930     }
1931 
1932     /**
1933      * This method has been removed due to privacy and stability concerns.
1934      */
1935     @Override
updateServiceLocation()1936     public void updateServiceLocation() {
1937         Log.e(LOG_TAG, "Call to unsupported method updateServiceLocation()");
1938         return;
1939     }
1940 
1941     @Override
updateServiceLocationWithPackageName(String callingPackage)1942     public void updateServiceLocationWithPackageName(String callingPackage) {
1943         mApp.getSystemService(AppOpsManager.class)
1944                 .checkPackage(Binder.getCallingUid(), callingPackage);
1945 
1946         final int targetSdk = getTargetSdk(callingPackage);
1947         if (targetSdk > android.os.Build.VERSION_CODES.R) {
1948             // Callers targeting S have no business invoking this method.
1949             return;
1950         }
1951 
1952         LocationAccessPolicy.LocationPermissionResult locationResult =
1953                 LocationAccessPolicy.checkLocationPermission(mApp,
1954                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
1955                                 .setCallingPackage(callingPackage)
1956                                 .setCallingFeatureId(null)
1957                                 .setCallingPid(Binder.getCallingPid())
1958                                 .setCallingUid(Binder.getCallingUid())
1959                                 .setMethod("updateServiceLocation")
1960                                 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
1961                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
1962                                 .build());
1963         // Apps that lack location permission have no business calling this method;
1964         // however, because no permission was declared in the public API, denials must
1965         // all be "soft".
1966         switch (locationResult) {
1967             case DENIED_HARD: /* fall through */
1968             case DENIED_SOFT:
1969                 return;
1970         }
1971 
1972         WorkSource workSource = getWorkSource(Binder.getCallingUid());
1973         final long identity = Binder.clearCallingIdentity();
1974         try {
1975             final Phone phone = getPhone(getDefaultSubscription());
1976             if (phone != null) {
1977                 phone.updateServiceLocation(workSource);
1978             }
1979         } finally {
1980             Binder.restoreCallingIdentity(identity);
1981         }
1982     }
1983 
1984     @Deprecated
1985     @Override
isRadioOn(String callingPackage)1986     public boolean isRadioOn(String callingPackage) {
1987         return isRadioOnWithFeature(callingPackage, null);
1988     }
1989 
1990     @Override
isRadioOnWithFeature(String callingPackage, String callingFeatureId)1991     public boolean isRadioOnWithFeature(String callingPackage, String callingFeatureId) {
1992         return isRadioOnForSubscriberWithFeature(getDefaultSubscription(), callingPackage,
1993                 callingFeatureId);
1994     }
1995 
1996     @Deprecated
1997     @Override
isRadioOnForSubscriber(int subId, String callingPackage)1998     public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
1999         return isRadioOnForSubscriberWithFeature(subId, callingPackage, null);
2000     }
2001 
2002     @Override
isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId)2003     public boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage,
2004             String callingFeatureId) {
2005         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2006                 mApp, subId, callingPackage, callingFeatureId, "isRadioOnForSubscriber")) {
2007             return false;
2008         }
2009 
2010         final long identity = Binder.clearCallingIdentity();
2011         try {
2012             return isRadioOnForSubscriber(subId);
2013         } finally {
2014             Binder.restoreCallingIdentity(identity);
2015         }
2016     }
2017 
isRadioOnForSubscriber(int subId)2018     private boolean isRadioOnForSubscriber(int subId) {
2019         final long identity = Binder.clearCallingIdentity();
2020         try {
2021             final Phone phone = getPhone(subId);
2022             if (phone != null) {
2023                 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
2024             } else {
2025                 return false;
2026             }
2027         } finally {
2028             Binder.restoreCallingIdentity(identity);
2029         }
2030     }
2031 
toggleRadioOnOff()2032     public void toggleRadioOnOff() {
2033         toggleRadioOnOffForSubscriber(getDefaultSubscription());
2034     }
2035 
toggleRadioOnOffForSubscriber(int subId)2036     public void toggleRadioOnOffForSubscriber(int subId) {
2037         enforceModifyPermission();
2038 
2039         final long identity = Binder.clearCallingIdentity();
2040         try {
2041             final Phone phone = getPhone(subId);
2042             if (phone != null) {
2043                 phone.setRadioPower(!isRadioOnForSubscriber(subId));
2044             }
2045         } finally {
2046             Binder.restoreCallingIdentity(identity);
2047         }
2048     }
2049 
setRadio(boolean turnOn)2050     public boolean setRadio(boolean turnOn) {
2051         return setRadioForSubscriber(getDefaultSubscription(), turnOn);
2052     }
2053 
setRadioForSubscriber(int subId, boolean turnOn)2054     public boolean setRadioForSubscriber(int subId, boolean turnOn) {
2055         enforceModifyPermission();
2056 
2057         final long identity = Binder.clearCallingIdentity();
2058         try {
2059             final Phone phone = getPhone(subId);
2060             if (phone == null) {
2061                 return false;
2062             }
2063             if ((phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF) != turnOn) {
2064                 toggleRadioOnOffForSubscriber(subId);
2065             }
2066             return true;
2067         } finally {
2068             Binder.restoreCallingIdentity(identity);
2069         }
2070     }
2071 
needMobileRadioShutdown()2072     public boolean needMobileRadioShutdown() {
2073         enforceReadPrivilegedPermission("needMobileRadioShutdown");
2074         /*
2075          * If any of the Radios are available, it will need to be
2076          * shutdown. So return true if any Radio is available.
2077          */
2078         final long identity = Binder.clearCallingIdentity();
2079         try {
2080             for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2081                 Phone phone = PhoneFactory.getPhone(i);
2082                 if (phone != null && phone.isRadioAvailable()) return true;
2083             }
2084             logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
2085             return false;
2086         } finally {
2087             Binder.restoreCallingIdentity(identity);
2088         }
2089     }
2090 
2091     @Override
shutdownMobileRadios()2092     public void shutdownMobileRadios() {
2093         enforceModifyPermission();
2094 
2095         final long identity = Binder.clearCallingIdentity();
2096         try {
2097             for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2098                 logv("Shutting down Phone " + i);
2099                 shutdownRadioUsingPhoneId(i);
2100             }
2101         } finally {
2102             Binder.restoreCallingIdentity(identity);
2103         }
2104     }
2105 
shutdownRadioUsingPhoneId(int phoneId)2106     private void shutdownRadioUsingPhoneId(int phoneId) {
2107         Phone phone = PhoneFactory.getPhone(phoneId);
2108         if (phone != null && phone.isRadioAvailable()) {
2109             phone.shutdownRadio();
2110         }
2111     }
2112 
setRadioPower(boolean turnOn)2113     public boolean setRadioPower(boolean turnOn) {
2114         enforceModifyPermission();
2115 
2116         final long identity = Binder.clearCallingIdentity();
2117         try {
2118             final Phone defaultPhone = PhoneFactory.getDefaultPhone();
2119             if (defaultPhone != null) {
2120                 defaultPhone.setRadioPower(turnOn);
2121                 return true;
2122             } else {
2123                 loge("There's no default phone.");
2124                 return false;
2125             }
2126         } finally {
2127             Binder.restoreCallingIdentity(identity);
2128         }
2129     }
2130 
setRadioPowerForSubscriber(int subId, boolean turnOn)2131     public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
2132         enforceModifyPermission();
2133 
2134         final long identity = Binder.clearCallingIdentity();
2135         try {
2136             final Phone phone = getPhone(subId);
2137             if (phone != null) {
2138                 phone.setRadioPower(turnOn);
2139                 return true;
2140             } else {
2141                 return false;
2142             }
2143         } finally {
2144             Binder.restoreCallingIdentity(identity);
2145         }
2146     }
2147 
2148     // FIXME: subId version needed
2149     @Override
enableDataConnectivity()2150     public boolean enableDataConnectivity() {
2151         enforceModifyPermission();
2152 
2153         final long identity = Binder.clearCallingIdentity();
2154         try {
2155             int subId = mSubscriptionController.getDefaultDataSubId();
2156             final Phone phone = getPhone(subId);
2157             if (phone != null) {
2158                 phone.getDataEnabledSettings().setUserDataEnabled(true);
2159                 return true;
2160             } else {
2161                 return false;
2162             }
2163         } finally {
2164             Binder.restoreCallingIdentity(identity);
2165         }
2166     }
2167 
2168     // FIXME: subId version needed
2169     @Override
disableDataConnectivity()2170     public boolean disableDataConnectivity() {
2171         enforceModifyPermission();
2172 
2173         final long identity = Binder.clearCallingIdentity();
2174         try {
2175             int subId = mSubscriptionController.getDefaultDataSubId();
2176             final Phone phone = getPhone(subId);
2177             if (phone != null) {
2178                 phone.getDataEnabledSettings().setUserDataEnabled(false);
2179                 return true;
2180             } else {
2181                 return false;
2182             }
2183         } finally {
2184             Binder.restoreCallingIdentity(identity);
2185         }
2186     }
2187 
2188     @Override
isDataConnectivityPossible(int subId)2189     public boolean isDataConnectivityPossible(int subId) {
2190         final long identity = Binder.clearCallingIdentity();
2191         try {
2192             final Phone phone = getPhone(subId);
2193             if (phone != null) {
2194                 return phone.isDataAllowed(ApnSetting.TYPE_DEFAULT);
2195             } else {
2196                 return false;
2197             }
2198         } finally {
2199             Binder.restoreCallingIdentity(identity);
2200         }
2201     }
2202 
handlePinMmi(String dialString)2203     public boolean handlePinMmi(String dialString) {
2204         return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
2205     }
2206 
handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback)2207     public void handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback) {
2208         enforceCallPermission();
2209 
2210         final long identity = Binder.clearCallingIdentity();
2211         try {
2212             if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2213                 return;
2214             }
2215             Pair<String, ResultReceiver> ussdObject = new Pair(ussdRequest, wrappedCallback);
2216             sendRequest(CMD_HANDLE_USSD_REQUEST, ussdObject, subId);
2217         } finally {
2218             Binder.restoreCallingIdentity(identity);
2219         }
2220     };
2221 
handlePinMmiForSubscriber(int subId, String dialString)2222     public boolean handlePinMmiForSubscriber(int subId, String dialString) {
2223         enforceModifyPermission();
2224 
2225         final long identity = Binder.clearCallingIdentity();
2226         try {
2227             if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2228                 return false;
2229             }
2230             return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
2231         } finally {
2232             Binder.restoreCallingIdentity(identity);
2233         }
2234     }
2235 
getCallState()2236     public int getCallState() {
2237         return getCallStateForSlot(getSlotForDefaultSubscription());
2238     }
2239 
getCallStateForSlot(int slotIndex)2240     public int getCallStateForSlot(int slotIndex) {
2241         final long identity = Binder.clearCallingIdentity();
2242         try {
2243             Phone phone = PhoneFactory.getPhone(slotIndex);
2244             return phone == null ? TelephonyManager.CALL_STATE_IDLE :
2245                     PhoneConstantConversions.convertCallState(phone.getState());
2246         } finally {
2247             Binder.restoreCallingIdentity(identity);
2248         }
2249     }
2250 
2251     @Override
getDataState()2252     public int getDataState() {
2253         return getDataStateForSubId(mSubscriptionController.getDefaultDataSubId());
2254     }
2255 
2256     @Override
getDataStateForSubId(int subId)2257     public int getDataStateForSubId(int subId) {
2258         final long identity = Binder.clearCallingIdentity();
2259         try {
2260             final Phone phone = getPhone(subId);
2261             if (phone != null) {
2262                 return PhoneConstantConversions.convertDataState(phone.getDataConnectionState());
2263             } else {
2264                 return PhoneConstantConversions.convertDataState(
2265                         PhoneConstants.DataState.DISCONNECTED);
2266             }
2267         } finally {
2268             Binder.restoreCallingIdentity(identity);
2269         }
2270     }
2271 
2272     @Override
getDataActivity()2273     public int getDataActivity() {
2274         return getDataActivityForSubId(mSubscriptionController.getDefaultDataSubId());
2275     }
2276 
2277     @Override
getDataActivityForSubId(int subId)2278     public int getDataActivityForSubId(int subId) {
2279         final long identity = Binder.clearCallingIdentity();
2280         try {
2281             final Phone phone = getPhone(subId);
2282             if (phone != null) {
2283                 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
2284             } else {
2285                 return TelephonyManager.DATA_ACTIVITY_NONE;
2286             }
2287         } finally {
2288             Binder.restoreCallingIdentity(identity);
2289         }
2290     }
2291 
2292     @Override
getCellLocation(String callingPackage, String callingFeatureId)2293     public CellIdentity getCellLocation(String callingPackage, String callingFeatureId) {
2294         mApp.getSystemService(AppOpsManager.class)
2295                 .checkPackage(Binder.getCallingUid(), callingPackage);
2296 
2297         LocationAccessPolicy.LocationPermissionResult locationResult =
2298                 LocationAccessPolicy.checkLocationPermission(mApp,
2299                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
2300                                 .setCallingPackage(callingPackage)
2301                                 .setCallingFeatureId(callingFeatureId)
2302                                 .setCallingPid(Binder.getCallingPid())
2303                                 .setCallingUid(Binder.getCallingUid())
2304                                 .setMethod("getCellLocation")
2305                                 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
2306                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
2307                                 .build());
2308         switch (locationResult) {
2309             case DENIED_HARD:
2310                 throw new SecurityException("Not allowed to access cell location");
2311             case DENIED_SOFT:
2312                 return (getDefaultPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
2313                         ? new CellIdentityCdma() : new CellIdentityGsm();
2314         }
2315 
2316         WorkSource workSource = getWorkSource(Binder.getCallingUid());
2317         final long identity = Binder.clearCallingIdentity();
2318         try {
2319             if (DBG_LOC) log("getCellLocation: is active user");
2320             int subId = mSubscriptionController.getDefaultDataSubId();
2321             return (CellIdentity) sendRequest(CMD_GET_CELL_LOCATION, workSource, subId);
2322         } finally {
2323             Binder.restoreCallingIdentity(identity);
2324         }
2325     }
2326 
2327     @Override
getNetworkCountryIsoForPhone(int phoneId)2328     public String getNetworkCountryIsoForPhone(int phoneId) {
2329         // Reporting the correct network country is ambiguous when IWLAN could conflict with
2330         // registered cell info, so return a NULL country instead.
2331         final long identity = Binder.clearCallingIdentity();
2332         try {
2333             if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
2334                 // Get default phone in this case.
2335                 phoneId = SubscriptionManager.DEFAULT_PHONE_INDEX;
2336             }
2337             final int subId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
2338             Phone phone = PhoneFactory.getPhone(phoneId);
2339             if (phone == null) return "";
2340             ServiceStateTracker sst = phone.getServiceStateTracker();
2341             if (sst == null) return "";
2342             LocaleTracker lt = sst.getLocaleTracker();
2343             if (lt == null) return "";
2344             if (!TextUtils.isEmpty(lt.getCurrentCountry())) return lt.getCurrentCountry();
2345             EmergencyNumberTracker ent = phone.getEmergencyNumberTracker();
2346             return (ent == null) ? "" : ent.getEmergencyCountryIso();
2347         } finally {
2348             Binder.restoreCallingIdentity(identity);
2349         }
2350     }
2351 
2352     /**
2353      * This method was removed due to potential issues caused by performing partial
2354      * updates of service state, and lack of a credible use case.
2355      *
2356      * This has the ability to break the telephony implementation by disabling notification of
2357      * changes in device connectivity. DO NOT USE THIS!
2358      */
2359     @Override
enableLocationUpdates()2360     public void enableLocationUpdates() {
2361         mApp.enforceCallingOrSelfPermission(
2362                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
2363     }
2364 
2365     /**
2366      * This method was removed due to potential issues caused by performing partial
2367      * updates of service state, and lack of a credible use case.
2368      *
2369      * This has the ability to break the telephony implementation by disabling notification of
2370      * changes in device connectivity. DO NOT USE THIS!
2371      */
2372     @Override
disableLocationUpdates()2373     public void disableLocationUpdates() {
2374         mApp.enforceCallingOrSelfPermission(
2375                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
2376     }
2377 
2378     /**
2379      * Returns the target SDK version number for a given package name.
2380      *
2381      * This call MUST be invoked before clearing the calling UID.
2382      *
2383      * @return target SDK if the package is found or INT_MAX.
2384      */
getTargetSdk(String packageName)2385     private int getTargetSdk(String packageName) {
2386         try {
2387             final ApplicationInfo ai = mApp.getPackageManager().getApplicationInfoAsUser(
2388                     packageName, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
2389             if (ai != null) return ai.targetSdkVersion;
2390         } catch (PackageManager.NameNotFoundException unexpected) {
2391             loge("Failed to get package info for pkg="
2392                     + packageName + ", uid=" + Binder.getCallingUid());
2393         }
2394         return Integer.MAX_VALUE;
2395     }
2396 
2397     @Override
2398     @SuppressWarnings("unchecked")
getNeighboringCellInfo(String callingPackage, String callingFeatureId)2399     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage,
2400             String callingFeatureId) {
2401         final int targetSdk = getTargetSdk(callingPackage);
2402         if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
2403             throw new SecurityException(
2404                     "getNeighboringCellInfo() is unavailable to callers targeting Q+ SDK levels.");
2405         }
2406 
2407         if (mAppOps.noteOp(AppOpsManager.OPSTR_NEIGHBORING_CELLS, Binder.getCallingUid(),
2408                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
2409             return null;
2410         }
2411 
2412         if (DBG_LOC) log("getNeighboringCellInfo: is active user");
2413 
2414         List<CellInfo> info = getAllCellInfo(callingPackage, callingFeatureId);
2415         if (info == null) return null;
2416 
2417         List<NeighboringCellInfo> neighbors = new ArrayList<NeighboringCellInfo>();
2418         for (CellInfo ci : info) {
2419             if (ci instanceof CellInfoGsm) {
2420                 neighbors.add(new NeighboringCellInfo((CellInfoGsm) ci));
2421             } else if (ci instanceof CellInfoWcdma) {
2422                 neighbors.add(new NeighboringCellInfo((CellInfoWcdma) ci));
2423             }
2424         }
2425         return (neighbors.size()) > 0 ? neighbors : null;
2426     }
2427 
getCachedCellInfo()2428     private List<CellInfo> getCachedCellInfo() {
2429         List<CellInfo> cellInfos = new ArrayList<CellInfo>();
2430         for (Phone phone : PhoneFactory.getPhones()) {
2431             List<CellInfo> info = phone.getAllCellInfo();
2432             if (info != null) cellInfos.addAll(info);
2433         }
2434         return cellInfos;
2435     }
2436 
2437     @Override
getAllCellInfo(String callingPackage, String callingFeatureId)2438     public List<CellInfo> getAllCellInfo(String callingPackage, String callingFeatureId) {
2439         mApp.getSystemService(AppOpsManager.class)
2440                 .checkPackage(Binder.getCallingUid(), callingPackage);
2441 
2442         LocationAccessPolicy.LocationPermissionResult locationResult =
2443                 LocationAccessPolicy.checkLocationPermission(mApp,
2444                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
2445                                 .setCallingPackage(callingPackage)
2446                                 .setCallingFeatureId(callingFeatureId)
2447                                 .setCallingPid(Binder.getCallingPid())
2448                                 .setCallingUid(Binder.getCallingUid())
2449                                 .setMethod("getAllCellInfo")
2450                                 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
2451                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
2452                                 .build());
2453         switch (locationResult) {
2454             case DENIED_HARD:
2455                 throw new SecurityException("Not allowed to access cell info");
2456             case DENIED_SOFT:
2457                 return new ArrayList<>();
2458         }
2459 
2460         final int targetSdk = getTargetSdk(callingPackage);
2461         if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
2462             return getCachedCellInfo();
2463         }
2464 
2465         if (DBG_LOC) log("getAllCellInfo: is active user");
2466         WorkSource workSource = getWorkSource(Binder.getCallingUid());
2467         final long identity = Binder.clearCallingIdentity();
2468         try {
2469             List<CellInfo> cellInfos = new ArrayList<CellInfo>();
2470             for (Phone phone : PhoneFactory.getPhones()) {
2471                 final List<CellInfo> info = (List<CellInfo>) sendRequest(
2472                         CMD_GET_ALL_CELL_INFO, null, phone, workSource);
2473                 if (info != null) cellInfos.addAll(info);
2474             }
2475             return cellInfos;
2476         } finally {
2477             Binder.restoreCallingIdentity(identity);
2478         }
2479     }
2480 
2481     @Override
requestCellInfoUpdate(int subId, ICellInfoCallback cb, String callingPackage, String callingFeatureId)2482     public void requestCellInfoUpdate(int subId, ICellInfoCallback cb, String callingPackage,
2483             String callingFeatureId) {
2484         requestCellInfoUpdateInternal(subId, cb, callingPackage, callingFeatureId,
2485                 getWorkSource(Binder.getCallingUid()));
2486     }
2487 
2488     @Override
requestCellInfoUpdateWithWorkSource(int subId, ICellInfoCallback cb, String callingPackage, String callingFeatureId, WorkSource workSource)2489     public void requestCellInfoUpdateWithWorkSource(int subId, ICellInfoCallback cb,
2490             String callingPackage, String callingFeatureId, WorkSource workSource) {
2491         enforceModifyPermission();
2492         requestCellInfoUpdateInternal(subId, cb, callingPackage, callingFeatureId, workSource);
2493     }
2494 
requestCellInfoUpdateInternal(int subId, ICellInfoCallback cb, String callingPackage, String callingFeatureId, WorkSource workSource)2495     private void requestCellInfoUpdateInternal(int subId, ICellInfoCallback cb,
2496             String callingPackage, String callingFeatureId, WorkSource workSource) {
2497         mApp.getSystemService(AppOpsManager.class)
2498                 .checkPackage(Binder.getCallingUid(), callingPackage);
2499 
2500         LocationAccessPolicy.LocationPermissionResult locationResult =
2501                 LocationAccessPolicy.checkLocationPermission(mApp,
2502                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
2503                                 .setCallingPackage(callingPackage)
2504                                 .setCallingFeatureId(callingFeatureId)
2505                                 .setCallingPid(Binder.getCallingPid())
2506                                 .setCallingUid(Binder.getCallingUid())
2507                                 .setMethod("requestCellInfoUpdate")
2508                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
2509                                 .build());
2510         switch (locationResult) {
2511             case DENIED_HARD:
2512                 throw new SecurityException("Not allowed to access cell info");
2513             case DENIED_SOFT:
2514                 try {
2515                     cb.onCellInfo(new ArrayList<CellInfo>());
2516                 } catch (RemoteException re) {
2517                     // Drop without consequences
2518                 }
2519                 return;
2520         }
2521 
2522 
2523         final Phone phone = getPhoneFromSubId(subId);
2524         if (phone == null) throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
2525 
2526         sendRequestAsync(CMD_REQUEST_CELL_INFO_UPDATE, cb, phone, workSource);
2527     }
2528 
2529     @Override
setCellInfoListRate(int rateInMillis)2530     public void setCellInfoListRate(int rateInMillis) {
2531         enforceModifyPermission();
2532         WorkSource workSource = getWorkSource(Binder.getCallingUid());
2533 
2534         final long identity = Binder.clearCallingIdentity();
2535         try {
2536             getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
2537         } finally {
2538             Binder.restoreCallingIdentity(identity);
2539         }
2540     }
2541 
2542     @Override
getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId)2543     public String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
2544         Phone phone = PhoneFactory.getPhone(slotIndex);
2545         if (phone == null) {
2546             return null;
2547         }
2548         int subId = phone.getSubId();
2549         if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
2550                 callingPackage, callingFeatureId, "getImeiForSlot")) {
2551             return null;
2552         }
2553 
2554         final long identity = Binder.clearCallingIdentity();
2555         try {
2556             return phone.getImei();
2557         } finally {
2558             Binder.restoreCallingIdentity(identity);
2559         }
2560     }
2561 
2562     @Override
getTypeAllocationCodeForSlot(int slotIndex)2563     public String getTypeAllocationCodeForSlot(int slotIndex) {
2564         Phone phone = PhoneFactory.getPhone(slotIndex);
2565         String tac = null;
2566         if (phone != null) {
2567             String imei = phone.getImei();
2568             tac = imei == null ? null : imei.substring(0, TYPE_ALLOCATION_CODE_LENGTH);
2569         }
2570         return tac;
2571     }
2572 
2573     @Override
getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId)2574     public String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
2575         Phone phone = PhoneFactory.getPhone(slotIndex);
2576         if (phone == null) {
2577             return null;
2578         }
2579 
2580         int subId = phone.getSubId();
2581         if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
2582                 callingPackage, callingFeatureId, "getMeidForSlot")) {
2583             return null;
2584         }
2585 
2586         final long identity = Binder.clearCallingIdentity();
2587         try {
2588             return phone.getMeid();
2589         } finally {
2590             Binder.restoreCallingIdentity(identity);
2591         }
2592     }
2593 
2594     @Override
getManufacturerCodeForSlot(int slotIndex)2595     public String getManufacturerCodeForSlot(int slotIndex) {
2596         Phone phone = PhoneFactory.getPhone(slotIndex);
2597         String manufacturerCode = null;
2598         if (phone != null) {
2599             String meid = phone.getMeid();
2600             manufacturerCode = meid == null ? null : meid.substring(0, MANUFACTURER_CODE_LENGTH);
2601         }
2602         return manufacturerCode;
2603     }
2604 
2605     @Override
getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage, String callingFeatureId)2606     public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage,
2607             String callingFeatureId) {
2608         Phone phone = PhoneFactory.getPhone(slotIndex);
2609         if (phone == null) {
2610             return null;
2611         }
2612         int subId = phone.getSubId();
2613         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2614                 mApp, subId, callingPackage, callingFeatureId,
2615                 "getDeviceSoftwareVersionForSlot")) {
2616             return null;
2617         }
2618 
2619         final long identity = Binder.clearCallingIdentity();
2620         try {
2621             return phone.getDeviceSvn();
2622         } finally {
2623             Binder.restoreCallingIdentity(identity);
2624         }
2625     }
2626 
2627     @Override
getSubscriptionCarrierId(int subId)2628     public int getSubscriptionCarrierId(int subId) {
2629         final long identity = Binder.clearCallingIdentity();
2630         try {
2631             final Phone phone = getPhone(subId);
2632             return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID : phone.getCarrierId();
2633         } finally {
2634             Binder.restoreCallingIdentity(identity);
2635         }
2636     }
2637 
2638     @Override
getSubscriptionCarrierName(int subId)2639     public String getSubscriptionCarrierName(int subId) {
2640         final long identity = Binder.clearCallingIdentity();
2641         try {
2642             final Phone phone = getPhone(subId);
2643             return phone == null ? null : phone.getCarrierName();
2644         } finally {
2645             Binder.restoreCallingIdentity(identity);
2646         }
2647     }
2648 
2649     @Override
getSubscriptionSpecificCarrierId(int subId)2650     public int getSubscriptionSpecificCarrierId(int subId) {
2651         final long identity = Binder.clearCallingIdentity();
2652         try {
2653             final Phone phone = getPhone(subId);
2654             return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID
2655                     : phone.getSpecificCarrierId();
2656         } finally {
2657             Binder.restoreCallingIdentity(identity);
2658         }
2659     }
2660 
2661     @Override
getSubscriptionSpecificCarrierName(int subId)2662     public String getSubscriptionSpecificCarrierName(int subId) {
2663         final long identity = Binder.clearCallingIdentity();
2664         try {
2665             final Phone phone = getPhone(subId);
2666             return phone == null ? null : phone.getSpecificCarrierName();
2667         } finally {
2668             Binder.restoreCallingIdentity(identity);
2669         }
2670     }
2671 
2672     @Override
getCarrierIdFromMccMnc(int slotIndex, String mccmnc, boolean isSubscriptionMccMnc)2673     public int getCarrierIdFromMccMnc(int slotIndex, String mccmnc, boolean isSubscriptionMccMnc) {
2674         if (!isSubscriptionMccMnc) {
2675             enforceReadPrivilegedPermission("getCarrierIdFromMccMnc");
2676         }
2677         final Phone phone = PhoneFactory.getPhone(slotIndex);
2678         if (phone == null) {
2679             return TelephonyManager.UNKNOWN_CARRIER_ID;
2680         }
2681         final long identity = Binder.clearCallingIdentity();
2682         try {
2683             return CarrierResolver.getCarrierIdFromMccMnc(phone.getContext(), mccmnc);
2684         } finally {
2685             Binder.restoreCallingIdentity(identity);
2686         }
2687     }
2688 
2689     //
2690     // Internal helper methods.
2691     //
2692 
2693     /**
2694      * Make sure the caller has the MODIFY_PHONE_STATE permission.
2695      *
2696      * @throws SecurityException if the caller does not have the required permission
2697      */
enforceModifyPermission()2698     private void enforceModifyPermission() {
2699         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
2700     }
2701 
2702     /**
2703      * Make sure the caller is system.
2704      *
2705      * @throws SecurityException if the caller is not system.
2706      */
enforceSystemCaller()2707     private void enforceSystemCaller() {
2708         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
2709             throw new SecurityException("Caller must be system");
2710         }
2711     }
2712 
enforceActiveEmergencySessionPermission()2713     private void enforceActiveEmergencySessionPermission() {
2714         mApp.enforceCallingOrSelfPermission(
2715                 android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
2716     }
2717 
2718     /**
2719      * Make sure the caller has the CALL_PHONE permission.
2720      *
2721      * @throws SecurityException if the caller does not have the required permission
2722      */
enforceCallPermission()2723     private void enforceCallPermission() {
2724         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
2725     }
2726 
enforceSettingsPermission()2727     private void enforceSettingsPermission() {
2728         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, null);
2729     }
2730 
createTelUrl(String number)2731     private String createTelUrl(String number) {
2732         if (TextUtils.isEmpty(number)) {
2733             return null;
2734         }
2735 
2736         return "tel:" + number;
2737     }
2738 
log(String msg)2739     private static void log(String msg) {
2740         Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
2741     }
2742 
logv(String msg)2743     private static void logv(String msg) {
2744         Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
2745     }
2746 
loge(String msg)2747     private static void loge(String msg) {
2748         Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
2749     }
2750 
2751     @Override
getActivePhoneType()2752     public int getActivePhoneType() {
2753         return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
2754     }
2755 
2756     @Override
getActivePhoneTypeForSlot(int slotIndex)2757     public int getActivePhoneTypeForSlot(int slotIndex) {
2758         final long identity = Binder.clearCallingIdentity();
2759         try {
2760             final Phone phone = PhoneFactory.getPhone(slotIndex);
2761             if (phone == null) {
2762                 return PhoneConstants.PHONE_TYPE_NONE;
2763             } else {
2764                 return phone.getPhoneType();
2765             }
2766         } finally {
2767             Binder.restoreCallingIdentity(identity);
2768         }
2769     }
2770 
2771     /**
2772      * Returns the CDMA ERI icon index to display
2773      */
2774     @Override
getCdmaEriIconIndex(String callingPackage, String callingFeatureId)2775     public int getCdmaEriIconIndex(String callingPackage, String callingFeatureId) {
2776         return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage,
2777                 callingFeatureId);
2778     }
2779 
2780     @Override
getCdmaEriIconIndexForSubscriber(int subId, String callingPackage, String callingFeatureId)2781     public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage,
2782             String callingFeatureId) {
2783         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2784                 mApp, subId, callingPackage, callingFeatureId,
2785                 "getCdmaEriIconIndexForSubscriber")) {
2786             return -1;
2787         }
2788 
2789         final long identity = Binder.clearCallingIdentity();
2790         try {
2791             final Phone phone = getPhone(subId);
2792             if (phone != null) {
2793                 return phone.getCdmaEriIconIndex();
2794             } else {
2795                 return -1;
2796             }
2797         } finally {
2798             Binder.restoreCallingIdentity(identity);
2799         }
2800     }
2801 
2802     /**
2803      * Returns the CDMA ERI icon mode,
2804      * 0 - ON
2805      * 1 - FLASHING
2806      */
2807     @Override
getCdmaEriIconMode(String callingPackage, String callingFeatureId)2808     public int getCdmaEriIconMode(String callingPackage, String callingFeatureId) {
2809         return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage,
2810                 callingFeatureId);
2811     }
2812 
2813     @Override
getCdmaEriIconModeForSubscriber(int subId, String callingPackage, String callingFeatureId)2814     public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage,
2815             String callingFeatureId) {
2816         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2817                 mApp, subId, callingPackage, callingFeatureId,
2818                 "getCdmaEriIconModeForSubscriber")) {
2819             return -1;
2820         }
2821 
2822         final long identity = Binder.clearCallingIdentity();
2823         try {
2824             final Phone phone = getPhone(subId);
2825             if (phone != null) {
2826                 return phone.getCdmaEriIconMode();
2827             } else {
2828                 return -1;
2829             }
2830         } finally {
2831             Binder.restoreCallingIdentity(identity);
2832         }
2833     }
2834 
2835     /**
2836      * Returns the CDMA ERI text,
2837      */
2838     @Override
getCdmaEriText(String callingPackage, String callingFeatureId)2839     public String getCdmaEriText(String callingPackage, String callingFeatureId) {
2840         return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage,
2841                 callingFeatureId);
2842     }
2843 
2844     @Override
getCdmaEriTextForSubscriber(int subId, String callingPackage, String callingFeatureId)2845     public String getCdmaEriTextForSubscriber(int subId, String callingPackage,
2846             String callingFeatureId) {
2847         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2848                 mApp, subId, callingPackage, callingFeatureId,
2849                 "getCdmaEriIconTextForSubscriber")) {
2850             return null;
2851         }
2852 
2853         final long identity = Binder.clearCallingIdentity();
2854         try {
2855             final Phone phone = getPhone(subId);
2856             if (phone != null) {
2857                 return phone.getCdmaEriText();
2858             } else {
2859                 return null;
2860             }
2861         } finally {
2862             Binder.restoreCallingIdentity(identity);
2863         }
2864     }
2865 
2866     /**
2867      * Returns the CDMA MDN.
2868      */
2869     @Override
getCdmaMdn(int subId)2870     public String getCdmaMdn(int subId) {
2871         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
2872                 mApp, subId, "getCdmaMdn");
2873 
2874         final long identity = Binder.clearCallingIdentity();
2875         try {
2876             final Phone phone = getPhone(subId);
2877             if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
2878                 return phone.getLine1Number();
2879             } else {
2880                 loge("getCdmaMdn: no phone found. Invalid subId: " + subId);
2881                 return null;
2882             }
2883         } finally {
2884             Binder.restoreCallingIdentity(identity);
2885         }
2886     }
2887 
2888     /**
2889      * Returns the CDMA MIN.
2890      */
2891     @Override
getCdmaMin(int subId)2892     public String getCdmaMin(int subId) {
2893         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
2894                 mApp, subId, "getCdmaMin");
2895 
2896         final long identity = Binder.clearCallingIdentity();
2897         try {
2898             final Phone phone = getPhone(subId);
2899             if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
2900                 return phone.getCdmaMin();
2901             } else {
2902                 return null;
2903             }
2904         } finally {
2905             Binder.restoreCallingIdentity(identity);
2906         }
2907     }
2908 
2909     @Override
requestNumberVerification(PhoneNumberRange range, long timeoutMillis, INumberVerificationCallback callback, String callingPackage)2910     public void requestNumberVerification(PhoneNumberRange range, long timeoutMillis,
2911             INumberVerificationCallback callback, String callingPackage) {
2912         if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2913                 != PERMISSION_GRANTED) {
2914             throw new SecurityException("Caller must hold the MODIFY_PHONE_STATE permission");
2915         }
2916         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
2917 
2918         String authorizedPackage = NumberVerificationManager.getAuthorizedPackage(mApp);
2919         if (!TextUtils.equals(callingPackage, authorizedPackage)) {
2920             throw new SecurityException("Calling package must be configured in the device config");
2921         }
2922 
2923         if (range == null) {
2924             throw new NullPointerException("Range must be non-null");
2925         }
2926 
2927         timeoutMillis = Math.min(timeoutMillis,
2928                 TelephonyManager.getMaxNumberVerificationTimeoutMillis());
2929 
2930         NumberVerificationManager.getInstance().requestVerification(range, callback, timeoutMillis);
2931     }
2932 
2933     /**
2934      * Returns true if CDMA provisioning needs to run.
2935      */
needsOtaServiceProvisioning()2936     public boolean needsOtaServiceProvisioning() {
2937         final long identity = Binder.clearCallingIdentity();
2938         try {
2939             return getDefaultPhone().needsOtaServiceProvisioning();
2940         } finally {
2941             Binder.restoreCallingIdentity(identity);
2942         }
2943     }
2944 
2945     /**
2946      * Sets the voice mail number of a given subId.
2947      */
2948     @Override
setVoiceMailNumber(int subId, String alphaTag, String number)2949     public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
2950         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
2951                 mApp, subId, "setVoiceMailNumber");
2952 
2953         final long identity = Binder.clearCallingIdentity();
2954         try {
2955             Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
2956                     new Pair<String, String>(alphaTag, number), new Integer(subId));
2957             return success;
2958         } finally {
2959             Binder.restoreCallingIdentity(identity);
2960         }
2961     }
2962 
2963     @Override
getVisualVoicemailSettings(String callingPackage, int subId)2964     public Bundle getVisualVoicemailSettings(String callingPackage, int subId) {
2965         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
2966         TelecomManager tm = mApp.getSystemService(TelecomManager.class);
2967         String systemDialer = tm.getSystemDialerPackage();
2968         if (!TextUtils.equals(callingPackage, systemDialer)) {
2969             throw new SecurityException("caller must be system dialer");
2970         }
2971 
2972         final long identity = Binder.clearCallingIdentity();
2973         try {
2974             PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(subId);
2975             if (phoneAccountHandle == null) {
2976                 return null;
2977             }
2978             return VisualVoicemailSettingsUtil.dump(mApp, phoneAccountHandle);
2979         } finally {
2980             Binder.restoreCallingIdentity(identity);
2981         }
2982     }
2983 
2984     @Override
getVisualVoicemailPackageName(String callingPackage, String callingFeatureId, int subId)2985     public String getVisualVoicemailPackageName(String callingPackage, String callingFeatureId,
2986             int subId) {
2987         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
2988         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2989                 mApp, subId, callingPackage, callingFeatureId,
2990                 "getVisualVoicemailPackageName")) {
2991             return null;
2992         }
2993 
2994         final long identity = Binder.clearCallingIdentity();
2995         try {
2996             return RemoteVvmTaskManager.getRemotePackage(mApp, subId).getPackageName();
2997         } finally {
2998             Binder.restoreCallingIdentity(identity);
2999         }
3000     }
3001 
3002     @Override
enableVisualVoicemailSmsFilter(String callingPackage, int subId, VisualVoicemailSmsFilterSettings settings)3003     public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
3004             VisualVoicemailSmsFilterSettings settings) {
3005         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3006 
3007         final long identity = Binder.clearCallingIdentity();
3008         try {
3009             VisualVoicemailSmsFilterConfig.enableVisualVoicemailSmsFilter(
3010                     mApp, callingPackage, subId, settings);
3011         } finally {
3012             Binder.restoreCallingIdentity(identity);
3013         }
3014     }
3015 
3016     @Override
disableVisualVoicemailSmsFilter(String callingPackage, int subId)3017     public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
3018         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3019 
3020         final long identity = Binder.clearCallingIdentity();
3021         try {
3022             VisualVoicemailSmsFilterConfig.disableVisualVoicemailSmsFilter(
3023                     mApp, callingPackage, subId);
3024         } finally {
3025             Binder.restoreCallingIdentity(identity);
3026         }
3027     }
3028 
3029     @Override
getVisualVoicemailSmsFilterSettings( String callingPackage, int subId)3030     public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
3031             String callingPackage, int subId) {
3032         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3033 
3034         final long identity = Binder.clearCallingIdentity();
3035         try {
3036             return VisualVoicemailSmsFilterConfig.getVisualVoicemailSmsFilterSettings(
3037                     mApp, callingPackage, subId);
3038         } finally {
3039             Binder.restoreCallingIdentity(identity);
3040         }
3041     }
3042 
3043     @Override
getActiveVisualVoicemailSmsFilterSettings(int subId)3044     public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
3045         enforceReadPrivilegedPermission("getActiveVisualVoicemailSmsFilterSettings");
3046 
3047         final long identity = Binder.clearCallingIdentity();
3048         try {
3049             return VisualVoicemailSmsFilterConfig.getActiveVisualVoicemailSmsFilterSettings(
3050                     mApp, subId);
3051         } finally {
3052             Binder.restoreCallingIdentity(identity);
3053         }
3054     }
3055 
3056     @Override
sendVisualVoicemailSmsForSubscriber(String callingPackage, String callingAttributionTag, int subId, String number, int port, String text, PendingIntent sentIntent)3057     public void sendVisualVoicemailSmsForSubscriber(String callingPackage,
3058             String callingAttributionTag, int subId, String number, int port, String text,
3059             PendingIntent sentIntent) {
3060         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3061         enforceVisualVoicemailPackage(callingPackage, subId);
3062         enforceSendSmsPermission();
3063         SmsController smsController = PhoneFactory.getSmsController();
3064         smsController.sendVisualVoicemailSmsForSubscriber(callingPackage, callingAttributionTag,
3065                 subId, number, port, text, sentIntent);
3066     }
3067 
3068     /**
3069      * Sets the voice activation state of a given subId.
3070      */
3071     @Override
setVoiceActivationState(int subId, int activationState)3072     public void setVoiceActivationState(int subId, int activationState) {
3073         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3074                 mApp, subId, "setVoiceActivationState");
3075 
3076         final long identity = Binder.clearCallingIdentity();
3077         try {
3078             final Phone phone = getPhone(subId);
3079             if (phone != null) {
3080                 phone.setVoiceActivationState(activationState);
3081             } else {
3082                 loge("setVoiceActivationState fails with invalid subId: " + subId);
3083             }
3084         } finally {
3085             Binder.restoreCallingIdentity(identity);
3086         }
3087     }
3088 
3089     /**
3090      * Sets the data activation state of a given subId.
3091      */
3092     @Override
setDataActivationState(int subId, int activationState)3093     public void setDataActivationState(int subId, int activationState) {
3094         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3095                 mApp, subId, "setDataActivationState");
3096 
3097         final long identity = Binder.clearCallingIdentity();
3098         try {
3099             final Phone phone = getPhone(subId);
3100             if (phone != null) {
3101                 phone.setDataActivationState(activationState);
3102             } else {
3103                 loge("setDataActivationState fails with invalid subId: " + subId);
3104             }
3105         } finally {
3106             Binder.restoreCallingIdentity(identity);
3107         }
3108     }
3109 
3110     /**
3111      * Returns the voice activation state of a given subId.
3112      */
3113     @Override
getVoiceActivationState(int subId, String callingPackage)3114     public int getVoiceActivationState(int subId, String callingPackage) {
3115         enforceReadPrivilegedPermission("getVoiceActivationState");
3116 
3117         final Phone phone = getPhone(subId);
3118         final long identity = Binder.clearCallingIdentity();
3119         try {
3120             if (phone != null) {
3121                 return phone.getVoiceActivationState();
3122             } else {
3123                 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
3124             }
3125         } finally {
3126             Binder.restoreCallingIdentity(identity);
3127         }
3128     }
3129 
3130     /**
3131      * Returns the data activation state of a given subId.
3132      */
3133     @Override
getDataActivationState(int subId, String callingPackage)3134     public int getDataActivationState(int subId, String callingPackage) {
3135         enforceReadPrivilegedPermission("getDataActivationState");
3136 
3137         final Phone phone = getPhone(subId);
3138         final long identity = Binder.clearCallingIdentity();
3139         try {
3140             if (phone != null) {
3141                 return phone.getDataActivationState();
3142             } else {
3143                 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
3144             }
3145         } finally {
3146             Binder.restoreCallingIdentity(identity);
3147         }
3148     }
3149 
3150     /**
3151      * Returns the unread count of voicemails for a subId
3152      */
3153     @Override
getVoiceMessageCountForSubscriber(int subId, String callingPackage, String callingFeatureId)3154     public int getVoiceMessageCountForSubscriber(int subId, String callingPackage,
3155             String callingFeatureId) {
3156         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
3157                 mApp, subId, callingPackage, callingFeatureId,
3158                 "getVoiceMessageCountForSubscriber")) {
3159             return 0;
3160         }
3161         final long identity = Binder.clearCallingIdentity();
3162         try {
3163             final Phone phone = getPhone(subId);
3164             if (phone != null) {
3165                 return phone.getVoiceMessageCount();
3166             } else {
3167                 return 0;
3168             }
3169         } finally {
3170             Binder.restoreCallingIdentity(identity);
3171         }
3172     }
3173 
3174     /**
3175       * returns true, if the device is in a state where both voice and data
3176       * are supported simultaneously. This can change based on location or network condition.
3177      */
3178     @Override
isConcurrentVoiceAndDataAllowed(int subId)3179     public boolean isConcurrentVoiceAndDataAllowed(int subId) {
3180         final long identity = Binder.clearCallingIdentity();
3181         try {
3182             final Phone phone = getPhone(subId);
3183             return (phone == null ? false : phone.isConcurrentVoiceAndDataAllowed());
3184         } finally {
3185             Binder.restoreCallingIdentity(identity);
3186         }
3187     }
3188 
3189     /**
3190      * Send the dialer code if called from the current default dialer or the caller has
3191      * carrier privilege.
3192      * @param inputCode The dialer code to send
3193      */
3194     @Override
sendDialerSpecialCode(String callingPackage, String inputCode)3195     public void sendDialerSpecialCode(String callingPackage, String inputCode) {
3196         final Phone defaultPhone = getDefaultPhone();
3197         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3198         TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
3199         String defaultDialer = tm.getDefaultDialerPackage();
3200         if (!TextUtils.equals(callingPackage, defaultDialer)) {
3201             TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
3202                     getDefaultSubscription(), "sendDialerSpecialCode");
3203         }
3204 
3205         final long identity = Binder.clearCallingIdentity();
3206         try {
3207             defaultPhone.sendDialerSpecialCode(inputCode);
3208         } finally {
3209             Binder.restoreCallingIdentity(identity);
3210         }
3211     }
3212 
3213     @Override
getNetworkSelectionMode(int subId)3214     public int getNetworkSelectionMode(int subId) {
3215         TelephonyPermissions
3216                     .enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3217                     mApp, subId, "getNetworkSelectionMode");
3218         final long identity = Binder.clearCallingIdentity();
3219         try {
3220             if (!isActiveSubscription(subId)) {
3221                 return TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
3222             }
3223             return (int) sendRequest(CMD_GET_NETWORK_SELECTION_MODE, null /* argument */, subId);
3224         } finally {
3225             Binder.restoreCallingIdentity(identity);
3226         }
3227     }
3228 
3229     @Override
isInEmergencySmsMode()3230     public boolean isInEmergencySmsMode() {
3231         enforceReadPrivilegedPermission("isInEmergencySmsMode");
3232         final long identity = Binder.clearCallingIdentity();
3233         try {
3234             for (Phone phone : PhoneFactory.getPhones()) {
3235                 if (phone.isInEmergencySmsMode()) {
3236                     return true;
3237                 }
3238             }
3239         } finally {
3240             Binder.restoreCallingIdentity(identity);
3241         }
3242         return false;
3243     }
3244 
3245     /**
3246      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3247      * @param subId The subscription to use to check the configuration.
3248      * @param c The callback that will be used to send the result.
3249      */
3250     @Override
registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)3251     public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
3252             throws RemoteException {
3253         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3254                 mApp, subId, "registerImsRegistrationCallback");
3255 
3256         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
3257             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
3258                     "IMS not available on device.");
3259         }
3260         final long token = Binder.clearCallingIdentity();
3261         try {
3262             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3263             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
3264                     .addRegistrationCallbackForSubscription(c, subId);
3265         } catch (ImsException e) {
3266             throw new ServiceSpecificException(e.getCode());
3267         } finally {
3268             Binder.restoreCallingIdentity(token);
3269         }
3270     }
3271 
3272     /**
3273      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3274      * @param subId The subscription to use to check the configuration.
3275      * @param c The callback that will be used to send the result.
3276      */
3277     @Override
unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c)3278     public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c) {
3279         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3280                 mApp, subId, "unregisterImsRegistrationCallback");
3281         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3282             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
3283         }
3284         final long token = Binder.clearCallingIdentity();
3285         try {
3286             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone.
3287             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
3288                     .removeRegistrationCallbackForSubscription(c, subId);
3289         } catch (ImsException e) {
3290             Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
3291                     + "is inactive, ignoring unregister.");
3292             // If the subscription is no longer active, just return, since the callback
3293             // will already have been removed internally.
3294         } finally {
3295             Binder.restoreCallingIdentity(token);
3296         }
3297     }
3298 
3299     /**
3300      * Get the IMS service registration state for the MmTelFeature associated with this sub id.
3301      */
3302     @Override
getImsMmTelRegistrationState(int subId, IIntegerConsumer consumer)3303     public void getImsMmTelRegistrationState(int subId, IIntegerConsumer consumer) {
3304         enforceReadPrivilegedPermission("getImsMmTelRegistrationState");
3305         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
3306             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
3307                     "IMS not available on device.");
3308         }
3309         final long token = Binder.clearCallingIdentity();
3310         try {
3311             Phone phone = getPhone(subId);
3312             if (phone == null) {
3313                 Log.w(LOG_TAG, "getImsMmTelRegistrationState: called with an invalid subscription '"
3314                         + subId + "'");
3315                 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
3316             }
3317             phone.getImsRegistrationState(regState -> {
3318                 try {
3319                     consumer.accept((regState == null)
3320                             ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
3321                 } catch (RemoteException e) {
3322                     // Ignore if the remote process is no longer available to call back.
3323                     Log.w(LOG_TAG, "getImsMmTelRegistrationState: callback not available.");
3324                 }
3325             });
3326         } finally {
3327             Binder.restoreCallingIdentity(token);
3328         }
3329     }
3330 
3331     /**
3332      * Get the transport type for the IMS service registration state.
3333      */
3334     @Override
getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer)3335     public void getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer) {
3336         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3337                 mApp, subId, "getImsMmTelRegistrationTransportType");
3338         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
3339             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
3340                     "IMS not available on device.");
3341         }
3342         final long token = Binder.clearCallingIdentity();
3343         try {
3344             Phone phone = getPhone(subId);
3345             if (phone == null) {
3346                 Log.w(LOG_TAG, "getImsMmTelRegistrationState: called with an invalid subscription '"
3347                         + subId + "'");
3348                 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
3349             }
3350             phone.getImsRegistrationTech(regTech -> {
3351                 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
3352                 int regTechConverted = (regTech == null)
3353                         ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
3354                 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
3355                         regTechConverted);
3356                 try {
3357                     consumer.accept(regTechConverted);
3358                 } catch (RemoteException e) {
3359                     // Ignore if the remote process is no longer available to call back.
3360                     Log.w(LOG_TAG, "getImsMmTelRegistrationState: callback not available.");
3361                 }
3362             });
3363         } finally {
3364             Binder.restoreCallingIdentity(token);
3365         }
3366     }
3367 
3368     /**
3369      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3370      * @param subId The subscription to use to check the configuration.
3371      * @param c The callback that will be used to send the result.
3372      */
3373     @Override
registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)3374     public void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)
3375             throws RemoteException {
3376         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3377                 mApp, subId, "registerMmTelCapabilityCallback");
3378         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
3379             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
3380                     "IMS not available on device.");
3381         }
3382         // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3383         final long token = Binder.clearCallingIdentity();
3384         try {
3385             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
3386                     .addCapabilitiesCallbackForSubscription(c, subId);
3387         } catch (ImsException e) {
3388             throw new ServiceSpecificException(e.getCode());
3389         } finally {
3390             Binder.restoreCallingIdentity(token);
3391         }
3392     }
3393 
3394     /**
3395      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3396      * @param subId The subscription to use to check the configuration.
3397      * @param c The callback that will be used to send the result.
3398      */
3399     @Override
unregisterMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)3400     public void unregisterMmTelCapabilityCallback(int subId, IImsCapabilityCallback c) {
3401         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3402                 mApp, subId, "unregisterMmTelCapabilityCallback");
3403         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3404             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
3405         }
3406 
3407         final long token = Binder.clearCallingIdentity();
3408         try {
3409             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone.
3410             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
3411                         .removeCapabilitiesCallbackForSubscription(c, subId);
3412         } catch (ImsException e) {
3413             Log.i(LOG_TAG, "unregisterMmTelCapabilityCallback: " + subId
3414                      + "is inactive, ignoring unregister.");
3415              // If the subscription is no longer active, just return, since the callback
3416              // will already have been removed internally.
3417         } finally {
3418             Binder.restoreCallingIdentity(token);
3419         }
3420     }
3421 
3422     @Override
isCapable(int subId, int capability, int regTech)3423     public boolean isCapable(int subId, int capability, int regTech) {
3424         enforceReadPrivilegedPermission("isCapable");
3425         // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3426         final long token = Binder.clearCallingIdentity();
3427         try {
3428             return ImsManager.getInstance(mApp,
3429                     getSlotIndexOrException(subId)).queryMmTelCapability(capability, regTech);
3430         } catch (com.android.ims.ImsException e) {
3431             Log.w(LOG_TAG, "IMS isCapable - service unavailable: " + e.getMessage());
3432             return false;
3433         } catch (ImsException e) {
3434             Log.i(LOG_TAG, "isCapable: " + subId + " is inactive, returning false.");
3435             return false;
3436         } finally {
3437             Binder.restoreCallingIdentity(token);
3438         }
3439     }
3440 
3441     @Override
isAvailable(int subId, int capability, int regTech)3442     public boolean isAvailable(int subId, int capability, int regTech) {
3443         enforceReadPrivilegedPermission("isAvailable");
3444         final long token = Binder.clearCallingIdentity();
3445         try {
3446             Phone phone = getPhone(subId);
3447             if (phone == null) return false;
3448             return phone.isImsCapabilityAvailable(capability, regTech);
3449         } catch (com.android.ims.ImsException e) {
3450             Log.w(LOG_TAG, "IMS isAvailable - service unavailable: " + e.getMessage());
3451             return false;
3452         } finally {
3453             Binder.restoreCallingIdentity(token);
3454         }
3455     }
3456 
3457     /**
3458      * Determines if the MmTel feature capability is supported by the carrier configuration for this
3459      * subscription.
3460      * @param subId The subscription to use to check the configuration.
3461      * @param callback The callback that will be used to send the result.
3462      * @param capability The MmTelFeature capability that will be used to send the result.
3463      * @param transportType The transport type of the MmTelFeature capability.
3464      */
3465     @Override
isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability, int transportType)3466     public void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability,
3467             int transportType) {
3468         enforceReadPrivilegedPermission("isMmTelCapabilitySupported");
3469         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
3470             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
3471                     "IMS not available on device.");
3472         }
3473         final long token = Binder.clearCallingIdentity();
3474         try {
3475             int slotId = getSlotIndex(subId);
3476             if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
3477                 Log.w(LOG_TAG, "isMmTelCapabilitySupported: called with an inactive subscription '"
3478                         + subId + "'");
3479                 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
3480             }
3481             ImsManager.getInstance(mApp, slotId).isSupported(capability,
3482                     transportType, aBoolean -> {
3483                         try {
3484                             callback.accept((aBoolean == null) ? 0 : (aBoolean ? 1 : 0));
3485                         } catch (RemoteException e) {
3486                             Log.w(LOG_TAG, "isMmTelCapabilitySupported: remote caller is not "
3487                                     + "running. Ignore");
3488                         }
3489                     });
3490         } finally {
3491             Binder.restoreCallingIdentity(token);
3492         }
3493     }
3494 
3495     /**
3496      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3497      * @param subId The subscription to use to check the configuration.
3498      */
3499     @Override
isAdvancedCallingSettingEnabled(int subId)3500     public boolean isAdvancedCallingSettingEnabled(int subId) {
3501         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3502                 mApp, subId, "isAdvancedCallingSettingEnabled");
3503 
3504         // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3505         final long token = Binder.clearCallingIdentity();
3506         try {
3507             return ImsManager.getInstance(mApp,
3508                     getSlotIndexOrException(subId)).isEnhanced4gLteModeSettingEnabledByUser();
3509         } catch (ImsException e) {
3510             throw new ServiceSpecificException(e.getCode());
3511         } finally {
3512             Binder.restoreCallingIdentity(token);
3513         }
3514     }
3515 
3516     @Override
setAdvancedCallingSettingEnabled(int subId, boolean isEnabled)3517     public void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled) {
3518         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3519                 "setAdvancedCallingSettingEnabled");
3520         final long identity = Binder.clearCallingIdentity();
3521         try {
3522             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3523             ImsManager.getInstance(mApp,
3524                     getSlotIndexOrException(subId)).setEnhanced4gLteModeSetting(isEnabled);
3525         } catch (ImsException e) {
3526             throw new ServiceSpecificException(e.getCode());
3527         } finally {
3528             Binder.restoreCallingIdentity(identity);
3529         }
3530     }
3531 
3532     /**
3533      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3534      * @param subId The subscription to use to check the configuration.
3535      */
3536     @Override
isVtSettingEnabled(int subId)3537     public boolean isVtSettingEnabled(int subId) {
3538         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3539                 mApp, subId, "isVtSettingEnabled");
3540         final long identity = Binder.clearCallingIdentity();
3541         try {
3542             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3543             return ImsManager.getInstance(mApp, getSlotIndexOrException(subId)).isVtEnabledByUser();
3544         } catch (ImsException e) {
3545             throw new ServiceSpecificException(e.getCode());
3546         } finally {
3547             Binder.restoreCallingIdentity(identity);
3548         }
3549     }
3550 
3551     @Override
setVtSettingEnabled(int subId, boolean isEnabled)3552     public void setVtSettingEnabled(int subId, boolean isEnabled) {
3553         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3554                 "setVtSettingEnabled");
3555         final long identity = Binder.clearCallingIdentity();
3556         try {
3557             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3558             ImsManager.getInstance(mApp, getSlotIndexOrException(subId)).setVtSetting(isEnabled);
3559         } catch (ImsException e) {
3560             throw new ServiceSpecificException(e.getCode());
3561         } finally {
3562             Binder.restoreCallingIdentity(identity);
3563         }
3564     }
3565 
3566     /**
3567      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3568      * @param subId The subscription to use to check the configuration.
3569      */
3570     @Override
isVoWiFiSettingEnabled(int subId)3571     public boolean isVoWiFiSettingEnabled(int subId) {
3572         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3573                 mApp, subId, "isVoWiFiSettingEnabled");
3574         final long identity = Binder.clearCallingIdentity();
3575         try {
3576             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3577             return ImsManager.getInstance(mApp,
3578                     getSlotIndexOrException(subId)).isWfcEnabledByUser();
3579         } catch (ImsException e) {
3580             throw new ServiceSpecificException(e.getCode());
3581         } finally {
3582             Binder.restoreCallingIdentity(identity);
3583         }
3584     }
3585 
3586     @Override
setVoWiFiSettingEnabled(int subId, boolean isEnabled)3587     public void setVoWiFiSettingEnabled(int subId, boolean isEnabled) {
3588         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3589                 "setVoWiFiSettingEnabled");
3590         final long identity = Binder.clearCallingIdentity();
3591         try {
3592             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3593             ImsManager.getInstance(mApp, getSlotIndexOrException(subId)).setWfcSetting(isEnabled);
3594         } catch (ImsException e) {
3595             throw new ServiceSpecificException(e.getCode());
3596         } finally {
3597             Binder.restoreCallingIdentity(identity);
3598         }
3599     }
3600 
3601     /**
3602      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3603      * @param subId The subscription to use to check the configuration.
3604      */
3605     @Override
isVoWiFiRoamingSettingEnabled(int subId)3606     public boolean isVoWiFiRoamingSettingEnabled(int subId) {
3607         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3608                 mApp, subId, "isVoWiFiRoamingSettingEnabled");
3609         final long identity = Binder.clearCallingIdentity();
3610         try {
3611             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3612             return ImsManager.getInstance(mApp,
3613                     getSlotIndexOrException(subId)).isWfcRoamingEnabledByUser();
3614         } catch (ImsException e) {
3615             throw new ServiceSpecificException(e.getCode());
3616         } finally {
3617             Binder.restoreCallingIdentity(identity);
3618         }
3619     }
3620 
3621     @Override
setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled)3622     public void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled) {
3623         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3624                 "setVoWiFiRoamingSettingEnabled");
3625         final long identity = Binder.clearCallingIdentity();
3626         try {
3627             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3628             ImsManager.getInstance(mApp,
3629                     getSlotIndexOrException(subId)).setWfcRoamingSetting(isEnabled);
3630         } catch (ImsException e) {
3631             throw new ServiceSpecificException(e.getCode());
3632         } finally {
3633             Binder.restoreCallingIdentity(identity);
3634         }
3635     }
3636 
3637     @Override
setVoWiFiNonPersistent(int subId, boolean isCapable, int mode)3638     public void setVoWiFiNonPersistent(int subId, boolean isCapable, int mode) {
3639         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3640                 "setVoWiFiNonPersistent");
3641         final long identity = Binder.clearCallingIdentity();
3642         try {
3643             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3644             ImsManager.getInstance(mApp,
3645                     getSlotIndexOrException(subId)).setWfcNonPersistent(isCapable, mode);
3646         } catch (ImsException e) {
3647             throw new ServiceSpecificException(e.getCode());
3648         } finally {
3649             Binder.restoreCallingIdentity(identity);
3650         }
3651     }
3652 
3653     /**
3654      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3655      * @param subId The subscription to use to check the configuration.
3656      */
3657     @Override
getVoWiFiModeSetting(int subId)3658     public int getVoWiFiModeSetting(int subId) {
3659         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3660                 mApp, subId, "getVoWiFiModeSetting");
3661         final long identity = Binder.clearCallingIdentity();
3662         try {
3663             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3664             return ImsManager.getInstance(mApp,
3665                     getSlotIndexOrException(subId)).getWfcMode(false /*isRoaming*/);
3666         } catch (ImsException e) {
3667             throw new ServiceSpecificException(e.getCode());
3668         } finally {
3669             Binder.restoreCallingIdentity(identity);
3670         }
3671     }
3672 
3673     @Override
setVoWiFiModeSetting(int subId, int mode)3674     public void setVoWiFiModeSetting(int subId, int mode) {
3675         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3676                 "setVoWiFiModeSetting");
3677         final long identity = Binder.clearCallingIdentity();
3678         try {
3679             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3680             ImsManager.getInstance(mApp,
3681                     getSlotIndexOrException(subId)).setWfcMode(mode, false /*isRoaming*/);
3682         } catch (ImsException e) {
3683             throw new ServiceSpecificException(e.getCode());
3684         } finally {
3685             Binder.restoreCallingIdentity(identity);
3686         }
3687     }
3688 
3689     @Override
getVoWiFiRoamingModeSetting(int subId)3690     public int getVoWiFiRoamingModeSetting(int subId) {
3691         enforceReadPrivilegedPermission("getVoWiFiRoamingModeSetting");
3692         final long identity = Binder.clearCallingIdentity();
3693         try {
3694             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3695             return ImsManager.getInstance(mApp,
3696                     getSlotIndexOrException(subId)).getWfcMode(true /*isRoaming*/);
3697         } catch (ImsException e) {
3698             throw new ServiceSpecificException(e.getCode());
3699         } finally {
3700             Binder.restoreCallingIdentity(identity);
3701         }
3702     }
3703 
3704     @Override
setVoWiFiRoamingModeSetting(int subId, int mode)3705     public void setVoWiFiRoamingModeSetting(int subId, int mode) {
3706         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3707                 "setVoWiFiRoamingModeSetting");
3708         final long identity = Binder.clearCallingIdentity();
3709         try {
3710             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3711             ImsManager.getInstance(mApp,
3712                     getSlotIndexOrException(subId)).setWfcMode(mode, true /*isRoaming*/);
3713         } catch (ImsException e) {
3714             throw new ServiceSpecificException(e.getCode());
3715         } finally {
3716             Binder.restoreCallingIdentity(identity);
3717         }
3718     }
3719 
3720     @Override
setRttCapabilitySetting(int subId, boolean isEnabled)3721     public void setRttCapabilitySetting(int subId, boolean isEnabled) {
3722         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3723                 "setRttCapabilityEnabled");
3724         final long identity = Binder.clearCallingIdentity();
3725         try {
3726             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3727             ImsManager.getInstance(mApp, getSlotIndexOrException(subId)).setRttEnabled(isEnabled);
3728         } catch (ImsException e) {
3729             throw new ServiceSpecificException(e.getCode());
3730         } finally {
3731             Binder.restoreCallingIdentity(identity);
3732         }
3733     }
3734 
3735     /**
3736      * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
3737      * @param subId The subscription to use to check the configuration.
3738      */
3739     @Override
isTtyOverVolteEnabled(int subId)3740     public boolean isTtyOverVolteEnabled(int subId) {
3741         TelephonyPermissions.enforeceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
3742                 mApp, subId, "isTtyOverVolteEnabled");
3743         final long identity = Binder.clearCallingIdentity();
3744         try {
3745             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3746             return ImsManager.getInstance(mApp,
3747                     getSlotIndexOrException(subId)).isTtyOnVoLteCapable();
3748         } catch (ImsException e) {
3749             throw new ServiceSpecificException(e.getCode());
3750         } finally {
3751             Binder.restoreCallingIdentity(identity);
3752         }
3753     }
3754 
3755     @Override
registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback)3756     public void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
3757         enforceReadPrivilegedPermission("registerImsProvisioningChangedCallback");
3758         final long identity = Binder.clearCallingIdentity();
3759         try {
3760             if (!isImsAvailableOnDevice()) {
3761                 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
3762                         "IMS not available on device.");
3763             }
3764             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3765             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
3766                     .addProvisioningCallbackForSubscription(callback, subId);
3767         } catch (ImsException e) {
3768             throw new ServiceSpecificException(e.getCode());
3769         } finally {
3770             Binder.restoreCallingIdentity(identity);
3771         }
3772     }
3773 
3774     @Override
unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback)3775     public void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
3776         enforceReadPrivilegedPermission("unregisterImsProvisioningChangedCallback");
3777         final long identity = Binder.clearCallingIdentity();
3778         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3779             throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
3780         }
3781         try {
3782             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3783             ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
3784                     .removeProvisioningCallbackForSubscription(callback, subId);
3785         } catch (ImsException e) {
3786             Log.i(LOG_TAG, "unregisterImsProvisioningChangedCallback: " + subId
3787                     + "is inactive, ignoring unregister.");
3788             // If the subscription is no longer active, just return, since the callback will already
3789             // have been removed internally.
3790         } finally {
3791             Binder.restoreCallingIdentity(identity);
3792         }
3793     }
3794 
3795 
checkModifyPhoneStatePermission(int subId, String message)3796     private void checkModifyPhoneStatePermission(int subId, String message) {
3797         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3798                 message);
3799     }
3800 
isImsProvisioningRequired(int subId, int capability, boolean isMmtelCapability)3801     private boolean isImsProvisioningRequired(int subId, int capability,
3802             boolean isMmtelCapability) {
3803         Phone phone = getPhone(subId);
3804         if (phone == null) {
3805             loge("phone instance null for subid " + subId);
3806             return false;
3807         }
3808         if (isMmtelCapability) {
3809             if (!doesImsCapabilityRequireProvisioning(phone.getContext(), subId, capability)) {
3810                 return false;
3811             }
3812         } else {
3813             if (!doesRcsCapabilityRequireProvisioning(phone.getContext(), subId, capability)) {
3814                 return false;
3815             }
3816         }
3817         return true;
3818     }
3819 
3820     @Override
setRcsProvisioningStatusForCapability(int subId, int capability, boolean isProvisioned)3821     public void setRcsProvisioningStatusForCapability(int subId, int capability,
3822             boolean isProvisioned) {
3823         checkModifyPhoneStatePermission(subId, "setRcsProvisioningStatusForCapability");
3824 
3825         final long identity = Binder.clearCallingIdentity();
3826         try {
3827             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3828             if (!isImsProvisioningRequired(subId, capability, false)) {
3829                 return;
3830             }
3831 
3832             // this capability requires provisioning, route to the correct API.
3833             ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
3834             switch (capability) {
3835                 case RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE:
3836                 case RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE:
3837                     ims.setEabProvisioned(isProvisioned);
3838                     break;
3839                 default: {
3840                     throw new IllegalArgumentException("Tried to set provisioning for "
3841                             + "rcs capability '" + capability + "', which does not require "
3842                             + "provisioning.");
3843                 }
3844             }
3845         } finally {
3846             Binder.restoreCallingIdentity(identity);
3847         }
3848 
3849     }
3850 
3851 
3852     @Override
getRcsProvisioningStatusForCapability(int subId, int capability)3853     public boolean getRcsProvisioningStatusForCapability(int subId, int capability) {
3854         enforceReadPrivilegedPermission("getRcsProvisioningStatusForCapability");
3855         final long identity = Binder.clearCallingIdentity();
3856         try {
3857             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3858             if (!isImsProvisioningRequired(subId, capability, false)) {
3859                 return true;
3860             }
3861 
3862             ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
3863             switch (capability) {
3864                 case RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE:
3865                 case RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE:
3866                     return ims.isEabProvisionedOnDevice();
3867 
3868                 default: {
3869                     throw new IllegalArgumentException("Tried to get rcs provisioning for "
3870                             + "capability '" + capability + "', which does not require "
3871                             + "provisioning.");
3872                 }
3873             }
3874 
3875         } finally {
3876             Binder.restoreCallingIdentity(identity);
3877         }
3878     }
3879 
3880     @Override
setImsProvisioningStatusForCapability(int subId, int capability, int tech, boolean isProvisioned)3881     public void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
3882             boolean isProvisioned) {
3883         if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3884                 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3885             throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3886         }
3887         checkModifyPhoneStatePermission(subId, "setImsProvisioningStatusForCapability");
3888         final long identity = Binder.clearCallingIdentity();
3889         try {
3890             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3891             if (!isImsProvisioningRequired(subId, capability, true)) {
3892                 return;
3893             }
3894 
3895             // this capability requires provisioning, route to the correct API.
3896             ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
3897             switch (capability) {
3898                 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE: {
3899                     if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3900                         ims.setVolteProvisioned(isProvisioned);
3901                     } else if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
3902                         ims.setWfcProvisioned(isProvisioned);
3903                     }
3904                     break;
3905                 }
3906                 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
3907                     // There is currently no difference in VT provisioning type.
3908                     ims.setVtProvisioned(isProvisioned);
3909                     break;
3910                 }
3911                 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
3912                     // There is no "deprecated" UT provisioning mechanism through ImsConfig, so
3913                     // change the capability of the feature instead if needed.
3914                     if (isMmTelCapabilityProvisionedInCache(subId, capability, tech)
3915                             == isProvisioned) {
3916                         // No change in provisioning.
3917                         return;
3918                     }
3919                     cacheMmTelCapabilityProvisioning(subId, capability, tech, isProvisioned);
3920                     try {
3921                         ims.changeMmTelCapability(capability, tech, isProvisioned);
3922                     } catch (com.android.ims.ImsException e) {
3923                         loge("setImsProvisioningStatusForCapability: couldn't change UT capability"
3924                                 + ", Exception" + e.getMessage());
3925                     }
3926                     break;
3927                 }
3928                 default: {
3929                     throw new IllegalArgumentException("Tried to set provisioning for "
3930                             + "MmTel capability '" + capability + "', which does not require "
3931                             + "provisioning. ");
3932                 }
3933             }
3934 
3935         } finally {
3936             Binder.restoreCallingIdentity(identity);
3937         }
3938     }
3939 
3940     @Override
getImsProvisioningStatusForCapability(int subId, int capability, int tech)3941     public boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech) {
3942         if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3943                 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3944             throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3945         }
3946         enforceReadPrivilegedPermission("getProvisioningStatusForCapability");
3947         final long identity = Binder.clearCallingIdentity();
3948         try {
3949             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3950             if (!isImsProvisioningRequired(subId, capability, true)) {
3951                 return true;
3952             }
3953 
3954             ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
3955             switch (capability) {
3956                 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE: {
3957                     if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3958                         return ims.isVolteProvisionedOnDevice();
3959                     } else if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
3960                         return ims.isWfcProvisionedOnDevice();
3961                     }
3962                     // This should never happen, since we are checking tech above to make sure it
3963                     // is either LTE or IWLAN.
3964                     throw new IllegalArgumentException("Invalid radio technology for voice "
3965                             + "capability.");
3966                 }
3967                 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
3968                     // There is currently no difference in VT provisioning type.
3969                     return ims.isVtProvisionedOnDevice();
3970                 }
3971                 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
3972                     // There is no "deprecated" UT provisioning mechanism, so get from shared prefs.
3973                     return isMmTelCapabilityProvisionedInCache(subId, capability, tech);
3974                 }
3975                 default: {
3976                     throw new IllegalArgumentException(
3977                             "Tried to get provisioning for MmTel capability '" + capability
3978                                     + "', which does not require provisioning.");
3979                 }
3980             }
3981 
3982         } finally {
3983             Binder.restoreCallingIdentity(identity);
3984         }
3985     }
3986 
3987     @Override
isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech)3988     public boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech) {
3989         if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3990                 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3991             throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3992         }
3993         enforceReadPrivilegedPermission("isMmTelCapabilityProvisionedInCache");
3994         int provisionedBits = getMmTelCapabilityProvisioningBitfield(subId, tech);
3995         return (provisionedBits & capability) > 0;
3996     }
3997 
3998     @Override
cacheMmTelCapabilityProvisioning(int subId, int capability, int tech, boolean isProvisioned)3999     public void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech,
4000             boolean isProvisioned) {
4001         if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
4002                 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
4003             throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
4004         }
4005         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
4006                 "setProvisioningStatusForCapability");
4007         int provisionedBits = getMmTelCapabilityProvisioningBitfield(subId, tech);
4008         // If the current provisioning status for capability already matches isProvisioned,
4009         // do nothing.
4010         if (((provisionedBits & capability) > 0) == isProvisioned) {
4011             return;
4012         }
4013         if (isProvisioned) {
4014             setMmTelCapabilityProvisioningBitfield(subId, tech, (provisionedBits | capability));
4015         } else {
4016             setMmTelCapabilityProvisioningBitfield(subId, tech, (provisionedBits & ~capability));
4017         }
4018     }
4019 
4020     /**
4021      * @return the bitfield containing the MmTel provisioning for the provided subscription and
4022      * technology. The bitfield should mirror the bitfield defined by
4023      * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}.
4024      */
getMmTelCapabilityProvisioningBitfield(int subId, int tech)4025     private int getMmTelCapabilityProvisioningBitfield(int subId, int tech) {
4026         String key = getMmTelProvisioningKey(subId, tech);
4027         // Default is no capabilities are provisioned.
4028         return mTelephonySharedPreferences.getInt(key, 0 /*default*/);
4029     }
4030 
4031     /**
4032      * Sets the MmTel capability provisioning bitfield (defined by
4033      *     {@link MmTelFeature.MmTelCapabilities.MmTelCapability}) for the subscription and
4034      *     technology specified.
4035      *
4036      * Note: This is a synchronous command and should not be called on UI thread.
4037      */
setMmTelCapabilityProvisioningBitfield(int subId, int tech, int newField)4038     private void setMmTelCapabilityProvisioningBitfield(int subId, int tech, int newField) {
4039         final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
4040         String key = getMmTelProvisioningKey(subId, tech);
4041         editor.putInt(key, newField);
4042         editor.commit();
4043     }
4044 
getMmTelProvisioningKey(int subId, int tech)4045     private static String getMmTelProvisioningKey(int subId, int tech) {
4046         // resulting key is provision_ims_mmtel_{subId}_{tech}
4047         return PREF_PROVISION_IMS_MMTEL_PREFIX + subId + "_" + tech;
4048     }
4049 
4050     /**
4051      * Query CarrierConfig to see if the specified capability requires provisioning for the
4052      * carrier associated with the subscription id.
4053      */
doesImsCapabilityRequireProvisioning(Context context, int subId, int capability)4054     private boolean doesImsCapabilityRequireProvisioning(Context context, int subId,
4055             int capability) {
4056         CarrierConfigManager configManager = new CarrierConfigManager(context);
4057         PersistableBundle c = configManager.getConfigForSubId(subId);
4058         boolean requireUtProvisioning = c.getBoolean(
4059                 CarrierConfigManager.KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, false)
4060                 && c.getBoolean(CarrierConfigManager.KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL,
4061                 false);
4062         boolean requireVoiceVtProvisioning = c.getBoolean(
4063                 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
4064 
4065         // First check to make sure that the capability requires provisioning.
4066         switch (capability) {
4067             case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE:
4068                 // intentional fallthrough
4069             case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
4070                 if (requireVoiceVtProvisioning) {
4071                     // Voice and Video requires provisioning
4072                     return true;
4073                 }
4074                 break;
4075             }
4076             case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
4077                 if (requireUtProvisioning) {
4078                     // UT requires provisioning
4079                     return true;
4080                 }
4081                 break;
4082             }
4083         }
4084         return false;
4085     }
4086 
doesRcsCapabilityRequireProvisioning(Context context, int subId, int capability)4087     private boolean doesRcsCapabilityRequireProvisioning(Context context, int subId,
4088             int capability) {
4089         CarrierConfigManager configManager = new CarrierConfigManager(context);
4090         PersistableBundle c = configManager.getConfigForSubId(subId);
4091 
4092         boolean requireRcsProvisioning = c.getBoolean(
4093                 CarrierConfigManager.KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL, false);
4094 
4095         // First check to make sure that the capability requires provisioning.
4096         switch (capability) {
4097             case RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE:
4098                 // intentional fallthrough
4099             case RcsFeature.RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE: {
4100                 if (requireRcsProvisioning) {
4101                     // OPTION or PRESENCE requires provisioning
4102                     return true;
4103                 }
4104                 break;
4105             }
4106         }
4107         return false;
4108     }
4109 
4110     @Override
getImsProvisioningInt(int subId, int key)4111     public int getImsProvisioningInt(int subId, int key) {
4112         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
4113             throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
4114         }
4115         enforceReadPrivilegedPermission("getImsProvisioningInt");
4116         final long identity = Binder.clearCallingIdentity();
4117         try {
4118             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
4119             int slotId = getSlotIndex(subId);
4120             if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
4121                 Log.w(LOG_TAG, "getImsProvisioningInt: called with an inactive subscription '"
4122                         + subId + "' for key:" + key);
4123                 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
4124             }
4125             return ImsManager.getInstance(mApp, slotId).getConfigInterface().getConfigInt(key);
4126         } catch (com.android.ims.ImsException e) {
4127             Log.w(LOG_TAG, "getImsProvisioningInt: ImsService is not available for subscription '"
4128                     + subId + "' for key:" + key);
4129             return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
4130         } finally {
4131             Binder.restoreCallingIdentity(identity);
4132         }
4133     }
4134 
4135     @Override
getImsProvisioningString(int subId, int key)4136     public String getImsProvisioningString(int subId, int key) {
4137         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
4138             throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
4139         }
4140         enforceReadPrivilegedPermission("getImsProvisioningString");
4141         final long identity = Binder.clearCallingIdentity();
4142         try {
4143             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
4144             int slotId = getSlotIndex(subId);
4145             if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
4146                 Log.w(LOG_TAG, "getImsProvisioningString: called for an inactive subscription id '"
4147                         + subId + "' for key:" + key);
4148                 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_GENERIC;
4149             }
4150             return ImsManager.getInstance(mApp, slotId).getConfigInterface().getConfigString(key);
4151         } catch (com.android.ims.ImsException e) {
4152             Log.w(LOG_TAG, "getImsProvisioningString: ImsService is not available for sub '"
4153                     + subId + "' for key:" + key);
4154             return ProvisioningManager.STRING_QUERY_RESULT_ERROR_NOT_READY;
4155         } finally {
4156             Binder.restoreCallingIdentity(identity);
4157         }
4158     }
4159 
4160     @Override
setImsProvisioningInt(int subId, int key, int value)4161     public int setImsProvisioningInt(int subId, int key, int value) {
4162         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
4163             throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
4164         }
4165         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
4166                 "setImsProvisioningInt");
4167         final long identity = Binder.clearCallingIdentity();
4168         try {
4169             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
4170             int slotId = getSlotIndex(subId);
4171             if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
4172                 Log.w(LOG_TAG, "setImsProvisioningInt: called with an inactive subscription id '"
4173                         + subId + "' for key:" + key);
4174                 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
4175             }
4176             return ImsManager.getInstance(mApp, slotId).getConfigInterface().setConfig(key, value);
4177         } catch (com.android.ims.ImsException e) {
4178             Log.w(LOG_TAG, "setImsProvisioningInt: ImsService unavailable for sub '" + subId
4179                     + "' for key:" + key);
4180             return ImsConfigImplBase.CONFIG_RESULT_FAILED;
4181         } finally {
4182             Binder.restoreCallingIdentity(identity);
4183         }
4184     }
4185 
4186     @Override
setImsProvisioningString(int subId, int key, String value)4187     public int setImsProvisioningString(int subId, int key, String value) {
4188         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
4189             throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
4190         }
4191         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
4192                 "setImsProvisioningString");
4193         final long identity = Binder.clearCallingIdentity();
4194         try {
4195             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
4196             int slotId = getSlotIndex(subId);
4197             if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
4198                 Log.w(LOG_TAG, "setImsProvisioningString: called with an inactive subscription id '"
4199                         + subId + "' for key:" + key);
4200                 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
4201             }
4202             return ImsManager.getInstance(mApp, slotId).getConfigInterface().setConfig(key, value);
4203         } catch (com.android.ims.ImsException e) {
4204             Log.w(LOG_TAG, "setImsProvisioningString: ImsService unavailable for sub '" + subId
4205                     + "' for key:" + key);
4206             return ImsConfigImplBase.CONFIG_RESULT_FAILED;
4207         } finally {
4208             Binder.restoreCallingIdentity(identity);
4209         }
4210     }
4211 
getSlotIndexOrException(int subId)4212     private int getSlotIndexOrException(int subId) throws ImsException {
4213         int slotId = SubscriptionManager.getSlotIndex(subId);
4214         if (!SubscriptionManager.isValidSlotIndex(slotId)) {
4215             throw new ImsException("Invalid Subscription Id, subId=" + subId,
4216                     ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
4217         }
4218         return slotId;
4219     }
4220 
getSlotIndex(int subId)4221     private int getSlotIndex(int subId) {
4222         int slotId = SubscriptionManager.getSlotIndex(subId);
4223         if (!SubscriptionManager.isValidSlotIndex(slotId)) {
4224             return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
4225         }
4226         return slotId;
4227     }
4228 
4229     /**
4230      * Returns the data network type for a subId; does not throw SecurityException.
4231      */
4232     @Override
getNetworkTypeForSubscriber(int subId, String callingPackage, String callingFeatureId)4233     public int getNetworkTypeForSubscriber(int subId, String callingPackage,
4234             String callingFeatureId) {
4235         final int targetSdk = getTargetSdk(callingPackage);
4236         if (targetSdk > android.os.Build.VERSION_CODES.Q) {
4237             return getDataNetworkTypeForSubscriber(subId, callingPackage, callingFeatureId);
4238         } else if (targetSdk == android.os.Build.VERSION_CODES.Q
4239                 && !TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
4240                         mApp, subId, callingPackage, callingFeatureId,
4241                 "getNetworkTypeForSubscriber")) {
4242             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
4243         }
4244 
4245         final long identity = Binder.clearCallingIdentity();
4246         try {
4247             final Phone phone = getPhone(subId);
4248             if (phone != null) {
4249                 return phone.getServiceState().getDataNetworkType();
4250             } else {
4251                 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
4252             }
4253         } finally {
4254             Binder.restoreCallingIdentity(identity);
4255         }
4256     }
4257 
4258     /**
4259      * Returns the data network type
4260      */
4261     @Override
getDataNetworkType(String callingPackage, String callingFeatureId)4262     public int getDataNetworkType(String callingPackage, String callingFeatureId) {
4263         return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage,
4264                 callingFeatureId);
4265     }
4266 
4267     /**
4268      * Returns the data network type for a subId
4269      */
4270     @Override
getDataNetworkTypeForSubscriber(int subId, String callingPackage, String callingFeatureId)4271     public int getDataNetworkTypeForSubscriber(int subId, String callingPackage,
4272             String callingFeatureId) {
4273         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
4274                 mApp, subId, callingPackage, callingFeatureId,
4275                 "getDataNetworkTypeForSubscriber")) {
4276             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
4277         }
4278 
4279         final long identity = Binder.clearCallingIdentity();
4280         try {
4281             final Phone phone = getPhone(subId);
4282             if (phone != null) {
4283                 return phone.getServiceState().getDataNetworkType();
4284             } else {
4285                 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
4286             }
4287         } finally {
4288             Binder.restoreCallingIdentity(identity);
4289         }
4290     }
4291 
4292     /**
4293      * Returns the Voice network type for a subId
4294      */
4295     @Override
getVoiceNetworkTypeForSubscriber(int subId, String callingPackage, String callingFeatureId)4296     public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage,
4297             String callingFeatureId) {
4298         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
4299                 mApp, subId, callingPackage, callingFeatureId,
4300                 "getDataNetworkTypeForSubscriber")) {
4301             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
4302         }
4303 
4304         final long identity = Binder.clearCallingIdentity();
4305         try {
4306             final Phone phone = getPhone(subId);
4307             if (phone != null) {
4308                 return phone.getServiceState().getVoiceNetworkType();
4309             } else {
4310                 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
4311             }
4312         } finally {
4313             Binder.restoreCallingIdentity(identity);
4314         }
4315     }
4316 
4317     /**
4318      * @return true if a ICC card is present
4319      */
hasIccCard()4320     public boolean hasIccCard() {
4321         // FIXME Make changes to pass defaultSimId of type int
4322         return hasIccCardUsingSlotIndex(mSubscriptionController.getSlotIndex(
4323                 getDefaultSubscription()));
4324     }
4325 
4326     /**
4327      * @return true if a ICC card is present for a slotIndex
4328      */
4329     @Override
hasIccCardUsingSlotIndex(int slotIndex)4330     public boolean hasIccCardUsingSlotIndex(int slotIndex) {
4331         final long identity = Binder.clearCallingIdentity();
4332         try {
4333             final Phone phone = PhoneFactory.getPhone(slotIndex);
4334             if (phone != null) {
4335                 return phone.getIccCard().hasIccCard();
4336             } else {
4337                 return false;
4338             }
4339         } finally {
4340             Binder.restoreCallingIdentity(identity);
4341         }
4342     }
4343 
4344     /**
4345      * Return if the current radio is LTE on CDMA. This
4346      * is a tri-state return value as for a period of time
4347      * the mode may be unknown.
4348      *
4349      * @param callingPackage the name of the package making the call.
4350      * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
4351      * or {@link Phone#LTE_ON_CDMA_TRUE}
4352      */
4353     @Override
getLteOnCdmaMode(String callingPackage, String callingFeatureId)4354     public int getLteOnCdmaMode(String callingPackage, String callingFeatureId) {
4355         return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage,
4356                 callingFeatureId);
4357     }
4358 
4359     @Override
getLteOnCdmaModeForSubscriber(int subId, String callingPackage, String callingFeatureId)4360     public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage,
4361             String callingFeatureId) {
4362         try {
4363             enforceReadPrivilegedPermission("getLteOnCdmaModeForSubscriber");
4364         } catch (SecurityException e) {
4365             return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
4366         }
4367 
4368         final long identity = Binder.clearCallingIdentity();
4369         try {
4370             final Phone phone = getPhone(subId);
4371             if (phone == null) {
4372                 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
4373             } else {
4374                 return TelephonyProperties.lte_on_cdma_device()
4375                         .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
4376             }
4377         } finally {
4378             Binder.restoreCallingIdentity(identity);
4379         }
4380     }
4381 
4382     /**
4383      * {@hide}
4384      * Returns Default subId, 0 in the case of single standby.
4385      */
getDefaultSubscription()4386     private int getDefaultSubscription() {
4387         return mSubscriptionController.getDefaultSubId();
4388     }
4389 
getSlotForDefaultSubscription()4390     private int getSlotForDefaultSubscription() {
4391         return mSubscriptionController.getPhoneId(getDefaultSubscription());
4392     }
4393 
getPreferredVoiceSubscription()4394     private int getPreferredVoiceSubscription() {
4395         return mSubscriptionController.getDefaultVoiceSubId();
4396     }
4397 
isActiveSubscription(int subId)4398     private boolean isActiveSubscription(int subId) {
4399         return mSubscriptionController.isActiveSubId(subId);
4400     }
4401 
4402     /**
4403      * @see android.telephony.TelephonyManager.WifiCallingChoices
4404      */
getWhenToMakeWifiCalls()4405     public int getWhenToMakeWifiCalls() {
4406         final long identity = Binder.clearCallingIdentity();
4407         try {
4408             return Settings.System.getInt(mApp.getContentResolver(),
4409                     Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
4410                     getWhenToMakeWifiCallsDefaultPreference());
4411         } finally {
4412             Binder.restoreCallingIdentity(identity);
4413         }
4414     }
4415 
4416     /**
4417      * @see android.telephony.TelephonyManager.WifiCallingChoices
4418      */
setWhenToMakeWifiCalls(int preference)4419     public void setWhenToMakeWifiCalls(int preference) {
4420         final long identity = Binder.clearCallingIdentity();
4421         try {
4422             if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
4423             Settings.System.putInt(mApp.getContentResolver(),
4424                     Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
4425         } finally {
4426             Binder.restoreCallingIdentity(identity);
4427         }
4428     }
4429 
getWhenToMakeWifiCallsDefaultPreference()4430     private static int getWhenToMakeWifiCallsDefaultPreference() {
4431         // TODO: Use a build property to choose this value.
4432         return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
4433     }
4434 
getPhoneFromSlotIdOrThrowException(int slotIndex)4435     private Phone getPhoneFromSlotIdOrThrowException(int slotIndex) {
4436         int phoneId = UiccController.getInstance().getPhoneIdFromSlotId(slotIndex);
4437         if (phoneId == -1) {
4438             throw new IllegalArgumentException("Given slot index: " + slotIndex
4439                     + " does not correspond to an active phone");
4440         }
4441         return PhoneFactory.getPhone(phoneId);
4442     }
4443 
4444     @Override
iccOpenLogicalChannel( int subId, String callingPackage, String aid, int p2)4445     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
4446             int subId, String callingPackage, String aid, int p2) {
4447         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4448                 mApp, subId, "iccOpenLogicalChannel");
4449         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4450         if (DBG) {
4451             log("iccOpenLogicalChannel: subId=" + subId + " aid=" + aid + " p2=" + p2);
4452         }
4453         return iccOpenLogicalChannelWithPermission(getPhoneFromSubId(subId), callingPackage, aid,
4454                 p2);
4455     }
4456 
4457 
4458     @Override
iccOpenLogicalChannelBySlot( int slotIndex, String callingPackage, String aid, int p2)4459     public IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(
4460             int slotIndex, String callingPackage, String aid, int p2) {
4461         enforceModifyPermission();
4462         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4463         if (DBG) {
4464             log("iccOpenLogicalChannelBySlot: slot=" + slotIndex + " aid=" + aid + " p2=" + p2);
4465         }
4466         return iccOpenLogicalChannelWithPermission(getPhoneFromSlotIdOrThrowException(slotIndex),
4467                 callingPackage, aid, p2);
4468     }
4469 
iccOpenLogicalChannelWithPermission(Phone phone, String callingPackage, String aid, int p2)4470     private IccOpenLogicalChannelResponse iccOpenLogicalChannelWithPermission(Phone phone,
4471             String callingPackage, String aid, int p2) {
4472         final long identity = Binder.clearCallingIdentity();
4473         try {
4474             if (TextUtils.equals(ISDR_AID, aid)) {
4475                 // Only allows LPA to open logical channel to ISD-R.
4476                 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
4477                         .getContext().getPackageManager());
4478                 if (bestComponent == null
4479                         || !TextUtils.equals(callingPackage, bestComponent.packageName)) {
4480                     loge("The calling package is not allowed to access ISD-R.");
4481                     throw new SecurityException(
4482                             "The calling package is not allowed to access ISD-R.");
4483                 }
4484             }
4485 
4486             IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse) sendRequest(
4487                     CMD_OPEN_CHANNEL, new Pair<String, Integer>(aid, p2), phone,
4488                     null /* workSource */);
4489             if (DBG) log("iccOpenLogicalChannelWithPermission: " + response);
4490             return response;
4491         } finally {
4492             Binder.restoreCallingIdentity(identity);
4493         }
4494     }
4495 
4496     @Override
iccCloseLogicalChannel(int subId, int channel)4497     public boolean iccCloseLogicalChannel(int subId, int channel) {
4498         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4499                 mApp, subId, "iccCloseLogicalChannel");
4500         if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
4501         return iccCloseLogicalChannelWithPermission(getPhoneFromSubId(subId), channel);
4502     }
4503 
4504     @Override
iccCloseLogicalChannelBySlot(int slotIndex, int channel)4505     public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
4506         enforceModifyPermission();
4507         if (DBG) log("iccCloseLogicalChannelBySlot: slotIndex=" + slotIndex + " chnl=" + channel);
4508         return iccCloseLogicalChannelWithPermission(getPhoneFromSlotIdOrThrowException(slotIndex),
4509                 channel);
4510     }
4511 
iccCloseLogicalChannelWithPermission(Phone phone, int channel)4512     private boolean iccCloseLogicalChannelWithPermission(Phone phone, int channel) {
4513         final long identity = Binder.clearCallingIdentity();
4514         try {
4515             if (channel < 0) {
4516                 return false;
4517             }
4518             Boolean success = (Boolean) sendRequest(CMD_CLOSE_CHANNEL, channel, phone,
4519                     null /* workSource */);
4520             if (DBG) log("iccCloseLogicalChannelWithPermission: " + success);
4521             return success;
4522         } finally {
4523             Binder.restoreCallingIdentity(identity);
4524         }
4525     }
4526 
4527     @Override
iccTransmitApduLogicalChannel(int subId, int channel, int cla, int command, int p1, int p2, int p3, String data)4528     public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
4529             int command, int p1, int p2, int p3, String data) {
4530         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4531                 mApp, subId, "iccTransmitApduLogicalChannel");
4532         if (DBG) {
4533             log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
4534                     + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
4535                     + p3 + " data=" + data);
4536         }
4537         return iccTransmitApduLogicalChannelWithPermission(getPhoneFromSubId(subId), channel, cla,
4538                 command, p1, p2, p3, data);
4539     }
4540 
4541     @Override
iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla, int command, int p1, int p2, int p3, String data)4542     public String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla,
4543             int command, int p1, int p2, int p3, String data) {
4544         enforceModifyPermission();
4545         if (DBG) {
4546             log("iccTransmitApduLogicalChannelBySlot: slotIndex=" + slotIndex + " chnl=" + channel
4547                     + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
4548                     + p3 + " data=" + data);
4549         }
4550         return iccTransmitApduLogicalChannelWithPermission(
4551                 getPhoneFromSlotIdOrThrowException(slotIndex), channel, cla, command, p1, p2, p3,
4552                 data);
4553     }
4554 
iccTransmitApduLogicalChannelWithPermission(Phone phone, int channel, int cla, int command, int p1, int p2, int p3, String data)4555     private String iccTransmitApduLogicalChannelWithPermission(Phone phone, int channel, int cla,
4556             int command, int p1, int p2, int p3, String data) {
4557         final long identity = Binder.clearCallingIdentity();
4558         try {
4559             if (channel <= 0) {
4560                 return "";
4561             }
4562 
4563             IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
4564                     new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), phone,
4565                     null /* workSource */);
4566             if (DBG) log("iccTransmitApduLogicalChannelWithPermission: " + response);
4567 
4568             // Append the returned status code to the end of the response payload.
4569             String s = Integer.toHexString(
4570                     (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
4571             if (response.payload != null) {
4572                 s = IccUtils.bytesToHexString(response.payload) + s;
4573             }
4574             return s;
4575         } finally {
4576             Binder.restoreCallingIdentity(identity);
4577         }
4578     }
4579 
4580     @Override
iccTransmitApduBasicChannel(int subId, String callingPackage, int cla, int command, int p1, int p2, int p3, String data)4581     public String iccTransmitApduBasicChannel(int subId, String callingPackage, int cla,
4582             int command, int p1, int p2, int p3, String data) {
4583         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4584                 mApp, subId, "iccTransmitApduBasicChannel");
4585         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4586         if (DBG) {
4587             log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
4588                     + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
4589         }
4590         return iccTransmitApduBasicChannelWithPermission(getPhoneFromSubId(subId), callingPackage,
4591                 cla, command, p1, p2, p3, data);
4592     }
4593 
4594     @Override
iccTransmitApduBasicChannelBySlot(int slotIndex, String callingPackage, int cla, int command, int p1, int p2, int p3, String data)4595     public String iccTransmitApduBasicChannelBySlot(int slotIndex, String callingPackage, int cla,
4596             int command, int p1, int p2, int p3, String data) {
4597         enforceModifyPermission();
4598         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4599         if (DBG) {
4600             log("iccTransmitApduBasicChannelBySlot: slotIndex=" + slotIndex + " cla=" + cla
4601                     + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3
4602                     + " data=" + data);
4603         }
4604 
4605         return iccTransmitApduBasicChannelWithPermission(
4606                 getPhoneFromSlotIdOrThrowException(slotIndex), callingPackage, cla, command, p1,
4607                 p2, p3, data);
4608     }
4609 
4610     // open APDU basic channel assuming the caller has sufficient permissions
iccTransmitApduBasicChannelWithPermission(Phone phone, String callingPackage, int cla, int command, int p1, int p2, int p3, String data)4611     private String iccTransmitApduBasicChannelWithPermission(Phone phone, String callingPackage,
4612             int cla, int command, int p1, int p2, int p3, String data) {
4613         final long identity = Binder.clearCallingIdentity();
4614         try {
4615             if (command == SELECT_COMMAND && p1 == SELECT_P1 && p2 == SELECT_P2 && p3 == SELECT_P3
4616                     && TextUtils.equals(ISDR_AID, data)) {
4617                 // Only allows LPA to select ISD-R.
4618                 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
4619                         .getContext().getPackageManager());
4620                 if (bestComponent == null
4621                         || !TextUtils.equals(callingPackage, bestComponent.packageName)) {
4622                     loge("The calling package is not allowed to select ISD-R.");
4623                     throw new SecurityException(
4624                             "The calling package is not allowed to select ISD-R.");
4625                 }
4626             }
4627 
4628             IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
4629                     new IccAPDUArgument(0, cla, command, p1, p2, p3, data), phone,
4630                     null /* workSource */);
4631             if (DBG) log("iccTransmitApduBasicChannelWithPermission: " + response);
4632 
4633             // Append the returned status code to the end of the response payload.
4634             String s = Integer.toHexString(
4635                     (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
4636             if (response.payload != null) {
4637                 s = IccUtils.bytesToHexString(response.payload) + s;
4638             }
4639             return s;
4640         } finally {
4641             Binder.restoreCallingIdentity(identity);
4642         }
4643     }
4644 
4645     @Override
iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3, String filePath)4646     public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
4647             String filePath) {
4648         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4649                 mApp, subId, "iccExchangeSimIO");
4650 
4651         final long identity = Binder.clearCallingIdentity();
4652         try {
4653             if (DBG) {
4654                 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " "
4655                         + p1 + " " + p2 + " " + p3 + ":" + filePath);
4656             }
4657 
4658             IccIoResult response =
4659                     (IccIoResult) sendRequest(CMD_EXCHANGE_SIM_IO,
4660                             new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
4661                             subId);
4662 
4663             if (DBG) {
4664                 log("Exchange SIM_IO [R]" + response);
4665             }
4666 
4667             byte[] result = null;
4668             int length = 2;
4669             if (response.payload != null) {
4670                 length = 2 + response.payload.length;
4671                 result = new byte[length];
4672                 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
4673             } else {
4674                 result = new byte[length];
4675             }
4676 
4677             result[length - 1] = (byte) response.sw2;
4678             result[length - 2] = (byte) response.sw1;
4679             return result;
4680         } finally {
4681             Binder.restoreCallingIdentity(identity);
4682         }
4683     }
4684 
4685     /**
4686      * Get the forbidden PLMN List from the given app type (ex APPTYPE_USIM)
4687      * on a particular subscription
4688      */
getForbiddenPlmns(int subId, int appType, String callingPackage, String callingFeatureId)4689     public String[] getForbiddenPlmns(int subId, int appType, String callingPackage,
4690             String callingFeatureId) {
4691         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
4692                 mApp, subId, callingPackage, callingFeatureId, "getForbiddenPlmns")) {
4693             return null;
4694         }
4695 
4696         final long identity = Binder.clearCallingIdentity();
4697         try {
4698             if (appType != TelephonyManager.APPTYPE_USIM
4699                     && appType != TelephonyManager.APPTYPE_SIM) {
4700                 loge("getForbiddenPlmnList(): App Type must be USIM or SIM");
4701                 return null;
4702             }
4703             Object response = sendRequest(
4704                     CMD_GET_FORBIDDEN_PLMNS, new Integer(appType), subId);
4705             if (response instanceof String[]) {
4706                 return (String[]) response;
4707             }
4708             // Response is an Exception of some kind
4709             // which is signalled to the user as a NULL retval
4710             return null;
4711         } finally {
4712             Binder.restoreCallingIdentity(identity);
4713         }
4714     }
4715 
4716     /**
4717      * Set the forbidden PLMN list from the given app type (ex APPTYPE_USIM) on a particular
4718      * subscription.
4719      *
4720      * @param subId the id of the subscription.
4721      * @param appType the uicc app type, must be USIM or SIM.
4722      * @param fplmns the Forbiden plmns list that needed to be written to the SIM.
4723      * @param callingPackage the op Package name.
4724      * @param callingFeatureId the feature in the package.
4725      * @return number of fplmns that is successfully written to the SIM.
4726      */
setForbiddenPlmns(int subId, int appType, List<String> fplmns, String callingPackage, String callingFeatureId)4727     public int setForbiddenPlmns(int subId, int appType, List<String> fplmns, String callingPackage,
4728             String callingFeatureId) {
4729         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId, callingPackage,
4730                 callingFeatureId, "setForbiddenPlmns")) {
4731             if (DBG) logv("no permissions for setForbiddenplmns");
4732             throw new IllegalStateException("No Permissions for setForbiddenPlmns");
4733         }
4734         if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
4735             loge("setForbiddenPlmnList(): App Type must be USIM or SIM");
4736             throw new IllegalArgumentException("Invalid appType: App Type must be USIM or SIM");
4737         }
4738         if (fplmns == null) {
4739             throw new IllegalArgumentException("Fplmn List provided is null");
4740         }
4741         for (String fplmn : fplmns) {
4742             if (!CellIdentity.isValidPlmn(fplmn)) {
4743                 throw new IllegalArgumentException("Invalid fplmn provided: " + fplmn);
4744             }
4745         }
4746         final long identity = Binder.clearCallingIdentity();
4747         try {
4748             Object response = sendRequest(
4749                     CMD_SET_FORBIDDEN_PLMNS,
4750                     new Pair<Integer, List<String>>(new Integer(appType), fplmns),
4751                     subId);
4752             return (int) response;
4753         } finally {
4754             Binder.restoreCallingIdentity(identity);
4755         }
4756     }
4757 
4758     @Override
sendEnvelopeWithStatus(int subId, String content)4759     public String sendEnvelopeWithStatus(int subId, String content) {
4760         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4761                 mApp, subId, "sendEnvelopeWithStatus");
4762 
4763         final long identity = Binder.clearCallingIdentity();
4764         try {
4765             IccIoResult response = (IccIoResult) sendRequest(CMD_SEND_ENVELOPE, content, subId);
4766             if (response.payload == null) {
4767                 return "";
4768             }
4769 
4770             // Append the returned status code to the end of the response payload.
4771             String s = Integer.toHexString(
4772                     (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
4773             s = IccUtils.bytesToHexString(response.payload) + s;
4774             return s;
4775         } finally {
4776             Binder.restoreCallingIdentity(identity);
4777         }
4778     }
4779 
4780     /**
4781      * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
4782      * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
4783      *
4784      * @param itemID the ID of the item to read
4785      * @return the NV item as a String, or null on error.
4786      */
4787     @Override
nvReadItem(int itemID)4788     public String nvReadItem(int itemID) {
4789         WorkSource workSource = getWorkSource(Binder.getCallingUid());
4790         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4791                 mApp, getDefaultSubscription(), "nvReadItem");
4792 
4793         final long identity = Binder.clearCallingIdentity();
4794         try {
4795             if (DBG) log("nvReadItem: item " + itemID);
4796             String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID, workSource);
4797             if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
4798             return value;
4799         } finally {
4800             Binder.restoreCallingIdentity(identity);
4801         }
4802     }
4803 
4804     /**
4805      * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
4806      * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
4807      *
4808      * @param itemID the ID of the item to read
4809      * @param itemValue the value to write, as a String
4810      * @return true on success; false on any failure
4811      */
4812     @Override
nvWriteItem(int itemID, String itemValue)4813     public boolean nvWriteItem(int itemID, String itemValue) {
4814         WorkSource workSource = getWorkSource(Binder.getCallingUid());
4815         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4816                 mApp, getDefaultSubscription(), "nvWriteItem");
4817 
4818         final long identity = Binder.clearCallingIdentity();
4819         try {
4820             if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
4821             Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
4822                     new Pair<Integer, String>(itemID, itemValue), workSource);
4823             if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
4824             return success;
4825         } finally {
4826             Binder.restoreCallingIdentity(identity);
4827         }
4828     }
4829 
4830     /**
4831      * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
4832      * Used for device configuration by some CDMA operators.
4833      *
4834      * @param preferredRoamingList byte array containing the new PRL
4835      * @return true on success; false on any failure
4836      */
4837     @Override
nvWriteCdmaPrl(byte[] preferredRoamingList)4838     public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
4839         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4840                 mApp, getDefaultSubscription(), "nvWriteCdmaPrl");
4841 
4842         final long identity = Binder.clearCallingIdentity();
4843         try {
4844             if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
4845             Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
4846             if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
4847             return success;
4848         } finally {
4849             Binder.restoreCallingIdentity(identity);
4850         }
4851     }
4852 
4853     /**
4854      * Rollback modem configurations to factory default except some config which are in whitelist.
4855      * Used for device configuration by some CDMA operators.
4856      *
4857      * @param slotIndex - device slot.
4858      *
4859      * @return true on success; false on any failure
4860      */
4861     @Override
resetModemConfig(int slotIndex)4862     public boolean resetModemConfig(int slotIndex) {
4863         Phone phone = PhoneFactory.getPhone(slotIndex);
4864         if (phone != null) {
4865             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4866                     mApp, phone.getSubId(), "resetModemConfig");
4867 
4868             final long identity = Binder.clearCallingIdentity();
4869             try {
4870                 Boolean success = (Boolean) sendRequest(CMD_RESET_MODEM_CONFIG, null);
4871                 if (DBG) log("resetModemConfig:" + ' ' + (success ? "ok" : "fail"));
4872                 return success;
4873             } finally {
4874                 Binder.restoreCallingIdentity(identity);
4875             }
4876         }
4877         return false;
4878     }
4879 
4880     /**
4881      * Generate a radio modem reset. Used for device configuration by some CDMA operators.
4882      *
4883      * @param slotIndex - device slot.
4884      *
4885      * @return true on success; false on any failure
4886      */
4887     @Override
rebootModem(int slotIndex)4888     public boolean rebootModem(int slotIndex) {
4889         Phone phone = PhoneFactory.getPhone(slotIndex);
4890         if (phone != null) {
4891             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4892                     mApp, phone.getSubId(), "rebootModem");
4893 
4894             final long identity = Binder.clearCallingIdentity();
4895             try {
4896                 Boolean success = (Boolean) sendRequest(CMD_MODEM_REBOOT, null);
4897                 if (DBG) log("rebootModem:" + ' ' + (success ? "ok" : "fail"));
4898                 return success;
4899             } finally {
4900                 Binder.restoreCallingIdentity(identity);
4901             }
4902         }
4903         return false;
4904     }
4905 
getPcscfAddress(String apnType, String callingPackage, String callingFeatureId)4906     public String[] getPcscfAddress(String apnType, String callingPackage,
4907             String callingFeatureId) {
4908         final Phone defaultPhone = getDefaultPhone();
4909         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
4910                 callingPackage, callingFeatureId, "getPcscfAddress")) {
4911             return new String[0];
4912         }
4913 
4914         final long identity = Binder.clearCallingIdentity();
4915         try {
4916             return defaultPhone.getPcscfAddress(apnType);
4917         } finally {
4918             Binder.restoreCallingIdentity(identity);
4919         }
4920     }
4921 
4922     /**
4923      * Toggle IMS disable and enable for the framework to reset it. See {@link #enableIms(int)} and
4924      * {@link #disableIms(int)}.
4925      * @param slotIndex device slot.
4926      */
resetIms(int slotIndex)4927     public void resetIms(int slotIndex) {
4928         enforceModifyPermission();
4929 
4930         final long identity = Binder.clearCallingIdentity();
4931         try {
4932             if (mImsResolver == null) {
4933                 // may happen if the does not support IMS.
4934                 return;
4935             }
4936             mImsResolver.disableIms(slotIndex);
4937             mImsResolver.enableIms(slotIndex);
4938         } finally {
4939             Binder.restoreCallingIdentity(identity);
4940         }
4941     }
4942 
4943     /**
4944      * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
4945      * status updates, if not already enabled.
4946      */
enableIms(int slotId)4947     public void enableIms(int slotId) {
4948         enforceModifyPermission();
4949 
4950         final long identity = Binder.clearCallingIdentity();
4951         try {
4952             if (mImsResolver == null) {
4953                 // may happen if the device does not support IMS.
4954                 return;
4955             }
4956             mImsResolver.enableIms(slotId);
4957         } finally {
4958             Binder.restoreCallingIdentity(identity);
4959         }
4960     }
4961 
4962     /**
4963      * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature
4964      * status updates to disabled.
4965      */
disableIms(int slotId)4966     public void disableIms(int slotId) {
4967         enforceModifyPermission();
4968 
4969         final long identity = Binder.clearCallingIdentity();
4970         try {
4971             if (mImsResolver == null) {
4972                 // may happen if the device does not support IMS.
4973                 return;
4974             }
4975             mImsResolver.disableIms(slotId);
4976         } finally {
4977             Binder.restoreCallingIdentity(identity);
4978         }
4979     }
4980 
4981     /**
4982      * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id for the MMTel
4983      * feature or {@link null} if the service is not available. If the feature is available, the
4984      * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
4985      */
getMmTelFeatureAndListen(int slotId, IImsServiceFeatureCallback callback)4986     public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
4987             IImsServiceFeatureCallback callback) {
4988         enforceModifyPermission();
4989 
4990         final long identity = Binder.clearCallingIdentity();
4991         try {
4992             if (mImsResolver == null) {
4993                 // may happen if the device does not support IMS.
4994                 return null;
4995             }
4996             return mImsResolver.getMmTelFeatureAndListen(slotId, callback);
4997         } finally {
4998             Binder.restoreCallingIdentity(identity);
4999         }
5000     }
5001 
5002     /**
5003      * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for the RCS
5004      * feature during emergency calling or {@link null} if the service is not available. If the
5005      * feature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
5006      * listener for feature updates.
5007      */
getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback)5008     public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
5009         enforceModifyPermission();
5010 
5011         final long identity = Binder.clearCallingIdentity();
5012         try {
5013             if (mImsResolver == null) {
5014                 // may happen if the device does not support IMS.
5015                 return null;
5016             }
5017             return mImsResolver.getRcsFeatureAndListen(slotId, callback);
5018         } finally {
5019             Binder.restoreCallingIdentity(identity);
5020         }
5021     }
5022 
5023     /**
5024      * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
5025      */
unregisterImsFeatureCallback(int slotId, int featureType, IImsServiceFeatureCallback callback)5026     public void unregisterImsFeatureCallback(int slotId, int featureType,
5027             IImsServiceFeatureCallback callback) {
5028         enforceModifyPermission();
5029 
5030         final long identity = Binder.clearCallingIdentity();
5031         try {
5032             if (mImsResolver == null) return;
5033             mImsResolver.unregisterImsFeatureCallback(slotId, featureType, callback);
5034         } finally {
5035             Binder.restoreCallingIdentity(identity);
5036         }
5037     }
5038 
5039     /**
5040      * Returns the {@link IImsRegistration} structure associated with the slotId and feature
5041      * specified or null if IMS is not supported on the slot specified.
5042      */
getImsRegistration(int slotId, int feature)5043     public IImsRegistration getImsRegistration(int slotId, int feature) throws RemoteException {
5044         enforceModifyPermission();
5045 
5046         final long identity = Binder.clearCallingIdentity();
5047         try {
5048             if (mImsResolver == null) {
5049                 // may happen if the device does not support IMS.
5050                 return null;
5051             }
5052             return mImsResolver.getImsRegistration(slotId, feature);
5053         } finally {
5054             Binder.restoreCallingIdentity(identity);
5055         }
5056     }
5057 
5058     /**
5059      * Returns the {@link IImsConfig} structure associated with the slotId and feature
5060      * specified or null if IMS is not supported on the slot specified.
5061      */
getImsConfig(int slotId, int feature)5062     public IImsConfig getImsConfig(int slotId, int feature) throws RemoteException {
5063         enforceModifyPermission();
5064 
5065         final long identity = Binder.clearCallingIdentity();
5066         try {
5067             if (mImsResolver == null) {
5068                 // may happen if the device does not support IMS.
5069                 return null;
5070             }
5071             return mImsResolver.getImsConfig(slotId, feature);
5072         } finally {
5073             Binder.restoreCallingIdentity(identity);
5074         }
5075     }
5076 
5077     /**
5078      * Sets the ImsService Package Name that Telephony will bind to.
5079      *
5080      * @param slotIndex the slot ID that the ImsService should bind for.
5081      * @param isCarrierService true if the ImsService is the carrier override, false if the
5082      *         ImsService is the device default ImsService.
5083      * @param featureTypes An integer array of feature types associated with a packageName.
5084      * @param packageName The name of the package that the current configuration will be replaced
5085      *                    with.
5086      * @return true if setting the ImsService to bind to succeeded, false if it did not.
5087      */
setBoundImsServiceOverride(int slotIndex, boolean isCarrierService, int[] featureTypes, String packageName)5088     public boolean setBoundImsServiceOverride(int slotIndex, boolean isCarrierService,
5089             int[] featureTypes, String packageName) {
5090         int[] subIds = SubscriptionManager.getSubId(slotIndex);
5091         TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setBoundImsServiceOverride");
5092         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
5093                 (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
5094                 "setBoundImsServiceOverride");
5095 
5096         final long identity = Binder.clearCallingIdentity();
5097         try {
5098             if (mImsResolver == null) {
5099                 // may happen if the device does not support IMS.
5100                 return false;
5101             }
5102             Map<Integer, String> featureConfig = new HashMap<>();
5103             for (int featureType : featureTypes) {
5104                 featureConfig.put(featureType, packageName);
5105             }
5106             return mImsResolver.overrideImsServiceConfiguration(slotIndex, isCarrierService,
5107                     featureConfig);
5108         } finally {
5109             Binder.restoreCallingIdentity(identity);
5110         }
5111     }
5112 
5113     /**
5114      * Return the package name of the currently bound ImsService.
5115      *
5116      * @param slotId The slot that the ImsService is associated with.
5117      * @param isCarrierImsService true, if the ImsService is a carrier override, false if it is
5118      *         the device default.
5119      * @param featureType The feature associated with the queried configuration.
5120      * @return the package name of the ImsService configuration.
5121      */
getBoundImsServicePackage(int slotId, boolean isCarrierImsService, @ImsFeature.FeatureType int featureType)5122     public String getBoundImsServicePackage(int slotId, boolean isCarrierImsService,
5123             @ImsFeature.FeatureType int featureType) {
5124         int[] subIds = SubscriptionManager.getSubId(slotId);
5125         TelephonyPermissions
5126                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
5127                 mApp, (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
5128                 "getBoundImsServicePackage");
5129 
5130         final long identity = Binder.clearCallingIdentity();
5131         try {
5132             if (mImsResolver == null) {
5133                 // may happen if the device does not support IMS.
5134                 return "";
5135             }
5136             // TODO: change API to query RCS separately.
5137             return mImsResolver.getImsServiceConfiguration(slotId, isCarrierImsService,
5138                     featureType);
5139         } finally {
5140             Binder.restoreCallingIdentity(identity);
5141         }
5142     }
5143 
5144     /**
5145      * Get the MmTelFeature state associated with the requested subscription id.
5146      * @param subId The subscription that the MmTelFeature is associated with.
5147      * @param callback A callback with an integer containing the
5148      * {@link android.telephony.ims.feature.ImsFeature.ImsState} associated with the MmTelFeature.
5149      */
5150     @Override
getImsMmTelFeatureState(int subId, IIntegerConsumer callback)5151     public void getImsMmTelFeatureState(int subId, IIntegerConsumer callback) {
5152         enforceReadPrivilegedPermission("getImsMmTelFeatureState");
5153         if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5154             throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5155                     "IMS not available on device.");
5156         }
5157         final long token = Binder.clearCallingIdentity();
5158         try {
5159             int slotId = getSlotIndex(subId);
5160             if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5161                 Log.w(LOG_TAG, "getImsMmTelFeatureState: called with an inactive subscription '"
5162                         + subId + "'");
5163                 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5164             }
5165             ImsManager.getInstance(mApp, slotId).getImsServiceState(anInteger -> {
5166                 try {
5167                     callback.accept(anInteger == null ? ImsFeature.STATE_UNAVAILABLE : anInteger);
5168                 } catch (RemoteException e) {
5169                     Log.w(LOG_TAG, "getImsMmTelFeatureState: remote caller is no longer running. "
5170                             + "Ignore");
5171                 }
5172             });
5173         } finally {
5174             Binder.restoreCallingIdentity(token);
5175         }
5176     }
5177 
setImsRegistrationState(boolean registered)5178     public void setImsRegistrationState(boolean registered) {
5179         enforceModifyPermission();
5180 
5181         final long identity = Binder.clearCallingIdentity();
5182         try {
5183             getDefaultPhone().setImsRegistrationState(registered);
5184         } finally {
5185             Binder.restoreCallingIdentity(identity);
5186         }
5187     }
5188 
5189     /**
5190      * Set the network selection mode to automatic.
5191      *
5192      */
5193     @Override
setNetworkSelectionModeAutomatic(int subId)5194     public void setNetworkSelectionModeAutomatic(int subId) {
5195         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5196                 mApp, subId, "setNetworkSelectionModeAutomatic");
5197 
5198         final long identity = Binder.clearCallingIdentity();
5199         try {
5200             if (!isActiveSubscription(subId)) {
5201                 return;
5202             }
5203             if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
5204             sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
5205         } finally {
5206             Binder.restoreCallingIdentity(identity);
5207         }
5208     }
5209 
5210    /**
5211      * Ask the radio to connect to the input network and change selection mode to manual.
5212      *
5213      * @param subId the id of the subscription.
5214      * @param operatorInfo the operator information, included the PLMN, long name and short name of
5215      * the operator to attach to.
5216      * @param persistSelection whether the selection will persist until reboot. If true, only allows
5217      * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
5218      * normal network selection next time.
5219      * @return {@code true} on success; {@code true} on any failure.
5220      */
5221     @Override
setNetworkSelectionModeManual( int subId, OperatorInfo operatorInfo, boolean persistSelection)5222     public boolean setNetworkSelectionModeManual(
5223             int subId, OperatorInfo operatorInfo, boolean persistSelection) {
5224         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5225                 mApp, subId, "setNetworkSelectionModeManual");
5226 
5227         if (!isActiveSubscription(subId)) {
5228             return false;
5229         }
5230 
5231         final long identity = Binder.clearCallingIdentity();
5232         try {
5233             ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operatorInfo,
5234                     persistSelection);
5235             if (DBG) {
5236                 log("setNetworkSelectionModeManual: subId: " + subId
5237                         + " operator: " + operatorInfo);
5238             }
5239             return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
5240         } finally {
5241             Binder.restoreCallingIdentity(identity);
5242         }
5243     }
5244 
5245     /**
5246      * Scans for available networks.
5247      */
5248     @Override
getCellNetworkScanResults(int subId, String callingPackage, String callingFeatureId)5249     public CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage,
5250             String callingFeatureId) {
5251         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5252                 mApp, subId, "getCellNetworkScanResults");
5253         LocationAccessPolicy.LocationPermissionResult locationResult =
5254                 LocationAccessPolicy.checkLocationPermission(mApp,
5255                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
5256                                 .setCallingPackage(callingPackage)
5257                                 .setCallingFeatureId(callingFeatureId)
5258                                 .setCallingPid(Binder.getCallingPid())
5259                                 .setCallingUid(Binder.getCallingUid())
5260                                 .setMethod("getCellNetworkScanResults")
5261                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
5262                                 .build());
5263         switch (locationResult) {
5264             case DENIED_HARD:
5265                 throw new SecurityException("Not allowed to access scan results -- location");
5266             case DENIED_SOFT:
5267                 return null;
5268         }
5269 
5270         long identity = Binder.clearCallingIdentity();
5271         try {
5272             if (DBG) log("getCellNetworkScanResults: subId " + subId);
5273             return (CellNetworkScanResult) sendRequest(
5274                     CMD_PERFORM_NETWORK_SCAN, null, subId);
5275         } finally {
5276             Binder.restoreCallingIdentity(identity);
5277         }
5278     }
5279 
5280     /**
5281      * Get the call forwarding info, given the call forwarding reason.
5282      */
5283     @Override
getCallForwarding(int subId, int callForwardingReason)5284     public CallForwardingInfo getCallForwarding(int subId, int callForwardingReason) {
5285         enforceReadPrivilegedPermission("getCallForwarding");
5286         long identity = Binder.clearCallingIdentity();
5287         try {
5288             if (DBG) {
5289                 log("getCallForwarding: subId " + subId
5290                         + " callForwardingReason" + callForwardingReason);
5291             }
5292             return (CallForwardingInfo) sendRequest(
5293                     CMD_GET_CALL_FORWARDING, callForwardingReason, subId);
5294         } finally {
5295             Binder.restoreCallingIdentity(identity);
5296         }
5297     }
5298 
5299     /**
5300      * Sets the voice call forwarding info including status (enable/disable), call forwarding
5301      * reason, the number to forward, and the timeout before the forwarding is attempted.
5302      */
5303     @Override
setCallForwarding(int subId, CallForwardingInfo callForwardingInfo)5304     public boolean setCallForwarding(int subId, CallForwardingInfo callForwardingInfo) {
5305         enforceModifyPermission();
5306         long identity = Binder.clearCallingIdentity();
5307         try {
5308             if (DBG) {
5309                 log("setCallForwarding: subId " + subId
5310                         + " callForwardingInfo" + callForwardingInfo);
5311             }
5312             return (Boolean) sendRequest(CMD_SET_CALL_FORWARDING, callForwardingInfo, subId);
5313         } finally {
5314             Binder.restoreCallingIdentity(identity);
5315         }
5316     }
5317 
5318     /**
5319      * Get the call forwarding info, given the call forwarding reason.
5320      */
5321     @Override
getCallWaitingStatus(int subId)5322     public int getCallWaitingStatus(int subId) {
5323         enforceReadPrivilegedPermission("getCallForwarding");
5324         long identity = Binder.clearCallingIdentity();
5325         try {
5326             if (DBG) log("getCallWaitingStatus: subId " + subId);
5327             return (Integer) sendRequest(CMD_GET_CALL_WAITING, null, subId);
5328         } finally {
5329             Binder.restoreCallingIdentity(identity);
5330         }
5331     }
5332 
5333     /**
5334      * Sets the voice call forwarding info including status (enable/disable), call forwarding
5335      * reason, the number to forward, and the timeout before the forwarding is attempted.
5336      */
5337     @Override
setCallWaitingStatus(int subId, boolean isEnable)5338     public boolean setCallWaitingStatus(int subId, boolean isEnable) {
5339         enforceModifyPermission();
5340         long identity = Binder.clearCallingIdentity();
5341         try {
5342             if (DBG) log("setCallWaitingStatus: subId " + subId + " isEnable: " + isEnable);
5343             return (Boolean) sendRequest(CMD_SET_CALL_WAITING, isEnable, subId);
5344         } finally {
5345             Binder.restoreCallingIdentity(identity);
5346         }
5347     }
5348 
5349     /**
5350      * Starts a new network scan and returns the id of this scan.
5351      *
5352      * @param subId id of the subscription
5353      * @param request contains the radio access networks with bands/channels to scan
5354      * @param messenger callback messenger for scan results or errors
5355      * @param binder for the purpose of auto clean when the user thread crashes
5356      * @return the id of the requested scan which can be used to stop the scan.
5357      */
5358     @Override
requestNetworkScan(int subId, NetworkScanRequest request, Messenger messenger, IBinder binder, String callingPackage, String callingFeatureId)5359     public int requestNetworkScan(int subId, NetworkScanRequest request, Messenger messenger,
5360             IBinder binder, String callingPackage, String callingFeatureId) {
5361         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5362                 mApp, subId, "requestNetworkScan");
5363         LocationAccessPolicy.LocationPermissionResult locationResult =
5364                 LocationAccessPolicy.checkLocationPermission(mApp,
5365                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
5366                                 .setCallingPackage(callingPackage)
5367                                 .setCallingFeatureId(callingFeatureId)
5368                                 .setCallingPid(Binder.getCallingPid())
5369                                 .setCallingUid(Binder.getCallingUid())
5370                                 .setMethod("requestNetworkScan")
5371                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
5372                                 .build());
5373         if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
5374             SecurityException e = checkNetworkRequestForSanitizedLocationAccess(request, subId);
5375             if (e != null) {
5376                 if (locationResult == LocationAccessPolicy.LocationPermissionResult.DENIED_HARD) {
5377                     throw e;
5378                 } else {
5379                     loge(e.getMessage());
5380                     return TelephonyScanManager.INVALID_SCAN_ID;
5381                 }
5382             }
5383         }
5384         int callingUid = Binder.getCallingUid();
5385         int callingPid = Binder.getCallingPid();
5386         final long identity = Binder.clearCallingIdentity();
5387         try {
5388             return mNetworkScanRequestTracker.startNetworkScan(
5389                     request, messenger, binder, getPhone(subId),
5390                     callingUid, callingPid, callingPackage);
5391         } finally {
5392             Binder.restoreCallingIdentity(identity);
5393         }
5394     }
5395 
checkNetworkRequestForSanitizedLocationAccess( NetworkScanRequest request, int subId)5396     private SecurityException checkNetworkRequestForSanitizedLocationAccess(
5397             NetworkScanRequest request, int subId) {
5398         boolean hasCarrierPriv = getCarrierPrivilegeStatusForUid(subId, Binder.getCallingUid())
5399                 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
5400         boolean hasNetworkScanPermission =
5401                 mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
5402                 == PERMISSION_GRANTED;
5403 
5404         if (!hasCarrierPriv && !hasNetworkScanPermission) {
5405             return new SecurityException("permission.NETWORK_SCAN or carrier privileges is needed"
5406                     + " for network scans without location access.");
5407         }
5408 
5409         if (request.getSpecifiers() != null && request.getSpecifiers().length > 0) {
5410             for (RadioAccessSpecifier ras : request.getSpecifiers()) {
5411                 if (ras.getChannels() != null && ras.getChannels().length > 0) {
5412                     return new SecurityException("Specific channels must not be"
5413                             + " scanned without location access.");
5414                 }
5415             }
5416         }
5417 
5418         return null;
5419     }
5420 
5421     /**
5422      * Stops an existing network scan with the given scanId.
5423      *
5424      * @param subId id of the subscription
5425      * @param scanId id of the scan that needs to be stopped
5426      */
5427     @Override
stopNetworkScan(int subId, int scanId)5428     public void stopNetworkScan(int subId, int scanId) {
5429         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5430                 mApp, subId, "stopNetworkScan");
5431 
5432         int callingUid = Binder.getCallingUid();
5433         final long identity = Binder.clearCallingIdentity();
5434         try {
5435             mNetworkScanRequestTracker.stopNetworkScan(scanId, callingUid);
5436         } finally {
5437             Binder.restoreCallingIdentity(identity);
5438         }
5439     }
5440 
5441     /**
5442      * Get the calculated preferred network type.
5443      * Used for debugging incorrect network type.
5444      *
5445      * @return the preferred network type, defined in RILConstants.java.
5446      */
5447     @Override
getCalculatedPreferredNetworkType(String callingPackage, String callingFeatureId)5448     public int getCalculatedPreferredNetworkType(String callingPackage, String callingFeatureId) {
5449         final Phone defaultPhone = getDefaultPhone();
5450         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
5451                 callingPackage, callingFeatureId, "getCalculatedPreferredNetworkType")) {
5452             return RILConstants.PREFERRED_NETWORK_MODE;
5453         }
5454 
5455         final long identity = Binder.clearCallingIdentity();
5456         try {
5457             // FIXME: need to get SubId from somewhere.
5458             return PhoneFactory.calculatePreferredNetworkType(defaultPhone.getContext(), 0);
5459         } finally {
5460             Binder.restoreCallingIdentity(identity);
5461         }
5462     }
5463 
5464     /**
5465      * Get the preferred network type.
5466      * Used for device configuration by some CDMA operators.
5467      *
5468      * @return the preferred network type, defined in RILConstants.java.
5469      */
5470     @Override
getPreferredNetworkType(int subId)5471     public int getPreferredNetworkType(int subId) {
5472         TelephonyPermissions
5473                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
5474                         mApp, subId, "getPreferredNetworkType");
5475 
5476         final long identity = Binder.clearCallingIdentity();
5477         try {
5478             if (DBG) log("getPreferredNetworkType");
5479             int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
5480             int networkType = (result != null ? result[0] : -1);
5481             if (DBG) log("getPreferredNetworkType: " + networkType);
5482             return networkType;
5483         } finally {
5484             Binder.restoreCallingIdentity(identity);
5485         }
5486     }
5487 
5488     /**
5489      * Set the preferred network type.
5490      *
5491      * @param networkType the preferred network type, defined in RILConstants.java.
5492      * @return true on success; false on any failure.
5493      */
5494     @Override
setPreferredNetworkType(int subId, int networkType)5495     public boolean setPreferredNetworkType(int subId, int networkType) {
5496         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5497                 mApp, subId, "setPreferredNetworkType");
5498 
5499         final long identity = Binder.clearCallingIdentity();
5500         try {
5501             Settings.Global.putInt(mApp.getContentResolver(),
5502                     Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
5503 
5504             Boolean success = (Boolean) sendRequest(
5505                     CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
5506             if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
5507             return success;
5508         } finally {
5509             Binder.restoreCallingIdentity(identity);
5510         }
5511     }
5512 
5513     /**
5514      * Get the allowed network types that store in the telephony provider.
5515      *
5516      * @param subId the id of the subscription.
5517      * @return allowedNetworkTypes the allowed network types.
5518      */
5519     @Override
getAllowedNetworkTypes(int subId)5520     public long getAllowedNetworkTypes(int subId) {
5521         TelephonyPermissions
5522                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
5523                     mApp, subId, "getAllowedNetworkTypes");
5524 
5525         final long identity = Binder.clearCallingIdentity();
5526         try {
5527             return SubscriptionManager.getLongSubscriptionProperty(
5528                     subId, SubscriptionManager.ALLOWED_NETWORK_TYPES, -1, mApp);
5529         } finally {
5530             Binder.restoreCallingIdentity(identity);
5531         }
5532     }
5533 
5534     /**
5535      * Set the allowed network types.
5536      *
5537      * @param subId the id of the subscription.
5538      * @param allowedNetworkTypes the allowed network types.
5539      * @return true on success; false on any failure.
5540      */
5541     @Override
setAllowedNetworkTypes(int subId, long allowedNetworkTypes)5542     public boolean setAllowedNetworkTypes(int subId, long allowedNetworkTypes) {
5543         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5544                 mApp, subId, "setAllowedNetworkTypes");
5545 
5546         SubscriptionManager.setSubscriptionProperty(subId,
5547                 SubscriptionManager.ALLOWED_NETWORK_TYPES,
5548                 String.valueOf(allowedNetworkTypes));
5549 
5550         int preferredNetworkMode = Settings.Global.getInt(mApp.getContentResolver(),
5551                 Settings.Global.PREFERRED_NETWORK_MODE + subId,
5552                 RILConstants.PREFERRED_NETWORK_MODE);
5553         return setPreferredNetworkType(subId, preferredNetworkMode);
5554     }
5555 
5556     /**
5557      * Get the allowed network types for certain reason.
5558      *
5559      * @param subId the id of the subscription.
5560      * @param reason the reason the allowed network type change is taking place
5561      * @return the allowed network types.
5562      */
5563     @Override
getAllowedNetworkTypesForReason(int subId, @TelephonyManager.AllowedNetworkTypesReason int reason)5564     public long getAllowedNetworkTypesForReason(int subId,
5565             @TelephonyManager.AllowedNetworkTypesReason int reason) {
5566         TelephonyPermissions
5567                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
5568                         mApp, subId, "getAllowedNetworkTypesForReason");
5569         final long identity = Binder.clearCallingIdentity();
5570         try {
5571             return getPhoneFromSubId(subId).getAllowedNetworkTypes(reason);
5572         } finally {
5573             Binder.restoreCallingIdentity(identity);
5574         }
5575     }
5576 
5577     /**
5578      * Get the effective allowed network types on the device.
5579      * This API will return an intersection of allowed network types for all reasons,
5580      * including the configuration done through setAllowedNetworkTypes
5581      *
5582      * @param subId the id of the subscription.
5583      * @return the allowed network types
5584      */
5585     @Override
getEffectiveAllowedNetworkTypes(int subId)5586     public long getEffectiveAllowedNetworkTypes(int subId) {
5587         TelephonyPermissions
5588                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
5589                         mApp, subId, "getEffectiveAllowedNetworkTypes");
5590         final long identity = Binder.clearCallingIdentity();
5591         try {
5592             return getPhoneFromSubId(subId).getEffectiveAllowedNetworkTypes();
5593         } finally {
5594             Binder.restoreCallingIdentity(identity);
5595         }
5596     }
5597 
5598     /**
5599      * Set the allowed network types of the device and
5600      * provide the reason triggering the allowed network change.
5601      *
5602      * @param subId the id of the subscription.
5603      * @param reason the reason the allowed network type change is taking place
5604      * @param allowedNetworkTypes the allowed network types.
5605      * @return true on success; false on any failure.
5606      */
5607     @Override
setAllowedNetworkTypesForReason(int subId, @TelephonyManager.AllowedNetworkTypesReason int reason, long allowedNetworkTypes)5608     public boolean setAllowedNetworkTypesForReason(int subId,
5609             @TelephonyManager.AllowedNetworkTypesReason int reason, long allowedNetworkTypes) {
5610         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5611                 mApp, subId, "setAllowedNetworkTypesForReason");
5612         final long identity = Binder.clearCallingIdentity();
5613         try {
5614             getPhoneFromSubId(subId).setAllowedNetworkTypes(reason, allowedNetworkTypes);
5615             int preferredNetworkMode = Settings.Global.getInt(mApp.getContentResolver(),
5616                     Settings.Global.PREFERRED_NETWORK_MODE + subId,
5617                     RILConstants.PREFERRED_NETWORK_MODE);
5618             return setPreferredNetworkType(subId, preferredNetworkMode);
5619         } finally {
5620             Binder.restoreCallingIdentity(identity);
5621         }
5622     }
5623 
5624     /**
5625      * Check whether DUN APN is required for tethering with subId.
5626      *
5627      * @param subId the id of the subscription to require tethering.
5628      * @return {@code true} if DUN APN is required for tethering.
5629      * @hide
5630      */
5631     @Override
isTetheringApnRequiredForSubscriber(int subId)5632     public boolean isTetheringApnRequiredForSubscriber(int subId) {
5633         enforceModifyPermission();
5634         final long identity = Binder.clearCallingIdentity();
5635         final Phone phone = getPhone(subId);
5636         try {
5637             if (phone != null) {
5638                 return phone.hasMatchedTetherApnSetting();
5639             } else {
5640                 return false;
5641             }
5642         } finally {
5643             Binder.restoreCallingIdentity(identity);
5644         }
5645     }
5646 
5647     /**
5648      * Set mobile data enabled
5649      * Used by the user through settings etc to turn on/off mobile data
5650      *
5651      * @param enable {@code true} turn turn data on, else {@code false}
5652      */
5653     @Override
setUserDataEnabled(int subId, boolean enable)5654     public void setUserDataEnabled(int subId, boolean enable) {
5655         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5656                 mApp, subId, "setUserDataEnabled");
5657 
5658         final long identity = Binder.clearCallingIdentity();
5659         try {
5660             int phoneId = mSubscriptionController.getPhoneId(subId);
5661             if (DBG) log("setUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
5662             Phone phone = PhoneFactory.getPhone(phoneId);
5663             if (phone != null) {
5664                 if (DBG) log("setUserDataEnabled: subId=" + subId + " enable=" + enable);
5665                 phone.getDataEnabledSettings().setUserDataEnabled(enable);
5666             } else {
5667                 loge("setUserDataEnabled: no phone found. Invalid subId=" + subId);
5668             }
5669         } finally {
5670             Binder.restoreCallingIdentity(identity);
5671         }
5672     }
5673 
5674     /**
5675      * Enable or disable always reporting signal strength changes from radio.
5676      *
5677      * @param isEnable {@code true} for enabling; {@code false} for disabling.
5678      */
5679     @Override
setAlwaysReportSignalStrength(int subId, boolean isEnable)5680     public void setAlwaysReportSignalStrength(int subId, boolean isEnable) {
5681         enforceModifyPermission();
5682         enforceSystemCaller();
5683 
5684         final long identity = Binder.clearCallingIdentity();
5685         final Phone phone = getPhone(subId);
5686         try {
5687             if (phone != null) {
5688                 if (DBG) {
5689                     log("setAlwaysReportSignalStrength: subId=" + subId
5690                             + " isEnable=" + isEnable);
5691                 }
5692                 phone.setAlwaysReportSignalStrength(isEnable);
5693             } else {
5694                 loge("setAlwaysReportSignalStrength: no phone found for subId="
5695                         + subId);
5696             }
5697         } finally {
5698             Binder.restoreCallingIdentity(identity);
5699         }
5700     }
5701 
5702     /**
5703      * Get the user enabled state of Mobile Data.
5704      *
5705      * TODO: remove and use isUserDataEnabled.
5706      * This can't be removed now because some vendor codes
5707      * calls through ITelephony directly while they should
5708      * use TelephonyManager.
5709      *
5710      * @return true on enabled
5711      */
5712     @Override
getDataEnabled(int subId)5713     public boolean getDataEnabled(int subId) {
5714         return isUserDataEnabled(subId);
5715     }
5716 
5717     /**
5718      * Get whether mobile data is enabled per user setting.
5719      *
5720      * There are other factors deciding whether mobile data is actually enabled, but they are
5721      * not considered here. See {@link #isDataEnabled(int)} for more details.
5722      *
5723      * Accepts either ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE or carrier privileges.
5724      *
5725      * @return {@code true} if data is enabled else {@code false}
5726      */
5727     @Override
isUserDataEnabled(int subId)5728     public boolean isUserDataEnabled(int subId) {
5729         try {
5730             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
5731                     null);
5732         } catch (Exception e) {
5733             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5734                     mApp, subId, "isUserDataEnabled");
5735         }
5736 
5737         final long identity = Binder.clearCallingIdentity();
5738         try {
5739             int phoneId = mSubscriptionController.getPhoneId(subId);
5740             if (DBG) log("isUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
5741             Phone phone = PhoneFactory.getPhone(phoneId);
5742             if (phone != null) {
5743                 boolean retVal = phone.isUserDataEnabled();
5744                 if (DBG) log("isUserDataEnabled: subId=" + subId + " retVal=" + retVal);
5745                 return retVal;
5746             } else {
5747                 if (DBG) loge("isUserDataEnabled: no phone subId=" + subId + " retVal=false");
5748                 return false;
5749             }
5750         } finally {
5751             Binder.restoreCallingIdentity(identity);
5752         }
5753     }
5754 
5755     /**
5756      * Checks if the device is capable of mobile data by considering whether whether the
5757      * user has enabled mobile data, whether the carrier has enabled mobile data, and
5758      * whether the network policy allows data connections.
5759      *
5760      * @return {@code true} if the overall data connection is capable; {@code false} if not.
5761      */
5762     @Override
isDataEnabled(int subId)5763     public boolean isDataEnabled(int subId) {
5764         enforceReadPrivilegedPermission("isDataEnabled");
5765 
5766         final long identity = Binder.clearCallingIdentity();
5767         try {
5768             int phoneId = mSubscriptionController.getPhoneId(subId);
5769             if (DBG) log("isDataEnabled: subId=" + subId + " phoneId=" + phoneId);
5770             Phone phone = PhoneFactory.getPhone(phoneId);
5771             if (phone != null) {
5772                 boolean retVal = phone.getDataEnabledSettings().isDataEnabled();
5773                 if (DBG) log("isDataEnabled: subId=" + subId + " retVal=" + retVal);
5774                 return retVal;
5775             } else {
5776                 if (DBG) loge("isDataEnabled: no phone subId=" + subId + " retVal=false");
5777                 return false;
5778             }
5779         } finally {
5780             Binder.restoreCallingIdentity(identity);
5781         }
5782     }
5783 
getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, int uid, Phone phone)5784     private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, int uid,
5785             Phone phone) {
5786         if (uid == Process.SYSTEM_UID || uid == Process.PHONE_UID) {
5787             // Skip the check if it's one of these special uids
5788             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
5789         }
5790 
5791         //load access rules from carrier configs, and check those as well: b/139133814
5792         SubscriptionController subController = SubscriptionController.getInstance();
5793         if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
5794                 || subController == null) return privilegeFromSim;
5795 
5796         PackageManager pkgMgr = phone.getContext().getPackageManager();
5797         String[] packages = pkgMgr.getPackagesForUid(uid);
5798 
5799         final long identity = Binder.clearCallingIdentity();
5800         try {
5801             SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
5802             SubscriptionManager subManager = (SubscriptionManager)
5803                     phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
5804             for (String pkg : packages) {
5805                 if (subManager.canManageSubscription(subInfo, pkg)) {
5806                     return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
5807                 }
5808             }
5809             return privilegeFromSim;
5810         } finally {
5811             Binder.restoreCallingIdentity(identity);
5812         }
5813     }
5814 
getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, Phone phone, String pkgName)5815     private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, Phone phone,
5816             String pkgName) {
5817         //load access rules from carrier configs, and check those as well: b/139133814
5818         SubscriptionController subController = SubscriptionController.getInstance();
5819         if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
5820                 || subController == null) return privilegeFromSim;
5821 
5822         final long identity = Binder.clearCallingIdentity();
5823         try {
5824             SubscriptionInfo subInfo = subController.getSubscriptionInfo(phone.getSubId());
5825             SubscriptionManager subManager = (SubscriptionManager)
5826                     phone.getContext().getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
5827             return subManager.canManageSubscription(subInfo, pkgName)
5828                 ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS : privilegeFromSim;
5829         } finally {
5830             Binder.restoreCallingIdentity(identity);
5831         }
5832     }
5833 
5834     @Override
getCarrierPrivilegeStatus(int subId)5835     public int getCarrierPrivilegeStatus(int subId) {
5836         final Phone phone = getPhone(subId);
5837         if (phone == null) {
5838             loge("getCarrierPrivilegeStatus: Invalid subId");
5839             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
5840         }
5841         UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
5842         if (card == null) {
5843             loge("getCarrierPrivilegeStatus: No UICC");
5844             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
5845         }
5846 
5847         return getCarrierPrivilegeStatusFromCarrierConfigRules(
5848             card.getCarrierPrivilegeStatusForCurrentTransaction(
5849                 phone.getContext().getPackageManager()), Binder.getCallingUid(), phone);
5850     }
5851 
5852     @Override
getCarrierPrivilegeStatusForUid(int subId, int uid)5853     public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
5854         enforceReadPrivilegedPermission("getCarrierPrivilegeStatusForUid");
5855         final Phone phone = getPhone(subId);
5856         if (phone == null) {
5857             loge("getCarrierPrivilegeStatusForUid: Invalid subId");
5858             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
5859         }
5860         UiccProfile profile =
5861                 UiccController.getInstance().getUiccProfileForPhone(phone.getPhoneId());
5862         if (profile == null) {
5863             loge("getCarrierPrivilegeStatusForUid: No UICC");
5864             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
5865         }
5866         return getCarrierPrivilegeStatusFromCarrierConfigRules(
5867                 profile.getCarrierPrivilegeStatusForUid(
5868                         phone.getContext().getPackageManager(), uid), uid, phone);
5869     }
5870 
5871     @Override
checkCarrierPrivilegesForPackage(int subId, String pkgName)5872     public int checkCarrierPrivilegesForPackage(int subId, String pkgName) {
5873         if (TextUtils.isEmpty(pkgName)) {
5874             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
5875         }
5876 
5877         int phoneId = SubscriptionManager.getPhoneId(subId);
5878         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
5879         if (card == null) {
5880             loge("checkCarrierPrivilegesForPackage: No UICC on subId " + subId);
5881             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
5882         }
5883         return getCarrierPrivilegeStatusFromCarrierConfigRules(
5884             card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName),
5885             getPhone(phoneId), pkgName);
5886     }
5887 
5888     @Override
checkCarrierPrivilegesForPackageAnyPhone(String pkgName)5889     public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
5890         if (TextUtils.isEmpty(pkgName))
5891             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
5892         int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
5893         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
5894             UiccCard card = UiccController.getInstance().getUiccCard(i);
5895             if (card == null) {
5896               // No UICC in that slot.
5897               continue;
5898             }
5899 
5900             result = getCarrierPrivilegeStatusFromCarrierConfigRules(
5901                 card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName),
5902                 getPhone(i), pkgName);
5903             if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
5904                 break;
5905             }
5906         }
5907 
5908         return result;
5909     }
5910 
5911     @Override
getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId)5912     public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
5913         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
5914             loge("phoneId " + phoneId + " is not valid.");
5915             return null;
5916         }
5917         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
5918         if (card == null) {
5919             loge("getCarrierPackageNamesForIntentAndPhone: No UICC");
5920             return null ;
5921         }
5922         return card.getCarrierPackageNamesForIntent(mApp.getPackageManager(), intent);
5923     }
5924 
5925     @Override
getPackagesWithCarrierPrivileges(int phoneId)5926     public List<String> getPackagesWithCarrierPrivileges(int phoneId) {
5927         PackageManager pm = mApp.getPackageManager();
5928         List<String> privilegedPackages = new ArrayList<>();
5929         List<PackageInfo> packages = null;
5930         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
5931         // has UICC in that slot.
5932         if (card != null) {
5933             if (card.hasCarrierPrivilegeRules()) {
5934                 if (packages == null) {
5935                     // Only check packages in user 0 for now
5936                     packages = pm.getInstalledPackagesAsUser(
5937                         PackageManager.MATCH_DISABLED_COMPONENTS
5938                             | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
5939                             | PackageManager.GET_SIGNING_CERTIFICATES,
5940                             UserHandle.SYSTEM.getIdentifier());
5941                 }
5942                 for (int p = packages.size() - 1; p >= 0; p--) {
5943                     PackageInfo pkgInfo = packages.get(p);
5944                     if (pkgInfo != null && pkgInfo.packageName != null
5945                             && card.getCarrierPrivilegeStatus(pkgInfo)
5946                             == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
5947                         privilegedPackages.add(pkgInfo.packageName);
5948                     }
5949                 }
5950             }
5951         }
5952         return privilegedPackages;
5953     }
5954 
5955     @Override
getPackagesWithCarrierPrivilegesForAllPhones()5956     public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
5957         enforceReadPrivilegedPermission("getPackagesWithCarrierPrivilegesForAllPhones");
5958 
5959         final long identity = Binder.clearCallingIdentity();
5960 
5961         List<String> privilegedPackages = new ArrayList<>();
5962         try {
5963             for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
5964                 privilegedPackages.addAll(getPackagesWithCarrierPrivileges(i));
5965             }
5966         } finally {
5967             Binder.restoreCallingIdentity(identity);
5968         }
5969         return privilegedPackages;
5970     }
5971 
getIccId(int subId)5972     private String getIccId(int subId) {
5973         final Phone phone = getPhone(subId);
5974         UiccCard card = phone == null ? null : phone.getUiccCard();
5975         if (card == null) {
5976             loge("getIccId: No UICC");
5977             return null;
5978         }
5979         String iccId = card.getIccId();
5980         if (TextUtils.isEmpty(iccId)) {
5981             loge("getIccId: ICC ID is null or empty.");
5982             return null;
5983         }
5984         return iccId;
5985     }
5986 
5987     @Override
setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number)5988     public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
5989             String number) {
5990         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
5991                 subId, "setLine1NumberForDisplayForSubscriber");
5992 
5993         final long identity = Binder.clearCallingIdentity();
5994         try {
5995             final String iccId = getIccId(subId);
5996             final Phone phone = getPhone(subId);
5997             if (phone == null) {
5998                 return false;
5999             }
6000             final String subscriberId = phone.getSubscriberId();
6001 
6002             if (DBG_MERGE) {
6003                 Rlog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
6004                         + subscriberId + " to " + number);
6005             }
6006 
6007             if (TextUtils.isEmpty(iccId)) {
6008                 return false;
6009             }
6010 
6011             final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
6012 
6013             final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
6014             if (alphaTag == null) {
6015                 editor.remove(alphaTagPrefKey);
6016             } else {
6017                 editor.putString(alphaTagPrefKey, alphaTag);
6018             }
6019 
6020             // Record both the line number and IMSI for this ICCID, since we need to
6021             // track all merged IMSIs based on line number
6022             final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
6023             final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
6024             if (number == null) {
6025                 editor.remove(numberPrefKey);
6026                 editor.remove(subscriberPrefKey);
6027             } else {
6028                 editor.putString(numberPrefKey, number);
6029                 editor.putString(subscriberPrefKey, subscriberId);
6030             }
6031 
6032             editor.commit();
6033             return true;
6034         } finally {
6035             Binder.restoreCallingIdentity(identity);
6036         }
6037     }
6038 
6039     @Override
getLine1NumberForDisplay(int subId, String callingPackage, String callingFeatureId)6040     public String getLine1NumberForDisplay(int subId, String callingPackage,
6041             String callingFeatureId) {
6042         // This is open to apps with WRITE_SMS.
6043         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
6044                 mApp, subId, callingPackage, callingFeatureId, "getLine1NumberForDisplay")) {
6045             if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
6046             return null;
6047         }
6048 
6049         final long identity = Binder.clearCallingIdentity();
6050         try {
6051             String iccId = getIccId(subId);
6052             if (iccId != null) {
6053                 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
6054                 if (DBG_MERGE) {
6055                     log("getLine1NumberForDisplay returning "
6056                             + mTelephonySharedPreferences.getString(numberPrefKey, null));
6057                 }
6058                 return mTelephonySharedPreferences.getString(numberPrefKey, null);
6059             }
6060             if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
6061             return null;
6062         } finally {
6063             Binder.restoreCallingIdentity(identity);
6064         }
6065     }
6066 
6067     @Override
getLine1AlphaTagForDisplay(int subId, String callingPackage, String callingFeatureId)6068     public String getLine1AlphaTagForDisplay(int subId, String callingPackage,
6069             String callingFeatureId) {
6070         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6071                 mApp, subId, callingPackage, callingFeatureId, "getLine1AlphaTagForDisplay")) {
6072             return null;
6073         }
6074 
6075         final long identity = Binder.clearCallingIdentity();
6076         try {
6077             String iccId = getIccId(subId);
6078             if (iccId != null) {
6079                 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
6080                 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
6081             }
6082             return null;
6083         } finally {
6084             Binder.restoreCallingIdentity(identity);
6085         }
6086     }
6087 
6088     @Override
getMergedSubscriberIds(int subId, String callingPackage, String callingFeatureId)6089     public String[] getMergedSubscriberIds(int subId, String callingPackage,
6090             String callingFeatureId) {
6091         // This API isn't public, so no need to provide a valid subscription ID - we're not worried
6092         // about carrier-privileged callers not having access.
6093         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6094                 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
6095                 callingFeatureId, "getMergedSubscriberIds")) {
6096             return null;
6097         }
6098 
6099         // Clear calling identity, when calling TelephonyManager, because callerUid must be
6100         // the process, where TelephonyManager was instantiated.
6101         // Otherwise AppOps check will fail.
6102         final long identity  = Binder.clearCallingIdentity();
6103         try {
6104             final Context context = mApp;
6105             final TelephonyManager tele = TelephonyManager.from(context);
6106             final SubscriptionManager sub = SubscriptionManager.from(context);
6107 
6108             // Figure out what subscribers are currently active
6109             final ArraySet<String> activeSubscriberIds = new ArraySet<>();
6110 
6111             // Only consider subs which match the current subId
6112             // This logic can be simplified. See b/131189269 for progress.
6113             if (isActiveSubscription(subId)) {
6114                 activeSubscriberIds.add(tele.getSubscriberId(subId));
6115             }
6116 
6117             // First pass, find a number override for an active subscriber
6118             String mergeNumber = null;
6119             final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
6120             for (String key : prefs.keySet()) {
6121                 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
6122                     final String subscriberId = (String) prefs.get(key);
6123                     if (activeSubscriberIds.contains(subscriberId)) {
6124                         final String iccId = key.substring(
6125                                 PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
6126                         final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
6127                         mergeNumber = (String) prefs.get(numberKey);
6128                         if (DBG_MERGE) {
6129                             Rlog.d(LOG_TAG, "Found line number " + mergeNumber
6130                                     + " for active subscriber " + subscriberId);
6131                         }
6132                         if (!TextUtils.isEmpty(mergeNumber)) {
6133                             break;
6134                         }
6135                     }
6136                 }
6137             }
6138 
6139             // Shortcut when no active merged subscribers
6140             if (TextUtils.isEmpty(mergeNumber)) {
6141                 return null;
6142             }
6143 
6144             // Second pass, find all subscribers under that line override
6145             final ArraySet<String> result = new ArraySet<>();
6146             for (String key : prefs.keySet()) {
6147                 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
6148                     final String number = (String) prefs.get(key);
6149                     if (mergeNumber.equals(number)) {
6150                         final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
6151                         final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
6152                         final String subscriberId = (String) prefs.get(subscriberKey);
6153                         if (!TextUtils.isEmpty(subscriberId)) {
6154                             result.add(subscriberId);
6155                         }
6156                     }
6157                 }
6158             }
6159 
6160             final String[] resultArray = result.toArray(new String[result.size()]);
6161             Arrays.sort(resultArray);
6162             if (DBG_MERGE) {
6163                 Rlog.d(LOG_TAG,
6164                         "Found subscribers " + Arrays.toString(resultArray) + " after merge");
6165             }
6166             return resultArray;
6167         } finally {
6168             Binder.restoreCallingIdentity(identity);
6169         }
6170     }
6171 
6172     @Override
getMergedSubscriberIdsFromGroup(int subId, String callingPackage)6173     public String[] getMergedSubscriberIdsFromGroup(int subId, String callingPackage) {
6174         enforceReadPrivilegedPermission("getMergedSubscriberIdsFromGroup");
6175 
6176         final long identity = Binder.clearCallingIdentity();
6177         try {
6178             final TelephonyManager telephonyManager = mApp.getSystemService(
6179                     TelephonyManager.class);
6180             String subscriberId = telephonyManager.getSubscriberId(subId);
6181             if (subscriberId == null) {
6182                 if (DBG) {
6183                     log("getMergedSubscriberIdsFromGroup can't find subscriberId for subId "
6184                             + subId);
6185                 }
6186                 return null;
6187             }
6188 
6189             final SubscriptionInfo info = SubscriptionController.getInstance()
6190                     .getSubscriptionInfo(subId);
6191             final ParcelUuid groupUuid = info.getGroupUuid();
6192             // If it doesn't belong to any group, return just subscriberId of itself.
6193             if (groupUuid == null) {
6194                 return new String[]{subscriberId};
6195             }
6196 
6197             // Get all subscriberIds from the group.
6198             final List<String> mergedSubscriberIds = new ArrayList<>();
6199             final List<SubscriptionInfo> groupInfos = SubscriptionController.getInstance()
6200                     .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
6201                             null);
6202             for (SubscriptionInfo subInfo : groupInfos) {
6203                 subscriberId = telephonyManager.getSubscriberId(subInfo.getSubscriptionId());
6204                 if (subscriberId != null) {
6205                     mergedSubscriberIds.add(subscriberId);
6206                 }
6207             }
6208 
6209             return mergedSubscriberIds.toArray(new String[mergedSubscriberIds.size()]);
6210         } finally {
6211             Binder.restoreCallingIdentity(identity);
6212 
6213         }
6214     }
6215 
6216     @Override
setOperatorBrandOverride(int subId, String brand)6217     public boolean setOperatorBrandOverride(int subId, String brand) {
6218         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
6219                 subId, "setOperatorBrandOverride");
6220 
6221         final long identity = Binder.clearCallingIdentity();
6222         try {
6223             final Phone phone = getPhone(subId);
6224             return phone == null ? false : phone.setOperatorBrandOverride(brand);
6225         } finally {
6226             Binder.restoreCallingIdentity(identity);
6227         }
6228     }
6229 
6230     @Override
setRoamingOverride(int subId, List<String> gsmRoamingList, List<String> gsmNonRoamingList, List<String> cdmaRoamingList, List<String> cdmaNonRoamingList)6231     public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
6232             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
6233             List<String> cdmaNonRoamingList) {
6234         TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
6235                 mApp, subId, "setRoamingOverride");
6236 
6237         final long identity = Binder.clearCallingIdentity();
6238         try {
6239             final Phone phone = getPhone(subId);
6240             if (phone == null) {
6241                 return false;
6242             }
6243             return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
6244                     cdmaNonRoamingList);
6245         } finally {
6246             Binder.restoreCallingIdentity(identity);
6247         }
6248     }
6249 
6250     @Override
6251     @Deprecated
invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp)6252     public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
6253         enforceModifyPermission();
6254 
6255         int returnValue = 0;
6256         try {
6257             AsyncResult result = (AsyncResult) sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
6258             if(result.exception == null) {
6259                 if (result.result != null) {
6260                     byte[] responseData = (byte[])(result.result);
6261                     if(responseData.length > oemResp.length) {
6262                         Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
6263                                 responseData.length +  "bytes. Buffer Size is " +
6264                                 oemResp.length + "bytes.");
6265                     }
6266                     System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
6267                     returnValue = responseData.length;
6268                 }
6269             } else {
6270                 CommandException ex = (CommandException) result.exception;
6271                 returnValue = ex.getCommandError().ordinal();
6272                 if(returnValue > 0) returnValue *= -1;
6273             }
6274         } catch (RuntimeException e) {
6275             Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
6276             returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
6277             if(returnValue > 0) returnValue *= -1;
6278         }
6279 
6280         return returnValue;
6281     }
6282 
6283     @Override
setRadioCapability(RadioAccessFamily[] rafs)6284     public void setRadioCapability(RadioAccessFamily[] rafs) {
6285         try {
6286             ProxyController.getInstance().setRadioCapability(rafs);
6287         } catch (RuntimeException e) {
6288             Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
6289         }
6290     }
6291 
6292     @Override
getRadioAccessFamily(int phoneId, String callingPackage)6293     public int getRadioAccessFamily(int phoneId, String callingPackage) {
6294         Phone phone = PhoneFactory.getPhone(phoneId);
6295         int raf = RadioAccessFamily.RAF_UNKNOWN;
6296         if (phone == null) {
6297             return raf;
6298         }
6299         final long identity = Binder.clearCallingIdentity();
6300         try {
6301             TelephonyPermissions
6302                     .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
6303                             mApp, phone.getSubId(), "getRadioAccessFamily");
6304             raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
6305         } finally {
6306             Binder.restoreCallingIdentity(identity);
6307         }
6308         return raf;
6309     }
6310 
6311     @Override
enableVideoCalling(boolean enable)6312     public void enableVideoCalling(boolean enable) {
6313         final Phone defaultPhone = getDefaultPhone();
6314         enforceModifyPermission();
6315 
6316         final long identity = Binder.clearCallingIdentity();
6317         try {
6318             ImsManager.getInstance(defaultPhone.getContext(),
6319                     defaultPhone.getPhoneId()).setVtSetting(enable);
6320         } finally {
6321             Binder.restoreCallingIdentity(identity);
6322         }
6323     }
6324 
6325     @Override
isVideoCallingEnabled(String callingPackage, String callingFeatureId)6326     public boolean isVideoCallingEnabled(String callingPackage, String callingFeatureId) {
6327         final Phone defaultPhone = getDefaultPhone();
6328         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
6329                 callingPackage, callingFeatureId, "isVideoCallingEnabled")) {
6330             return false;
6331         }
6332 
6333         final long identity = Binder.clearCallingIdentity();
6334         try {
6335             // Check the user preference and the  system-level IMS setting. Even if the user has
6336             // enabled video calling, if IMS is disabled we aren't able to support video calling.
6337             // In the long run, we may instead need to check if there exists a connection service
6338             // which can support video calling.
6339             ImsManager imsManager =
6340                     ImsManager.getInstance(defaultPhone.getContext(), defaultPhone.getPhoneId());
6341             return imsManager.isVtEnabledByPlatform()
6342                     && imsManager.isEnhanced4gLteModeSettingEnabledByUser()
6343                     && imsManager.isVtEnabledByUser();
6344         } finally {
6345             Binder.restoreCallingIdentity(identity);
6346         }
6347     }
6348 
6349     @Override
canChangeDtmfToneLength(int subId, String callingPackage, String callingFeatureId)6350     public boolean canChangeDtmfToneLength(int subId, String callingPackage,
6351             String callingFeatureId) {
6352         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6353                 mApp, subId, callingPackage, callingFeatureId,
6354                 "isVideoCallingEnabled")) {
6355             return false;
6356         }
6357 
6358         final long identity = Binder.clearCallingIdentity();
6359         try {
6360             CarrierConfigManager configManager =
6361                     (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
6362             return configManager.getConfigForSubId(subId)
6363                     .getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
6364         } finally {
6365             Binder.restoreCallingIdentity(identity);
6366         }
6367     }
6368 
6369     @Override
isWorldPhone(int subId, String callingPackage, String callingFeatureId)6370     public boolean isWorldPhone(int subId, String callingPackage, String callingFeatureId) {
6371         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6372                 mApp, subId, callingPackage, callingFeatureId, "isVideoCallingEnabled")) {
6373             return false;
6374         }
6375 
6376         final long identity = Binder.clearCallingIdentity();
6377         try {
6378             CarrierConfigManager configManager =
6379                     (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
6380             return configManager.getConfigForSubId(subId)
6381                     .getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
6382         } finally {
6383             Binder.restoreCallingIdentity(identity);
6384         }
6385     }
6386 
6387     @Override
isTtyModeSupported()6388     public boolean isTtyModeSupported() {
6389         TelecomManager telecomManager = mApp.getSystemService(TelecomManager.class);
6390         return telecomManager.isTtySupported();
6391     }
6392 
6393     @Override
isHearingAidCompatibilitySupported()6394     public boolean isHearingAidCompatibilitySupported() {
6395         final long identity = Binder.clearCallingIdentity();
6396         try {
6397             return mApp.getResources().getBoolean(R.bool.hac_enabled);
6398         } finally {
6399             Binder.restoreCallingIdentity(identity);
6400         }
6401     }
6402 
6403     /**
6404      * Determines whether the device currently supports RTT (Real-time text). Based both on carrier
6405      * support for the feature and device firmware support.
6406      *
6407      * @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
6408      */
6409     @Override
isRttSupported(int subscriptionId)6410     public boolean isRttSupported(int subscriptionId) {
6411         final long identity = Binder.clearCallingIdentity();
6412         final Phone phone = getPhone(subscriptionId);
6413         if (phone == null) {
6414             loge("isRttSupported: no Phone found. Invalid subId:" + subscriptionId);
6415             return false;
6416         }
6417         try {
6418             boolean isCarrierSupported = mApp.getCarrierConfigForSubId(subscriptionId).getBoolean(
6419                     CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
6420             boolean isDeviceSupported =
6421                     phone.getContext().getResources().getBoolean(R.bool.config_support_rtt);
6422             return isCarrierSupported && isDeviceSupported;
6423         } finally {
6424             Binder.restoreCallingIdentity(identity);
6425         }
6426     }
6427 
6428     /**
6429      * Determines whether the user has turned on RTT. If the carrier wants to ignore the user-set
6430      * RTT setting, will return true if the device and carrier both support RTT.
6431      * Otherwise. only returns true if the device and carrier both also support RTT.
6432      */
isRttEnabled(int subscriptionId)6433     public boolean isRttEnabled(int subscriptionId) {
6434         final long identity = Binder.clearCallingIdentity();
6435         try {
6436             boolean isRttSupported = isRttSupported(subscriptionId);
6437             boolean isUserRttSettingOn = Settings.Secure.getInt(
6438                     mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
6439             boolean shouldIgnoreUserRttSetting = mApp.getCarrierConfigForSubId(subscriptionId)
6440                     .getBoolean(CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL);
6441             return isRttSupported && (isUserRttSettingOn || shouldIgnoreUserRttSetting);
6442         } finally {
6443             Binder.restoreCallingIdentity(identity);
6444         }
6445     }
6446 
6447     @Deprecated
6448     @Override
getDeviceId(String callingPackage)6449     public String getDeviceId(String callingPackage) {
6450         return getDeviceIdWithFeature(callingPackage, null);
6451     }
6452 
6453     /**
6454      * Returns the unique device ID of phone, for example, the IMEI for
6455      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
6456      *
6457      * <p>Requires Permission:
6458      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
6459      */
6460     @Override
getDeviceIdWithFeature(String callingPackage, String callingFeatureId)6461     public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) {
6462         final Phone phone = PhoneFactory.getPhone(0);
6463         if (phone == null) {
6464             return null;
6465         }
6466         int subId = phone.getSubId();
6467         if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
6468                 callingPackage, callingFeatureId, "getDeviceId")) {
6469             return null;
6470         }
6471 
6472         final long identity = Binder.clearCallingIdentity();
6473         try {
6474             return phone.getDeviceId();
6475         } finally {
6476             Binder.restoreCallingIdentity(identity);
6477         }
6478     }
6479 
6480     /**
6481      * {@hide}
6482      * Returns the IMS Registration Status on a particular subid
6483      *
6484      * @param subId
6485      */
isImsRegistered(int subId)6486     public boolean isImsRegistered(int subId) {
6487         Phone phone = getPhone(subId);
6488         if (phone != null) {
6489             return phone.isImsRegistered();
6490         } else {
6491             return false;
6492         }
6493     }
6494 
6495     @Override
getSubIdForPhoneAccount(PhoneAccount phoneAccount)6496     public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
6497         final long identity = Binder.clearCallingIdentity();
6498         try {
6499             return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
6500         } finally {
6501             Binder.restoreCallingIdentity(identity);
6502         }
6503     }
6504 
6505     @Override
getSubIdForPhoneAccountHandle( PhoneAccountHandle phoneAccountHandle, String callingPackage, String callingFeatureId)6506     public int getSubIdForPhoneAccountHandle(
6507             PhoneAccountHandle phoneAccountHandle, String callingPackage, String callingFeatureId) {
6508         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, getDefaultSubscription(),
6509                 callingPackage, callingFeatureId, "getSubIdForPhoneAccountHandle")) {
6510             throw new SecurityException("Requires READ_PHONE_STATE permission.");
6511         }
6512         final long identity = Binder.clearCallingIdentity();
6513         try {
6514             return PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle);
6515         } finally {
6516             Binder.restoreCallingIdentity(identity);
6517         }
6518     }
6519 
6520     @Override
getPhoneAccountHandleForSubscriptionId(int subscriptionId)6521     public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
6522         enforceReadPrivilegedPermission("getPhoneAccountHandleForSubscriptionId, "
6523                 + "subscriptionId: " + subscriptionId);
6524         final long identity = Binder.clearCallingIdentity();
6525         try {
6526             Phone phone = getPhone(subscriptionId);
6527             if (phone == null) {
6528                 return null;
6529             }
6530             return PhoneUtils.makePstnPhoneAccountHandle(phone);
6531         } finally {
6532             Binder.restoreCallingIdentity(identity);
6533         }
6534     }
6535 
6536     /**
6537      * @return the VoWiFi calling availability.
6538      */
isWifiCallingAvailable(int subId)6539     public boolean isWifiCallingAvailable(int subId) {
6540         final long identity = Binder.clearCallingIdentity();
6541         try {
6542             Phone phone = getPhone(subId);
6543             if (phone != null) {
6544                 return phone.isWifiCallingEnabled();
6545             } else {
6546                 return false;
6547             }
6548         } finally {
6549             Binder.restoreCallingIdentity(identity);
6550         }
6551     }
6552 
6553     /**
6554      * @return the VT calling availability.
6555      */
isVideoTelephonyAvailable(int subId)6556     public boolean isVideoTelephonyAvailable(int subId) {
6557         final long identity = Binder.clearCallingIdentity();
6558         try {
6559             Phone phone = getPhone(subId);
6560             if (phone != null) {
6561                 return phone.isVideoEnabled();
6562             } else {
6563                 return false;
6564             }
6565         } finally {
6566             Binder.restoreCallingIdentity(identity);
6567         }
6568     }
6569 
6570     /**
6571      * @return the IMS registration technology for the MMTEL feature. Valid return values are
6572      * defined in {@link ImsRegistrationImplBase}.
6573      */
getImsRegTechnologyForMmTel(int subId)6574     public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel(int subId) {
6575         final long identity = Binder.clearCallingIdentity();
6576         try {
6577             Phone phone = getPhone(subId);
6578             if (phone != null) {
6579                 return phone.getImsRegistrationTech();
6580             } else {
6581                 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
6582             }
6583         } finally {
6584             Binder.restoreCallingIdentity(identity);
6585         }
6586     }
6587 
6588     @Override
factoryReset(int subId)6589     public void factoryReset(int subId) {
6590         enforceSettingsPermission();
6591         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
6592             return;
6593         }
6594 
6595         final long identity = Binder.clearCallingIdentity();
6596 
6597         try {
6598             if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
6599                     UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
6600                 setUserDataEnabled(subId, getDefaultDataEnabled());
6601                 setNetworkSelectionModeAutomatic(subId);
6602                 setPreferredNetworkType(subId, getDefaultNetworkType(subId));
6603                 setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
6604                 CarrierInfoManager.deleteAllCarrierKeysForImsiEncryption(mApp);
6605             }
6606             // There has been issues when Sms raw table somehow stores orphan
6607             // fragments. They lead to garbled message when new fragments come
6608             // in and combined with those stale ones. In case this happens again,
6609             // user can reset all network settings which will clean up this table.
6610             cleanUpSmsRawTable(getDefaultPhone().getContext());
6611             // Clean up IMS settings as well here.
6612             int slotId = getSlotIndex(subId);
6613             if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
6614                 ImsManager.getInstance(mApp, slotId).factoryReset();
6615             }
6616 
6617             // Erase modem config if erase modem on network setting is enabled.
6618             String configValue = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_TELEPHONY,
6619                     RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED);
6620             if (configValue != null && Boolean.parseBoolean(configValue)) {
6621               sendEraseModemConfig(getDefaultPhone());
6622             }
6623         } finally {
6624             Binder.restoreCallingIdentity(identity);
6625         }
6626     }
6627 
cleanUpSmsRawTable(Context context)6628     private void cleanUpSmsRawTable(Context context) {
6629         ContentResolver resolver = context.getContentResolver();
6630         Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
6631         resolver.delete(uri, null, null);
6632     }
6633 
6634     @Override
getSimLocaleForSubscriber(int subId)6635     public String getSimLocaleForSubscriber(int subId) {
6636         enforceReadPrivilegedPermission("getSimLocaleForSubscriber, subId: " + subId);
6637         final Phone phone = getPhone(subId);
6638         if (phone == null) {
6639             log("getSimLocaleForSubscriber, invalid subId");
6640             return null;
6641         }
6642         final long identity = Binder.clearCallingIdentity();
6643         try {
6644             final SubscriptionInfo info = mSubscriptionController.getActiveSubscriptionInfo(subId,
6645                     phone.getContext().getOpPackageName(), null);
6646             if (info == null) {
6647                 log("getSimLocaleForSubscriber, inactive subId: " + subId);
6648                 return null;
6649             }
6650             // Try and fetch the locale from the carrier properties or from the SIM language
6651             // preferences (EF-PL and EF-LI)...
6652             final int mcc = info.getMcc();
6653             String simLanguage = null;
6654             final Locale localeFromDefaultSim = phone.getLocaleFromSimAndCarrierPrefs();
6655             if (localeFromDefaultSim != null) {
6656                 if (!localeFromDefaultSim.getCountry().isEmpty()) {
6657                     if (DBG) log("Using locale from subId: " + subId + " locale: "
6658                             + localeFromDefaultSim);
6659                     return localeFromDefaultSim.toLanguageTag();
6660                 } else {
6661                     simLanguage = localeFromDefaultSim.getLanguage();
6662                 }
6663             }
6664 
6665             // The SIM language preferences only store a language (e.g. fr = French), not an
6666             // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
6667             // the SIM and carrier preferences does not include a country we add the country
6668             // determined from the SIM MCC to provide an exact locale.
6669             final Locale mccLocale = LocaleUtils.getLocaleFromMcc(mApp, mcc, simLanguage);
6670             if (mccLocale != null) {
6671                 if (DBG) log("No locale from SIM, using mcc locale:" + mccLocale);
6672                 return mccLocale.toLanguageTag();
6673             }
6674 
6675             if (DBG) log("No locale found - returning null");
6676             return null;
6677         } finally {
6678             Binder.restoreCallingIdentity(identity);
6679         }
6680     }
6681 
getAllSubscriptionInfoList()6682     private List<SubscriptionInfo> getAllSubscriptionInfoList() {
6683         return mSubscriptionController.getAllSubInfoList(mApp.getOpPackageName(),
6684                 null);
6685     }
6686 
6687     /**
6688      * NOTE: this method assumes permission checks are done and caller identity has been cleared.
6689      */
getActiveSubscriptionInfoListPrivileged()6690     private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
6691         return mSubscriptionController.getActiveSubscriptionInfoList(mApp.getOpPackageName(),
6692                 null);
6693     }
6694 
6695     private final ModemActivityInfo mLastModemActivityInfo =
6696             new ModemActivityInfo(0, 0, 0, new int[0], 0);
6697 
6698     /**
6699      * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
6700      * representing the state of the modem.
6701      *
6702      * NOTE: The underlying implementation clears the modem state, so there should only ever be one
6703      * caller to it. Everyone should call this class to get cumulative data.
6704      * @hide
6705      */
6706     @Override
requestModemActivityInfo(ResultReceiver result)6707     public void requestModemActivityInfo(ResultReceiver result) {
6708         enforceModifyPermission();
6709         WorkSource workSource = getWorkSource(Binder.getCallingUid());
6710 
6711         final long identity = Binder.clearCallingIdentity();
6712         try {
6713             sendRequestAsync(CMD_GET_MODEM_ACTIVITY_INFO, result, null, workSource);
6714         } finally {
6715             Binder.restoreCallingIdentity(identity);
6716         }
6717     }
6718 
6719     // Checks that ModemActivityInfo is valid. Sleep time, Idle time, Rx time and Tx time should be
6720     // less than total activity duration.
isModemActivityInfoValid(ModemActivityInfo info)6721     private boolean isModemActivityInfoValid(ModemActivityInfo info) {
6722         if (info == null) {
6723             return false;
6724         }
6725         int activityDurationMs =
6726             (int) (info.getTimestamp() - mLastModemActivityInfo.getTimestamp());
6727         int totalTxTimeMs = 0;
6728         int[] txTimeMs = info.getTransmitTimeMillis();
6729         for (int i = 0; i < info.getTransmitPowerInfo().size(); i++) {
6730             totalTxTimeMs += txTimeMs[i];
6731         }
6732         return (info.isValid()
6733             && (info.getSleepTimeMillis() <= activityDurationMs)
6734             && (info.getIdleTimeMillis() <= activityDurationMs)
6735             && (info.getReceiveTimeMillis() <= activityDurationMs)
6736             && (totalTxTimeMs <= activityDurationMs));
6737     }
6738 
6739     /**
6740      * {@hide}
6741      * Returns the service state information on specified subscription.
6742      */
6743     @Override
getServiceStateForSubscriber(int subId, String callingPackage, String callingFeatureId)6744     public ServiceState getServiceStateForSubscriber(int subId, String callingPackage,
6745             String callingFeatureId) {
6746         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6747                 mApp, subId, callingPackage, callingFeatureId, "getServiceStateForSubscriber")) {
6748             return null;
6749         }
6750 
6751         LocationAccessPolicy.LocationPermissionResult fineLocationResult =
6752                 LocationAccessPolicy.checkLocationPermission(mApp,
6753                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
6754                                 .setCallingPackage(callingPackage)
6755                                 .setCallingFeatureId(callingFeatureId)
6756                                 .setCallingPid(Binder.getCallingPid())
6757                                 .setCallingUid(Binder.getCallingUid())
6758                                 .setMethod("getServiceStateForSubscriber")
6759                                 .setLogAsInfo(true)
6760                                 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
6761                                 .build());
6762 
6763         LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
6764                 LocationAccessPolicy.checkLocationPermission(mApp,
6765                         new LocationAccessPolicy.LocationPermissionQuery.Builder()
6766                                 .setCallingPackage(callingPackage)
6767                                 .setCallingFeatureId(callingFeatureId)
6768                                 .setCallingPid(Binder.getCallingPid())
6769                                 .setCallingUid(Binder.getCallingUid())
6770                                 .setMethod("getServiceStateForSubscriber")
6771                                 .setLogAsInfo(true)
6772                                 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
6773                                 .build());
6774         // We don't care about hard or soft here -- all we need to know is how much info to scrub.
6775         boolean hasFinePermission =
6776                 fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
6777         boolean hasCoarsePermission =
6778                 coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
6779 
6780         final long identity = Binder.clearCallingIdentity();
6781         try {
6782             final Phone phone = getPhone(subId);
6783             if (phone == null) {
6784                 return null;
6785             }
6786 
6787             ServiceState ss = phone.getServiceState();
6788 
6789             // Scrub out the location info in ServiceState depending on what level of access
6790             // the caller has.
6791             if (hasFinePermission) return ss;
6792             if (hasCoarsePermission) return ss.createLocationInfoSanitizedCopy(false);
6793             return ss.createLocationInfoSanitizedCopy(true);
6794         } finally {
6795             Binder.restoreCallingIdentity(identity);
6796         }
6797     }
6798 
6799     /**
6800      * Returns the URI for the per-account voicemail ringtone set in Phone settings.
6801      *
6802      * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
6803      * voicemail ringtone.
6804      * @return The URI for the ringtone to play when receiving a voicemail from a specific
6805      * PhoneAccount.
6806      */
6807     @Override
getVoicemailRingtoneUri(PhoneAccountHandle accountHandle)6808     public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
6809         final long identity = Binder.clearCallingIdentity();
6810         try {
6811             Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
6812             if (phone == null) {
6813                 phone = getDefaultPhone();
6814             }
6815 
6816             return VoicemailNotificationSettingsUtil.getRingtoneUri(phone.getContext());
6817         } finally {
6818             Binder.restoreCallingIdentity(identity);
6819         }
6820     }
6821 
6822     /**
6823      * Sets the per-account voicemail ringtone.
6824      *
6825      * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
6826      * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
6827      *
6828      * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
6829      * voicemail ringtone.
6830      * @param uri The URI for the ringtone to play when receiving a voicemail from a specific
6831      * PhoneAccount.
6832      */
6833     @Override
setVoicemailRingtoneUri(String callingPackage, PhoneAccountHandle phoneAccountHandle, Uri uri)6834     public void setVoicemailRingtoneUri(String callingPackage,
6835             PhoneAccountHandle phoneAccountHandle, Uri uri) {
6836         final Phone defaultPhone = getDefaultPhone();
6837         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
6838         TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
6839         if (!TextUtils.equals(callingPackage, tm.getDefaultDialerPackage())) {
6840             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6841                     mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
6842                     "setVoicemailRingtoneUri");
6843         }
6844 
6845         final long identity = Binder.clearCallingIdentity();
6846         try {
6847             Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
6848             if (phone == null) {
6849                 phone = defaultPhone;
6850             }
6851             VoicemailNotificationSettingsUtil.setRingtoneUri(phone.getContext(), uri);
6852         } finally {
6853             Binder.restoreCallingIdentity(identity);
6854         }
6855     }
6856 
6857     /**
6858      * Returns whether vibration is set for voicemail notification in Phone settings.
6859      *
6860      * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
6861      * voicemail vibration setting.
6862      * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
6863      */
6864     @Override
isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle)6865     public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
6866         final long identity = Binder.clearCallingIdentity();
6867         try {
6868             Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
6869             if (phone == null) {
6870                 phone = getDefaultPhone();
6871             }
6872 
6873             return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone.getContext());
6874         } finally {
6875             Binder.restoreCallingIdentity(identity);
6876         }
6877     }
6878 
6879     /**
6880      * Sets the per-account voicemail vibration.
6881      *
6882      * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
6883      * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
6884      *
6885      * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
6886      * voicemail vibration setting.
6887      * @param enabled Whether to enable or disable vibration for voicemail notifications from a
6888      * specific PhoneAccount.
6889      */
6890     @Override
setVoicemailVibrationEnabled(String callingPackage, PhoneAccountHandle phoneAccountHandle, boolean enabled)6891     public void setVoicemailVibrationEnabled(String callingPackage,
6892             PhoneAccountHandle phoneAccountHandle, boolean enabled) {
6893         final Phone defaultPhone = getDefaultPhone();
6894         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
6895         TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
6896         if (!TextUtils.equals(callingPackage, tm.getDefaultDialerPackage())) {
6897             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6898                     mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
6899                     "setVoicemailVibrationEnabled");
6900         }
6901 
6902         final long identity = Binder.clearCallingIdentity();
6903         try {
6904             Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
6905             if (phone == null) {
6906                 phone = defaultPhone;
6907             }
6908             VoicemailNotificationSettingsUtil.setVibrationEnabled(phone.getContext(), enabled);
6909         } finally {
6910             Binder.restoreCallingIdentity(identity);
6911         }
6912     }
6913 
6914     /**
6915      * Make sure either called from same process as self (phone) or IPC caller has read privilege.
6916      *
6917      * @throws SecurityException if the caller does not have the required permission
6918      */
enforceReadPrivilegedPermission(String message)6919     private void enforceReadPrivilegedPermission(String message) {
6920         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
6921                 message);
6922     }
6923 
6924     /**
6925      * Make sure either called from same process as self (phone) or IPC caller has send SMS
6926      * permission.
6927      *
6928      * @throws SecurityException if the caller does not have the required permission
6929      */
enforceSendSmsPermission()6930     private void enforceSendSmsPermission() {
6931         mApp.enforceCallingOrSelfPermission(permission.SEND_SMS, null);
6932     }
6933 
6934     /**
6935      * Make sure called from the package in charge of visual voicemail.
6936      *
6937      * @throws SecurityException if the caller is not the visual voicemail package.
6938      */
enforceVisualVoicemailPackage(String callingPackage, int subId)6939     private void enforceVisualVoicemailPackage(String callingPackage, int subId) {
6940         final long identity = Binder.clearCallingIdentity();
6941         try {
6942             ComponentName componentName =
6943                     RemoteVvmTaskManager.getRemotePackage(mApp, subId);
6944             if (componentName == null) {
6945                 throw new SecurityException(
6946                         "Caller not current active visual voicemail package[null]");
6947             }
6948             String vvmPackage = componentName.getPackageName();
6949             if (!callingPackage.equals(vvmPackage)) {
6950                 throw new SecurityException("Caller not current active visual voicemail package["
6951                         + vvmPackage + "]");
6952             }
6953         } finally {
6954             Binder.restoreCallingIdentity(identity);
6955         }
6956     }
6957 
6958     /**
6959      * Return the application ID for the app type.
6960      *
6961      * @param subId the subscription ID that this request applies to.
6962      * @param appType the uicc app type.
6963      * @return Application ID for specificied app type, or null if no uicc.
6964      */
6965     @Override
getAidForAppType(int subId, int appType)6966     public String getAidForAppType(int subId, int appType) {
6967         enforceReadPrivilegedPermission("getAidForAppType");
6968         Phone phone = getPhone(subId);
6969 
6970         final long identity = Binder.clearCallingIdentity();
6971         try {
6972             if (phone == null) {
6973                 return null;
6974             }
6975             String aid = null;
6976             try {
6977                 aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
6978                         .getApplicationByType(appType).getAid();
6979             } catch (Exception e) {
6980                 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
6981             }
6982             return aid;
6983         } finally {
6984             Binder.restoreCallingIdentity(identity);
6985         }
6986     }
6987 
6988     /**
6989      * Return the Electronic Serial Number.
6990      *
6991      * @param subId the subscription ID that this request applies to.
6992      * @return ESN or null if error.
6993      */
6994     @Override
getEsn(int subId)6995     public String getEsn(int subId) {
6996         enforceReadPrivilegedPermission("getEsn");
6997         Phone phone = getPhone(subId);
6998 
6999         final long identity = Binder.clearCallingIdentity();
7000         try {
7001             if (phone == null) {
7002                 return null;
7003             }
7004             String esn = null;
7005             try {
7006                 esn = phone.getEsn();
7007             } catch (Exception e) {
7008                 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
7009             }
7010             return esn;
7011         } finally {
7012             Binder.restoreCallingIdentity(identity);
7013         }
7014     }
7015 
7016     /**
7017      * Return the Preferred Roaming List Version.
7018      *
7019      * @param subId the subscription ID that this request applies to.
7020      * @return PRLVersion or null if error.
7021      */
7022     @Override
getCdmaPrlVersion(int subId)7023     public String getCdmaPrlVersion(int subId) {
7024         enforceReadPrivilegedPermission("getCdmaPrlVersion");
7025         Phone phone = getPhone(subId);
7026 
7027         final long identity = Binder.clearCallingIdentity();
7028         try {
7029             if (phone == null) {
7030                 return null;
7031             }
7032             String cdmaPrlVersion = null;
7033             try {
7034                 cdmaPrlVersion = phone.getCdmaPrlVersion();
7035             } catch (Exception e) {
7036                 Log.e(LOG_TAG, "Not getting PRLVersion", e);
7037             }
7038             return cdmaPrlVersion;
7039         } finally {
7040             Binder.restoreCallingIdentity(identity);
7041         }
7042     }
7043 
7044     /**
7045      * Get snapshot of Telephony histograms
7046      * @return List of Telephony histograms
7047      * @hide
7048      */
7049     @Override
getTelephonyHistograms()7050     public List<TelephonyHistogram> getTelephonyHistograms() {
7051         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7052                 mApp, getDefaultSubscription(), "getTelephonyHistograms");
7053 
7054         final long identity = Binder.clearCallingIdentity();
7055         try {
7056             return RIL.getTelephonyRILTimingHistograms();
7057         } finally {
7058             Binder.restoreCallingIdentity(identity);
7059         }
7060     }
7061 
7062     /**
7063      * {@hide}
7064      * Set the allowed carrier list and the excluded carrier list, indicating the priority between
7065      * the two lists.
7066      * Require system privileges. In the future we may add this to carrier APIs.
7067      *
7068      * @return Integer with the result of the operation, as defined in {@link TelephonyManager}.
7069      */
7070     @Override
7071     @TelephonyManager.SetCarrierRestrictionResult
setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules)7072     public int setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules) {
7073         enforceModifyPermission();
7074         WorkSource workSource = getWorkSource(Binder.getCallingUid());
7075 
7076         if (carrierRestrictionRules == null) {
7077             throw new NullPointerException("carrier restriction cannot be null");
7078         }
7079 
7080         final long identity = Binder.clearCallingIdentity();
7081         try {
7082             return (int) sendRequest(CMD_SET_ALLOWED_CARRIERS, carrierRestrictionRules,
7083                     workSource);
7084         } finally {
7085             Binder.restoreCallingIdentity(identity);
7086         }
7087     }
7088 
7089     /**
7090      * {@hide}
7091      * Get the allowed carrier list and the excluded carrier list, including the priority between
7092      * the two lists.
7093      * Require system privileges. In the future we may add this to carrier APIs.
7094      *
7095      * @return {@link android.telephony.CarrierRestrictionRules}
7096      */
7097     @Override
getAllowedCarriers()7098     public CarrierRestrictionRules getAllowedCarriers() {
7099         enforceReadPrivilegedPermission("getAllowedCarriers");
7100         WorkSource workSource = getWorkSource(Binder.getCallingUid());
7101 
7102         final long identity = Binder.clearCallingIdentity();
7103         try {
7104             Object response = sendRequest(CMD_GET_ALLOWED_CARRIERS, null, workSource);
7105             if (response instanceof CarrierRestrictionRules) {
7106                 return (CarrierRestrictionRules) response;
7107             }
7108             // Response is an Exception of some kind,
7109             // which is signalled to the user as a NULL retval
7110             return null;
7111         } catch (Exception e) {
7112             Log.e(LOG_TAG, "getAllowedCarriers. Exception ex=" + e);
7113             return null;
7114         } finally {
7115             Binder.restoreCallingIdentity(identity);
7116         }
7117     }
7118 
7119     /**
7120      * Action set from carrier signalling broadcast receivers to enable/disable metered apns
7121      * @param subId the subscription ID that this action applies to.
7122      * @param enabled control enable or disable metered apns.
7123      * {@hide}
7124      */
7125     @Override
carrierActionSetMeteredApnsEnabled(int subId, boolean enabled)7126     public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
7127         enforceModifyPermission();
7128         final Phone phone = getPhone(subId);
7129 
7130         final long identity = Binder.clearCallingIdentity();
7131         if (phone == null) {
7132             loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
7133             return;
7134         }
7135         try {
7136             phone.carrierActionSetMeteredApnsEnabled(enabled);
7137         } catch (Exception e) {
7138             Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
7139         } finally {
7140             Binder.restoreCallingIdentity(identity);
7141         }
7142     }
7143 
7144     /**
7145      * Action set from carrier signalling broadcast receivers to enable/disable radio
7146      * @param subId the subscription ID that this action applies to.
7147      * @param enabled control enable or disable radio.
7148      * {@hide}
7149      */
7150     @Override
carrierActionSetRadioEnabled(int subId, boolean enabled)7151     public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
7152         enforceModifyPermission();
7153         final Phone phone = getPhone(subId);
7154 
7155         final long identity = Binder.clearCallingIdentity();
7156         if (phone == null) {
7157             loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
7158             return;
7159         }
7160         try {
7161             phone.carrierActionSetRadioEnabled(enabled);
7162         } catch (Exception e) {
7163             Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
7164         } finally {
7165             Binder.restoreCallingIdentity(identity);
7166         }
7167     }
7168 
7169     /**
7170      * Action set from carrier signalling broadcast receivers to start/stop reporting the default
7171      * network status based on which carrier apps could apply actions accordingly,
7172      * enable/disable default url handler for example.
7173      *
7174      * @param subId the subscription ID that this action applies to.
7175      * @param report control start/stop reporting the default network status.
7176      * {@hide}
7177      */
7178     @Override
carrierActionReportDefaultNetworkStatus(int subId, boolean report)7179     public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
7180         enforceModifyPermission();
7181         final Phone phone = getPhone(subId);
7182 
7183         final long identity = Binder.clearCallingIdentity();
7184         if (phone == null) {
7185             loge("carrierAction: ReportDefaultNetworkStatus fails with invalid sibId: " + subId);
7186             return;
7187         }
7188         try {
7189             phone.carrierActionReportDefaultNetworkStatus(report);
7190         } catch (Exception e) {
7191             Log.e(LOG_TAG, "carrierAction: ReportDefaultNetworkStatus fails. Exception ex=" + e);
7192         } finally {
7193             Binder.restoreCallingIdentity(identity);
7194         }
7195     }
7196 
7197     /**
7198      * Action set from carrier signalling broadcast receivers to reset all carrier actions
7199      * @param subId the subscription ID that this action applies to.
7200      * {@hide}
7201      */
7202     @Override
carrierActionResetAll(int subId)7203     public void carrierActionResetAll(int subId) {
7204         enforceModifyPermission();
7205         final Phone phone = getPhone(subId);
7206         if (phone == null) {
7207             loge("carrierAction: ResetAll fails with invalid sibId: " + subId);
7208             return;
7209         }
7210         try {
7211             phone.carrierActionResetAll();
7212         } catch (Exception e) {
7213             Log.e(LOG_TAG, "carrierAction: ResetAll fails. Exception ex=" + e);
7214         }
7215     }
7216 
7217     /**
7218      * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
7219      * bug report is being generated.
7220      */
7221     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)7222     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
7223         if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
7224                 != PackageManager.PERMISSION_GRANTED) {
7225             writer.println("Permission Denial: can't dump Phone from pid="
7226                     + Binder.getCallingPid()
7227                     + ", uid=" + Binder.getCallingUid()
7228                     + "without permission "
7229                     + android.Manifest.permission.DUMP);
7230             return;
7231         }
7232         DumpsysHandler.dump(mApp, fd, writer, args);
7233     }
7234 
7235     @Override
onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)7236     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
7237             String[] args, ShellCallback callback, ResultReceiver resultReceiver)
7238             throws RemoteException {
7239         (new TelephonyShellCommand(this, getDefaultPhone().getContext()))
7240                 .exec(this, in, out, err, args, callback, resultReceiver);
7241     }
7242 
7243     /**
7244      * Policy control of data connection. Usually used when data limit is passed.
7245      * @param enabled True if enabling the data, otherwise disabling.
7246      * @param subId Subscription index
7247      * {@hide}
7248      */
7249     @Override
setPolicyDataEnabled(boolean enabled, int subId)7250     public void setPolicyDataEnabled(boolean enabled, int subId) {
7251         enforceModifyPermission();
7252 
7253         final long identity = Binder.clearCallingIdentity();
7254         try {
7255             Phone phone = getPhone(subId);
7256             if (phone != null) {
7257                 phone.getDataEnabledSettings().setPolicyDataEnabled(enabled);
7258             }
7259         } finally {
7260             Binder.restoreCallingIdentity(identity);
7261         }
7262     }
7263 
7264     /**
7265      * Get Client request stats
7266      * @return List of Client Request Stats
7267      * @hide
7268      */
7269     @Override
getClientRequestStats(String callingPackage, String callingFeatureId, int subId)7270     public List<ClientRequestStats> getClientRequestStats(String callingPackage,
7271             String callingFeatureId, int subId) {
7272         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
7273                 mApp, subId, callingPackage, callingFeatureId, "getClientRequestStats")) {
7274             return null;
7275         }
7276         Phone phone = getPhone(subId);
7277 
7278         final long identity = Binder.clearCallingIdentity();
7279         try {
7280             if (phone != null) {
7281                 return phone.getClientRequestStats();
7282             }
7283 
7284             return null;
7285         } finally {
7286             Binder.restoreCallingIdentity(identity);
7287         }
7288     }
7289 
getWorkSource(int uid)7290     private WorkSource getWorkSource(int uid) {
7291         String packageName = mApp.getPackageManager().getNameForUid(uid);
7292         return new WorkSource(uid, packageName);
7293     }
7294 
7295     /**
7296      * Set SIM card power state.
7297      *
7298      * @param slotIndex SIM slot id.
7299      * @param state  State of SIM (power down, power up, pass through)
7300      * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
7301      * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
7302      * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
7303      *
7304      **/
7305     @Override
setSimPowerStateForSlot(int slotIndex, int state)7306     public void setSimPowerStateForSlot(int slotIndex, int state) {
7307         enforceModifyPermission();
7308         Phone phone = PhoneFactory.getPhone(slotIndex);
7309 
7310         WorkSource workSource = getWorkSource(Binder.getCallingUid());
7311 
7312         final long identity = Binder.clearCallingIdentity();
7313         try {
7314             if (phone != null) {
7315                 phone.setSimPowerState(state, workSource);
7316             }
7317         } finally {
7318             Binder.restoreCallingIdentity(identity);
7319         }
7320     }
7321 
isUssdApiAllowed(int subId)7322     private boolean isUssdApiAllowed(int subId) {
7323         CarrierConfigManager configManager =
7324                 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
7325         if (configManager == null) {
7326             return false;
7327         }
7328         PersistableBundle pb = configManager.getConfigForSubId(subId);
7329         if (pb == null) {
7330             return false;
7331         }
7332         return pb.getBoolean(
7333                 CarrierConfigManager.KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL);
7334     }
7335 
7336     /**
7337      * Check if phone is in emergency callback mode
7338      * @return true if phone is in emergency callback mode
7339      * @param subId sub id
7340      */
7341     @Override
getEmergencyCallbackMode(int subId)7342     public boolean getEmergencyCallbackMode(int subId) {
7343         enforceReadPrivilegedPermission("getEmergencyCallbackMode");
7344         final Phone phone = getPhone(subId);
7345 
7346         final long identity = Binder.clearCallingIdentity();
7347         try {
7348             if (phone != null) {
7349                 return phone.isInEcm();
7350             } else {
7351                 return false;
7352             }
7353         } finally {
7354             Binder.restoreCallingIdentity(identity);
7355         }
7356     }
7357 
7358     /**
7359      * Get the current signal strength information for the given subscription.
7360      * Because this information is not updated when the device is in a low power state
7361      * it should not be relied-upon to be current.
7362      * @param subId Subscription index
7363      * @return the most recent cached signal strength info from the modem
7364      */
7365     @Override
getSignalStrength(int subId)7366     public SignalStrength getSignalStrength(int subId) {
7367         final long identity = Binder.clearCallingIdentity();
7368         try {
7369             Phone p = getPhone(subId);
7370             if (p == null) {
7371                 return null;
7372             }
7373 
7374             return p.getSignalStrength();
7375         } finally {
7376             Binder.restoreCallingIdentity(identity);
7377         }
7378     }
7379 
7380     /**
7381      * Get the current modem radio state for the given slot.
7382      * @param slotIndex slot index.
7383      * @param callingPackage the name of the package making the call.
7384      * @param callingFeatureId The feature in the package.
7385      * @return the current radio power state from the modem
7386      */
7387     @Override
getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId)7388     public int getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId) {
7389         Phone phone = PhoneFactory.getPhone(slotIndex);
7390         if (phone != null) {
7391             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, phone.getSubId(),
7392                     callingPackage, callingFeatureId, "getRadioPowerState")) {
7393                 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
7394             }
7395 
7396             final long identity = Binder.clearCallingIdentity();
7397             try {
7398                 return phone.getRadioPowerState();
7399             } finally {
7400                 Binder.restoreCallingIdentity(identity);
7401             }
7402         }
7403         return TelephonyManager.RADIO_POWER_UNAVAILABLE;
7404     }
7405 
7406     /**
7407      * Checks if data roaming is enabled on the subscription with id {@code subId}.
7408      *
7409      * <p>Requires one of the following permissions:
7410      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE},
7411      * {@link android.Manifest.permission#READ_PHONE_STATE} or that the calling app has carrier
7412      * privileges.
7413      *
7414      * @param subId subscription id
7415      * @return {@code true} if data roaming is enabled on this subscription, otherwise return
7416      * {@code false}.
7417      */
7418     @Override
isDataRoamingEnabled(int subId)7419     public boolean isDataRoamingEnabled(int subId) {
7420         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
7421                 null /* message */);
7422 
7423         boolean isEnabled = false;
7424         final long identity = Binder.clearCallingIdentity();
7425         try {
7426             Phone phone = getPhone(subId);
7427             isEnabled =  phone != null ? phone.getDataRoamingEnabled() : false;
7428         } catch (Exception e) {
7429             TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
7430                     mApp, subId, "isDataRoamingEnabled");
7431         } finally {
7432             Binder.restoreCallingIdentity(identity);
7433         }
7434         return isEnabled;
7435     }
7436 
7437 
7438     /**
7439      * Enables/Disables the data roaming on the subscription with id {@code subId}.
7440      *
7441      * <p> Requires permission:
7442      * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the calling app has carrier
7443      * privileges.
7444      *
7445      * @param subId subscription id
7446      * @param isEnabled {@code true} means enable, {@code false} means disable.
7447      */
7448     @Override
setDataRoamingEnabled(int subId, boolean isEnabled)7449     public void setDataRoamingEnabled(int subId, boolean isEnabled) {
7450         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7451                 mApp, subId, "setDataRoamingEnabled");
7452 
7453         final long identity = Binder.clearCallingIdentity();
7454         try {
7455             Phone phone = getPhone(subId);
7456             if (phone != null) {
7457                 phone.setDataRoamingEnabled(isEnabled);
7458             }
7459         } finally {
7460             Binder.restoreCallingIdentity(identity);
7461         }
7462     }
7463 
7464     @Override
isManualNetworkSelectionAllowed(int subId)7465     public boolean isManualNetworkSelectionAllowed(int subId) {
7466         TelephonyPermissions
7467                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
7468                 mApp, subId, "isManualNetworkSelectionAllowed");
7469 
7470         boolean isAllowed = true;
7471         final long identity = Binder.clearCallingIdentity();
7472         try {
7473             Phone phone = getPhone(subId);
7474             if (phone != null) {
7475                 isAllowed = phone.isCspPlmnEnabled();
7476             }
7477         } finally {
7478             Binder.restoreCallingIdentity(identity);
7479         }
7480         return isAllowed;
7481     }
7482 
7483     @Override
getUiccCardsInfo(String callingPackage)7484     public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
7485         // Verify that tha callingPackage belongs to the calling UID
7486         mApp.getSystemService(AppOpsManager.class)
7487                 .checkPackage(Binder.getCallingUid(), callingPackage);
7488 
7489         boolean hasReadPermission = false;
7490         try {
7491             enforceReadPrivilegedPermission("getUiccCardsInfo");
7492             hasReadPermission = true;
7493         } catch (SecurityException e) {
7494             // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
7495             // has carrier privileges on an active UICC
7496             if (checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
7497                         != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
7498                 throw new SecurityException("Caller does not have permission.");
7499             }
7500         }
7501 
7502         final long identity = Binder.clearCallingIdentity();
7503         try {
7504             UiccController uiccController = UiccController.getInstance();
7505             ArrayList<UiccCardInfo> cardInfos = uiccController.getAllUiccCardInfos();
7506             if (hasReadPermission) {
7507                 return cardInfos;
7508             }
7509 
7510             // Remove private info if the caller doesn't have access
7511             ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
7512             for (UiccCardInfo cardInfo : cardInfos) {
7513                 // For an inactive eUICC, the UiccCard will be null even though the UiccCardInfo
7514                 // is available
7515                 UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getSlotIndex());
7516                 if (card == null || card.getUiccProfile() == null) {
7517                     // assume no access if the card or profile is unavailable
7518                     filteredInfos.add(cardInfo.getUnprivileged());
7519                     continue;
7520                 }
7521                 UiccProfile profile = card.getUiccProfile();
7522                 if (profile.getCarrierPrivilegeStatus(mApp.getPackageManager(), callingPackage)
7523                         == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
7524                     filteredInfos.add(cardInfo);
7525                 } else {
7526                     filteredInfos.add(cardInfo.getUnprivileged());
7527                 }
7528             }
7529             return filteredInfos;
7530         } finally {
7531             Binder.restoreCallingIdentity(identity);
7532         }
7533     }
7534 
7535     @Override
getUiccSlotsInfo()7536     public UiccSlotInfo[] getUiccSlotsInfo() {
7537         enforceReadPrivilegedPermission("getUiccSlotsInfo");
7538 
7539         final long identity = Binder.clearCallingIdentity();
7540         try {
7541             UiccSlot[] slots = UiccController.getInstance().getUiccSlots();
7542             if (slots == null) {
7543                 Rlog.i(LOG_TAG, "slots is null.");
7544                 return null;
7545             }
7546 
7547             UiccSlotInfo[] infos = new UiccSlotInfo[slots.length];
7548             for (int i = 0; i < slots.length; i++) {
7549                 UiccSlot slot = slots[i];
7550                 if (slot == null) {
7551                     continue;
7552                 }
7553 
7554                 String cardId;
7555                 UiccCard card = slot.getUiccCard();
7556                 if (card != null) {
7557                     cardId = card.getCardId();
7558                 } else {
7559                     cardId = slot.getEid();
7560                     if (TextUtils.isEmpty(cardId)) {
7561                         cardId = slot.getIccId();
7562                     }
7563                 }
7564 
7565                 if (cardId != null) {
7566                     // if cardId is an ICCID, strip off trailing Fs before exposing to user
7567                     // if cardId is an EID, it's all digits so this is fine
7568                     cardId = IccUtils.stripTrailingFs(cardId);
7569                 }
7570 
7571                 int cardState = 0;
7572                 switch (slot.getCardState()) {
7573                     case CARDSTATE_ABSENT:
7574                         cardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT;
7575                         break;
7576                     case CARDSTATE_PRESENT:
7577                         cardState = UiccSlotInfo.CARD_STATE_INFO_PRESENT;
7578                         break;
7579                     case CARDSTATE_ERROR:
7580                         cardState = UiccSlotInfo.CARD_STATE_INFO_ERROR;
7581                         break;
7582                     case CARDSTATE_RESTRICTED:
7583                         cardState = UiccSlotInfo.CARD_STATE_INFO_RESTRICTED;
7584                         break;
7585                     default:
7586                         break;
7587 
7588                 }
7589 
7590                 infos[i] = new UiccSlotInfo(
7591                         slot.isActive(),
7592                         slot.isEuicc(),
7593                         cardId,
7594                         cardState,
7595                         slot.getPhoneId(),
7596                         slot.isExtendedApduSupported(),
7597                         slot.isRemovable());
7598             }
7599             return infos;
7600         } finally {
7601             Binder.restoreCallingIdentity(identity);
7602         }
7603     }
7604 
7605     @Override
switchSlots(int[] physicalSlots)7606     public boolean switchSlots(int[] physicalSlots) {
7607         enforceModifyPermission();
7608 
7609         final long identity = Binder.clearCallingIdentity();
7610         try {
7611             return (Boolean) sendRequest(CMD_SWITCH_SLOTS, physicalSlots);
7612         } finally {
7613             Binder.restoreCallingIdentity(identity);
7614         }
7615     }
7616 
7617     @Override
getCardIdForDefaultEuicc(int subId, String callingPackage)7618     public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
7619         final long identity = Binder.clearCallingIdentity();
7620         try {
7621             return UiccController.getInstance().getCardIdForDefaultEuicc();
7622         } finally {
7623             Binder.restoreCallingIdentity(identity);
7624         }
7625     }
7626 
7627     /**
7628      * A test API to reload the UICC profile.
7629      *
7630      * <p>Requires that the calling app has permission
7631      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
7632      * @hide
7633      */
7634     @Override
refreshUiccProfile(int subId)7635     public void refreshUiccProfile(int subId) {
7636         enforceModifyPermission();
7637 
7638         final long identity = Binder.clearCallingIdentity();
7639         try {
7640             Phone phone = getPhone(subId);
7641             if (phone == null) {
7642                 return;
7643             }
7644             UiccCard uiccCard = phone.getUiccCard();
7645             if (uiccCard == null) {
7646                 return;
7647             }
7648             UiccProfile uiccProfile = uiccCard.getUiccProfile();
7649             if (uiccProfile == null) {
7650                 return;
7651             }
7652             uiccProfile.refresh();
7653         } finally {
7654             Binder.restoreCallingIdentity(identity);
7655         }
7656     }
7657 
7658     /**
7659      * Returns false if the mobile data is disabled by default, otherwise return true.
7660      */
getDefaultDataEnabled()7661     private boolean getDefaultDataEnabled() {
7662         return TelephonyProperties.mobile_data().orElse(true);
7663     }
7664 
7665     /**
7666      * Returns true if the data roaming is enabled by default, i.e the system property
7667      * of {@link #DEFAULT_DATA_ROAMING_PROPERTY_NAME} is true or the config of
7668      * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} is true.
7669      */
getDefaultDataRoamingEnabled(int subId)7670     private boolean getDefaultDataRoamingEnabled(int subId) {
7671         final CarrierConfigManager configMgr = (CarrierConfigManager)
7672                 mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
7673         boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
7674         isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
7675                 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
7676         return isDataRoamingEnabled;
7677     }
7678 
7679     /**
7680      * Returns the default network type for the given {@code subId}, if the default network type is
7681      * not set, return {@link Phone#PREFERRED_NT_MODE}.
7682      */
getDefaultNetworkType(int subId)7683     private int getDefaultNetworkType(int subId) {
7684         List<Integer> list = TelephonyProperties.default_network();
7685         int phoneId = mSubscriptionController.getPhoneId(subId);
7686         if (phoneId >= 0 && phoneId < list.size() && list.get(phoneId) != null) {
7687             return list.get(phoneId);
7688         }
7689         return Phone.PREFERRED_NT_MODE;
7690     }
7691 
7692     @Override
setCarrierTestOverride(int subId, String mccmnc, String imsi, String iccid, String gid1, String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn)7693     public void setCarrierTestOverride(int subId, String mccmnc, String imsi, String iccid, String
7694             gid1, String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn) {
7695         enforceModifyPermission();
7696 
7697         final long identity = Binder.clearCallingIdentity();
7698         try {
7699             final Phone phone = getPhone(subId);
7700             if (phone == null) {
7701                 loge("setCarrierTestOverride fails with invalid subId: " + subId);
7702                 return;
7703             }
7704             phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
7705                     carrierPrivilegeRules, apn);
7706         } finally {
7707             Binder.restoreCallingIdentity(identity);
7708         }
7709     }
7710 
7711     @Override
getCarrierIdListVersion(int subId)7712     public int getCarrierIdListVersion(int subId) {
7713         enforceReadPrivilegedPermission("getCarrierIdListVersion");
7714 
7715         final long identity = Binder.clearCallingIdentity();
7716         try {
7717             final Phone phone = getPhone(subId);
7718             if (phone == null) {
7719                 loge("getCarrierIdListVersion fails with invalid subId: " + subId);
7720                 return TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION;
7721             }
7722             return phone.getCarrierIdListVersion();
7723         } finally {
7724             Binder.restoreCallingIdentity(identity);
7725         }
7726     }
7727 
7728     @Override
getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage, String callingFeatureId)7729     public int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage,
7730             String callingFeatureId) {
7731         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
7732                 mApp, subId, callingPackage, callingFeatureId,
7733                 "getNumberOfModemsWithSimultaneousDataConnections")) {
7734             return -1;
7735         }
7736 
7737         final long identity = Binder.clearCallingIdentity();
7738         try {
7739             return mPhoneConfigurationManager.getNumberOfModemsWithSimultaneousDataConnections();
7740         } finally {
7741             Binder.restoreCallingIdentity(identity);
7742         }
7743     }
7744 
7745     @Override
getCdmaRoamingMode(int subId)7746     public int getCdmaRoamingMode(int subId) {
7747         TelephonyPermissions
7748                 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
7749                 mApp, subId, "getCdmaRoamingMode");
7750 
7751         final long identity = Binder.clearCallingIdentity();
7752         try {
7753             return (int) sendRequest(CMD_GET_CDMA_ROAMING_MODE, null /* argument */, subId);
7754         } finally {
7755             Binder.restoreCallingIdentity(identity);
7756         }
7757     }
7758 
7759     @Override
setCdmaRoamingMode(int subId, int mode)7760     public boolean setCdmaRoamingMode(int subId, int mode) {
7761         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7762                 mApp, subId, "setCdmaRoamingMode");
7763 
7764         final long identity = Binder.clearCallingIdentity();
7765         try {
7766             return (boolean) sendRequest(CMD_SET_CDMA_ROAMING_MODE, mode, subId);
7767         } finally {
7768             Binder.restoreCallingIdentity(identity);
7769         }
7770     }
7771 
7772     @Override
setCdmaSubscriptionMode(int subId, int mode)7773     public boolean setCdmaSubscriptionMode(int subId, int mode) {
7774         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7775                 mApp, subId, "setCdmaSubscriptionMode");
7776 
7777         final long identity = Binder.clearCallingIdentity();
7778         try {
7779             return (boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION_MODE, mode, subId);
7780         } finally {
7781             Binder.restoreCallingIdentity(identity);
7782         }
7783     }
7784 
7785     @Override
getEmergencyNumberList( String callingPackage, String callingFeatureId)7786     public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
7787             String callingPackage, String callingFeatureId) {
7788         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
7789                 mApp, getDefaultSubscription(), callingPackage, callingFeatureId,
7790                 "getEmergencyNumberList")) {
7791             throw new SecurityException("Requires READ_PHONE_STATE permission.");
7792         }
7793         final long identity = Binder.clearCallingIdentity();
7794         try {
7795             Map<Integer, List<EmergencyNumber>> emergencyNumberListInternal = new HashMap<>();
7796             for (Phone phone: PhoneFactory.getPhones()) {
7797                 if (phone.getEmergencyNumberTracker() != null
7798                         && phone.getEmergencyNumberTracker().getEmergencyNumberList() != null) {
7799                     emergencyNumberListInternal.put(
7800                             phone.getSubId(),
7801                             phone.getEmergencyNumberTracker().getEmergencyNumberList());
7802                 }
7803             }
7804             return emergencyNumberListInternal;
7805         } finally {
7806             Binder.restoreCallingIdentity(identity);
7807         }
7808     }
7809 
7810     @Override
isEmergencyNumber(String number, boolean exactMatch)7811     public boolean isEmergencyNumber(String number, boolean exactMatch) {
7812         final Phone defaultPhone = getDefaultPhone();
7813         if (!exactMatch) {
7814             TelephonyPermissions
7815                     .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
7816                             mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
7817         }
7818         final long identity = Binder.clearCallingIdentity();
7819         try {
7820             for (Phone phone: PhoneFactory.getPhones()) {
7821                 if (phone.getEmergencyNumberTracker() != null
7822                         && phone.getEmergencyNumberTracker() != null) {
7823                     if (phone.getEmergencyNumberTracker().isEmergencyNumber(
7824                             number, exactMatch)) {
7825                         return true;
7826                     }
7827                 }
7828             }
7829             return false;
7830         } finally {
7831             Binder.restoreCallingIdentity(identity);
7832         }
7833     }
7834 
7835     /**
7836      * Update emergency number list for test mode.
7837      */
7838     @Override
updateEmergencyNumberListTestMode(int action, EmergencyNumber num)7839     public void updateEmergencyNumberListTestMode(int action, EmergencyNumber num) {
7840         TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
7841                 "updateEmergencyNumberListTestMode");
7842 
7843         final long identity = Binder.clearCallingIdentity();
7844         try {
7845             for (Phone phone: PhoneFactory.getPhones()) {
7846                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
7847                 if (tracker != null) {
7848                     tracker.executeEmergencyNumberTestModeCommand(action, num);
7849                 }
7850             }
7851         } finally {
7852             Binder.restoreCallingIdentity(identity);
7853         }
7854     }
7855 
7856     /**
7857      * Get the full emergency number list for test mode.
7858      */
7859     @Override
getEmergencyNumberListTestMode()7860     public List<String> getEmergencyNumberListTestMode() {
7861         TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
7862                 "getEmergencyNumberListTestMode");
7863 
7864         final long identity = Binder.clearCallingIdentity();
7865         try {
7866             Set<String> emergencyNumbers = new HashSet<>();
7867             for (Phone phone: PhoneFactory.getPhones()) {
7868                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
7869                 if (tracker != null) {
7870                     for (EmergencyNumber num : tracker.getEmergencyNumberList()) {
7871                         emergencyNumbers.add(num.getNumber());
7872                     }
7873                 }
7874             }
7875             return new ArrayList<>(emergencyNumbers);
7876         } finally {
7877             Binder.restoreCallingIdentity(identity);
7878         }
7879     }
7880 
7881     @Override
getEmergencyNumberDbVersion(int subId)7882     public int getEmergencyNumberDbVersion(int subId) {
7883         enforceReadPrivilegedPermission("getEmergencyNumberDbVersion");
7884 
7885         final long identity = Binder.clearCallingIdentity();
7886         try {
7887             final Phone phone = getPhone(subId);
7888             if (phone == null) {
7889                 loge("getEmergencyNumberDbVersion fails with invalid subId: " + subId);
7890                 return TelephonyManager.INVALID_EMERGENCY_NUMBER_DB_VERSION;
7891             }
7892             return phone.getEmergencyNumberDbVersion();
7893         } finally {
7894             Binder.restoreCallingIdentity(identity);
7895         }
7896     }
7897 
7898     @Override
notifyOtaEmergencyNumberDbInstalled()7899     public void notifyOtaEmergencyNumberDbInstalled() {
7900         enforceModifyPermission();
7901 
7902         final long identity = Binder.clearCallingIdentity();
7903         try {
7904             for (Phone phone: PhoneFactory.getPhones()) {
7905                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
7906                 if (tracker != null) {
7907                     tracker.updateOtaEmergencyNumberDatabase();
7908                 }
7909             }
7910         } finally {
7911             Binder.restoreCallingIdentity(identity);
7912         }
7913     }
7914 
7915     @Override
updateOtaEmergencyNumberDbFilePath(ParcelFileDescriptor otaParcelFileDescriptor)7916     public void updateOtaEmergencyNumberDbFilePath(ParcelFileDescriptor otaParcelFileDescriptor) {
7917         enforceActiveEmergencySessionPermission();
7918 
7919         final long identity = Binder.clearCallingIdentity();
7920         try {
7921             for (Phone phone: PhoneFactory.getPhones()) {
7922                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
7923                 if (tracker != null) {
7924                     tracker.updateOtaEmergencyNumberDbFilePath(otaParcelFileDescriptor);
7925                 }
7926             }
7927         } finally {
7928             Binder.restoreCallingIdentity(identity);
7929         }
7930     }
7931 
7932     @Override
resetOtaEmergencyNumberDbFilePath()7933     public void resetOtaEmergencyNumberDbFilePath() {
7934         enforceActiveEmergencySessionPermission();
7935 
7936         final long identity = Binder.clearCallingIdentity();
7937         try {
7938             for (Phone phone: PhoneFactory.getPhones()) {
7939                 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
7940                 if (tracker != null) {
7941                     tracker.resetOtaEmergencyNumberDbFilePath();
7942                 }
7943             }
7944         } finally {
7945             Binder.restoreCallingIdentity(identity);
7946         }
7947     }
7948 
7949     @Override
getCertsFromCarrierPrivilegeAccessRules(int subId)7950     public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
7951         enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
7952         Phone phone = getPhone(subId);
7953         if (phone == null) {
7954             return null;
7955         }
7956         final long identity = Binder.clearCallingIdentity();
7957         try {
7958             UiccProfile profile = UiccController.getInstance()
7959                     .getUiccProfileForPhone(phone.getPhoneId());
7960             if (profile != null) {
7961                 return profile.getCertsFromCarrierPrivilegeAccessRules();
7962             }
7963         } finally {
7964             Binder.restoreCallingIdentity(identity);
7965         }
7966         return null;
7967     }
7968 
7969     /**
7970      * Enable or disable a modem stack.
7971      */
7972     @Override
enableModemForSlot(int slotIndex, boolean enable)7973     public boolean enableModemForSlot(int slotIndex, boolean enable) {
7974         enforceModifyPermission();
7975 
7976         final long identity = Binder.clearCallingIdentity();
7977         try {
7978             Phone phone = PhoneFactory.getPhone(slotIndex);
7979             if (phone == null) {
7980                 return false;
7981             } else {
7982                 return (Boolean) sendRequest(CMD_REQUEST_ENABLE_MODEM, enable, phone, null);
7983             }
7984         } finally {
7985             Binder.restoreCallingIdentity(identity);
7986         }
7987     }
7988 
7989     /**
7990      * Whether a modem stack is enabled or not.
7991      */
7992     @Override
isModemEnabledForSlot(int slotIndex, String callingPackage, String callingFeatureId)7993     public boolean isModemEnabledForSlot(int slotIndex, String callingPackage,
7994             String callingFeatureId) {
7995         Phone phone = PhoneFactory.getPhone(slotIndex);
7996         if (phone == null) return false;
7997 
7998         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
7999                 mApp, phone.getSubId(), callingPackage, callingFeatureId,
8000                 "isModemEnabledForSlot")) {
8001             throw new SecurityException("Requires READ_PHONE_STATE permission.");
8002         }
8003 
8004         final long identity = Binder.clearCallingIdentity();
8005         try {
8006             try {
8007                 return mPhoneConfigurationManager.getPhoneStatusFromCache(phone.getPhoneId());
8008             } catch (NoSuchElementException ex) {
8009                 return (Boolean) sendRequest(CMD_GET_MODEM_STATUS, null, phone, null);
8010             }
8011         } finally {
8012             Binder.restoreCallingIdentity(identity);
8013         }
8014     }
8015 
8016     @Override
setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted)8017     public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
8018         enforceModifyPermission();
8019 
8020         final long identity = Binder.clearCallingIdentity();
8021         try {
8022             mTelephonySharedPreferences.edit()
8023                     .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultiSimCarrierRestricted)
8024                     .commit();
8025         } finally {
8026             Binder.restoreCallingIdentity(identity);
8027         }
8028     }
8029 
8030     @Override
8031     @TelephonyManager.IsMultiSimSupportedResult
isMultiSimSupported(String callingPackage, String callingFeatureId)8032     public int isMultiSimSupported(String callingPackage, String callingFeatureId) {
8033         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp,
8034                 getDefaultPhone().getSubId(), callingPackage, callingFeatureId,
8035                 "isMultiSimSupported")) {
8036             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
8037         }
8038 
8039         final long identity = Binder.clearCallingIdentity();
8040         try {
8041             return isMultiSimSupportedInternal();
8042         } finally {
8043             Binder.restoreCallingIdentity(identity);
8044         }
8045     }
8046 
8047     @TelephonyManager.IsMultiSimSupportedResult
isMultiSimSupportedInternal()8048     private int isMultiSimSupportedInternal() {
8049         // If the device has less than 2 SIM cards, indicate that multisim is restricted.
8050         int numPhysicalSlots = UiccController.getInstance().getUiccSlots().length;
8051         if (numPhysicalSlots < 2) {
8052             loge("isMultiSimSupportedInternal: requires at least 2 cards");
8053             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
8054         }
8055         // Check if the hardware supports multisim functionality. If usage of multisim is not
8056         // supported by the modem, indicate that it is restricted.
8057         PhoneCapability staticCapability =
8058                 mPhoneConfigurationManager.getStaticPhoneCapability();
8059         if (staticCapability == null) {
8060             loge("isMultiSimSupportedInternal: no static configuration available");
8061             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
8062         }
8063         if (staticCapability.logicalModemList.size() < 2) {
8064             loge("isMultiSimSupportedInternal: maximum number of modem is < 2");
8065             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
8066         }
8067         // Check if support of multiple SIMs is restricted by carrier
8068         if (mTelephonySharedPreferences.getBoolean(PREF_MULTI_SIM_RESTRICTED, false)) {
8069             return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_CARRIER;
8070         }
8071 
8072         return TelephonyManager.MULTISIM_ALLOWED;
8073     }
8074 
8075     /**
8076      * Switch configs to enable multi-sim or switch back to single-sim
8077      * Note: Switch from multi-sim to single-sim is only possible with MODIFY_PHONE_STATE
8078      * permission, but the other way around is possible with either MODIFY_PHONE_STATE
8079      * or carrier privileges
8080      * @param numOfSims number of active sims we want to switch to
8081      */
8082     @Override
switchMultiSimConfig(int numOfSims)8083     public void switchMultiSimConfig(int numOfSims) {
8084         if (numOfSims == 1) {
8085             enforceModifyPermission();
8086         } else {
8087             TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
8088                     mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
8089         }
8090         final long identity = Binder.clearCallingIdentity();
8091 
8092         try {
8093             //only proceed if multi-sim is not restricted
8094             if (isMultiSimSupportedInternal() != TelephonyManager.MULTISIM_ALLOWED) {
8095                 loge("switchMultiSimConfig not possible. It is restricted or not supported.");
8096                 return;
8097             }
8098             mPhoneConfigurationManager.switchMultiSimConfig(numOfSims);
8099         } finally {
8100             Binder.restoreCallingIdentity(identity);
8101         }
8102     }
8103 
8104     @Override
isApplicationOnUicc(int subId, int appType)8105     public boolean isApplicationOnUicc(int subId, int appType) {
8106         enforceReadPrivilegedPermission("isApplicationOnUicc");
8107         Phone phone = getPhone(subId);
8108         if (phone == null) {
8109             return false;
8110         }
8111         final long identity = Binder.clearCallingIdentity();
8112         try {
8113             UiccCard uiccCard = phone.getUiccCard();
8114             if (uiccCard == null) {
8115                 return false;
8116             }
8117             UiccProfile uiccProfile = uiccCard.getUiccProfile();
8118             if (uiccProfile == null) {
8119                 return false;
8120             }
8121             if (TelephonyManager.APPTYPE_SIM <= appType
8122                     && appType <= TelephonyManager.APPTYPE_ISIM) {
8123                 return uiccProfile.isApplicationOnIcc(AppType.values()[appType]);
8124             }
8125             return false;
8126         } finally {
8127             Binder.restoreCallingIdentity(identity);
8128         }
8129     }
8130 
8131     /**
8132      * Get whether making changes to modem configurations will trigger reboot.
8133      * Return value defaults to true.
8134      */
8135     @Override
doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage, String callingFeatureId)8136     public boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage,
8137             String callingFeatureId) {
8138         if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
8139                 mApp, subId, callingPackage, callingFeatureId,
8140                 "doesSwitchMultiSimConfigTriggerReboot")) {
8141             return false;
8142         }
8143         final long identity = Binder.clearCallingIdentity();
8144         try {
8145             return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
8146         } finally {
8147             Binder.restoreCallingIdentity(identity);
8148         }
8149     }
8150 
updateModemStateMetrics()8151     private void updateModemStateMetrics() {
8152         TelephonyMetrics metrics = TelephonyMetrics.getInstance();
8153         // TODO: check the state for each modem if the api is ready.
8154         metrics.updateEnabledModemBitmap((1 << TelephonyManager.from(mApp).getPhoneCount()) - 1);
8155     }
8156 
8157     @Override
getSlotsMapping()8158     public int[] getSlotsMapping() {
8159         enforceReadPrivilegedPermission("getSlotsMapping");
8160 
8161         final long identity = Binder.clearCallingIdentity();
8162         try {
8163             int phoneCount = TelephonyManager.getDefault().getPhoneCount();
8164             // All logical slots should have a mapping to a physical slot.
8165             int[] logicalSlotsMapping = new int[phoneCount];
8166             UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
8167             for (int i = 0; i < slotInfos.length; i++) {
8168                 if (SubscriptionManager.isValidPhoneId(slotInfos[i].getLogicalSlotIdx())) {
8169                     logicalSlotsMapping[slotInfos[i].getLogicalSlotIdx()] = i;
8170                 }
8171             }
8172             return logicalSlotsMapping;
8173         } finally {
8174             Binder.restoreCallingIdentity(identity);
8175         }
8176     }
8177 
8178     /**
8179      * Get the IRadio HAL Version
8180      */
8181     @Override
getRadioHalVersion()8182     public int getRadioHalVersion() {
8183         Phone phone = getDefaultPhone();
8184         if (phone == null) return -1;
8185         HalVersion hv = phone.getHalVersion();
8186         if (hv.equals(HalVersion.UNKNOWN)) return -1;
8187         return hv.major * 100 + hv.minor;
8188     }
8189 
8190     /**
8191      * Get the current calling package name.
8192      * @return the current calling package name
8193      */
8194     @Override
getCurrentPackageName()8195     public String getCurrentPackageName() {
8196         return mApp.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0];
8197     }
8198 
8199     /**
8200      * Return whether data is enabled for certain APN type. This will tell if framework will accept
8201      * corresponding network requests on a subId.
8202      *
8203      *  Data is enabled if:
8204      *  1) user data is turned on, or
8205      *  2) APN is un-metered for this subscription, or
8206      *  3) APN type is whitelisted. E.g. MMS is whitelisted if
8207      *  {@link TelephonyManager#setAlwaysAllowMmsData} is turned on.
8208      *
8209      * @return whether data is allowed for a apn type.
8210      *
8211      * @hide
8212      */
8213     @Override
isDataEnabledForApn(int apnType, int subId, String callingPackage)8214     public boolean isDataEnabledForApn(int apnType, int subId, String callingPackage) {
8215         enforceReadPrivilegedPermission("Needs READ_PRIVILEGED_PHONE_STATE for "
8216                 + "isDataEnabledForApn");
8217 
8218         // Now that all security checks passes, perform the operation as ourselves.
8219         final long identity = Binder.clearCallingIdentity();
8220         try {
8221             Phone phone = getPhone(subId);
8222             if (phone == null) return false;
8223 
8224             boolean isMetered = ApnSettingUtils.isMeteredApnType(apnType, phone);
8225             return !isMetered || phone.getDataEnabledSettings().isDataEnabled(apnType);
8226         } finally {
8227             Binder.restoreCallingIdentity(identity);
8228         }
8229     }
8230 
8231     @Override
isApnMetered(@pnType int apnType, int subId)8232     public boolean isApnMetered(@ApnType int apnType, int subId) {
8233         enforceReadPrivilegedPermission("isApnMetered");
8234 
8235         // Now that all security checks passes, perform the operation as ourselves.
8236         final long identity = Binder.clearCallingIdentity();
8237         try {
8238             Phone phone = getPhone(subId);
8239             if (phone == null) return true; // By default return true.
8240 
8241             return ApnSettingUtils.isMeteredApnType(apnType, phone);
8242         } finally {
8243             Binder.restoreCallingIdentity(identity);
8244         }
8245     }
8246 
8247     @Override
setSystemSelectionChannels(List<RadioAccessSpecifier> specifiers, int subscriptionId, IBooleanConsumer resultCallback)8248     public void setSystemSelectionChannels(List<RadioAccessSpecifier> specifiers,
8249             int subscriptionId, IBooleanConsumer resultCallback) {
8250         enforceModifyPermission();
8251         long token = Binder.clearCallingIdentity();
8252         try {
8253             Phone phone = getPhone(subscriptionId);
8254             if (phone == null) {
8255                 try {
8256                     if (resultCallback != null) {
8257                         resultCallback.accept(false);
8258                     }
8259                 } catch (RemoteException e) {
8260                     // ignore
8261                 }
8262                 return;
8263             }
8264             Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> argument =
8265                     Pair.create(specifiers, (x) -> {
8266                         try {
8267                             if (resultCallback != null) {
8268                                 resultCallback.accept(x);
8269                             }
8270                         } catch (RemoteException e) {
8271                             // ignore
8272                         }
8273                     });
8274             sendRequestAsync(CMD_SET_SYSTEM_SELECTION_CHANNELS, argument, phone, null);
8275         } finally {
8276             Binder.restoreCallingIdentity(token);
8277         }
8278     }
8279 
8280     @Override
isMvnoMatched(int subId, int mvnoType, @NonNull String mvnoMatchData)8281     public boolean isMvnoMatched(int subId, int mvnoType, @NonNull String mvnoMatchData) {
8282         IccRecords iccRecords = UiccController.getInstance().getIccRecords(
8283                 SubscriptionManager.getPhoneId(subId), UiccController.APP_FAM_3GPP);
8284         if (iccRecords == null) {
8285             Log.d(LOG_TAG, "isMvnoMatched# IccRecords is null");
8286             return false;
8287         }
8288         return ApnSettingUtils.mvnoMatches(iccRecords, mvnoType, mvnoMatchData);
8289     }
8290 
8291     @Override
enqueueSmsPickResult(String callingPackage, String callingAttributionTag, IIntegerConsumer pendingSubIdResult)8292     public void enqueueSmsPickResult(String callingPackage, String callingAttributionTag,
8293             IIntegerConsumer pendingSubIdResult) {
8294         if (callingPackage == null) {
8295             callingPackage = getCurrentPackageName();
8296         }
8297         SmsPermissions permissions = new SmsPermissions(getDefaultPhone(), mApp,
8298                 (AppOpsManager) mApp.getSystemService(Context.APP_OPS_SERVICE));
8299         if (!permissions.checkCallingCanSendSms(callingPackage, callingAttributionTag,
8300                 "Sending message")) {
8301             throw new SecurityException("Requires SEND_SMS permission to perform this operation");
8302         }
8303         PickSmsSubscriptionActivity.addPendingResult(pendingSubIdResult);
8304         Intent intent = new Intent();
8305         intent.setClass(mApp, PickSmsSubscriptionActivity.class);
8306         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8307         // Bring up choose default SMS subscription dialog right now
8308         intent.putExtra(PickSmsSubscriptionActivity.DIALOG_TYPE_KEY,
8309                 PickSmsSubscriptionActivity.SMS_PICK_FOR_MESSAGE);
8310         mApp.startActivity(intent);
8311     }
8312 
8313     @Override
getMmsUAProfUrl(int subId)8314     public String getMmsUAProfUrl(int subId) {
8315         //TODO investigate if this API should require proper permission check in R b/133791609
8316         final long identity = Binder.clearCallingIdentity();
8317         try {
8318             String carrierUAProfUrl = mApp.getCarrierConfigForSubId(subId).getString(
8319                     CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING);
8320             if (!TextUtils.isEmpty(carrierUAProfUrl)) {
8321                 return carrierUAProfUrl;
8322             }
8323             return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
8324                     .getString(com.android.internal.R.string.config_mms_user_agent_profile_url);
8325         } finally {
8326             Binder.restoreCallingIdentity(identity);
8327         }
8328     }
8329 
8330     @Override
getMmsUserAgent(int subId)8331     public String getMmsUserAgent(int subId) {
8332         //TODO investigate if this API should require proper permission check in R b/133791609
8333         final long identity = Binder.clearCallingIdentity();
8334         try {
8335             String carrierUserAgent = mApp.getCarrierConfigForSubId(subId).getString(
8336                     CarrierConfigManager.KEY_MMS_USER_AGENT_STRING);
8337             if (!TextUtils.isEmpty(carrierUserAgent)) {
8338                 return carrierUserAgent;
8339             }
8340             return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
8341                     .getString(com.android.internal.R.string.config_mms_user_agent);
8342         } finally {
8343             Binder.restoreCallingIdentity(identity);
8344         }
8345     }
8346 
8347     @Override
setDataAllowedDuringVoiceCall(int subId, boolean allow)8348     public boolean setDataAllowedDuringVoiceCall(int subId, boolean allow) {
8349         enforceModifyPermission();
8350 
8351         // Now that all security checks passes, perform the operation as ourselves.
8352         final long identity = Binder.clearCallingIdentity();
8353         try {
8354             Phone phone = getPhone(subId);
8355             if (phone == null) return false;
8356 
8357             return phone.getDataEnabledSettings().setAllowDataDuringVoiceCall(allow);
8358         } finally {
8359             Binder.restoreCallingIdentity(identity);
8360         }
8361     }
8362 
8363     @Override
isDataAllowedInVoiceCall(int subId)8364     public boolean isDataAllowedInVoiceCall(int subId) {
8365         enforceReadPrivilegedPermission("isDataAllowedInVoiceCall");
8366 
8367         // Now that all security checks passes, perform the operation as ourselves.
8368         final long identity = Binder.clearCallingIdentity();
8369         try {
8370             Phone phone = getPhone(subId);
8371             if (phone == null) return false;
8372 
8373             return phone.getDataEnabledSettings().isDataAllowedInVoiceCall();
8374         } finally {
8375             Binder.restoreCallingIdentity(identity);
8376         }
8377     }
8378 
8379     @Override
setAlwaysAllowMmsData(int subId, boolean alwaysAllow)8380     public boolean setAlwaysAllowMmsData(int subId, boolean alwaysAllow) {
8381         enforceModifyPermission();
8382 
8383         // Now that all security checks passes, perform the operation as ourselves.
8384         final long identity = Binder.clearCallingIdentity();
8385         try {
8386             Phone phone = getPhone(subId);
8387             if (phone == null) return false;
8388 
8389             return phone.getDataEnabledSettings().setAlwaysAllowMmsData(alwaysAllow);
8390         } finally {
8391             Binder.restoreCallingIdentity(identity);
8392         }
8393     }
8394 
8395     /**
8396      * Updates whether conference event pacakge handling is enabled.
8397      * @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
8398      *                                 otherwise.
8399      */
8400     @Override
setCepEnabled(boolean isCepEnabled)8401     public void setCepEnabled(boolean isCepEnabled) {
8402         TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCepEnabled");
8403 
8404         final long identity = Binder.clearCallingIdentity();
8405         try {
8406             Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled);
8407             for (Phone phone : PhoneFactory.getPhones()) {
8408                 Phone defaultPhone = phone.getImsPhone();
8409                 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
8410                     ImsPhone imsPhone = (ImsPhone) defaultPhone;
8411                     ImsPhoneCallTracker imsPhoneCallTracker =
8412                             (ImsPhoneCallTracker) imsPhone.getCallTracker();
8413                     imsPhoneCallTracker.setConferenceEventPackageEnabled(isCepEnabled);
8414                     Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled + ", for imsPhone "
8415                             + imsPhone.getMsisdn());
8416                 }
8417             }
8418         } finally {
8419             Binder.restoreCallingIdentity(identity);
8420         }
8421     }
8422 
8423     /**
8424      * Notify that an RCS autoconfiguration XML file has been received for provisioning.
8425      *
8426      * @param config       The XML file to be read. ASCII/UTF8 encoded text if not compressed.
8427      * @param isCompressed The XML file is compressed in gzip format and must be decompressed
8428      *                     before being read.
8429      */
8430     @Override
notifyRcsAutoConfigurationReceived(int subId, @NonNull byte[] config, boolean isCompressed)8431     public void notifyRcsAutoConfigurationReceived(int subId, @NonNull byte[] config, boolean
8432             isCompressed) {
8433         TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
8434                 mApp, subId, "notifyRcsAutoConfigurationReceived");
8435         try {
8436             IImsConfig configBinder = getImsConfig(getSlotIndex(subId), ImsFeature.FEATURE_RCS);
8437             if (configBinder == null) {
8438                 Rlog.e(LOG_TAG, "null result for getImsConfig");
8439             } else {
8440                 configBinder.notifyRcsAutoConfigurationReceived(config, isCompressed);
8441             }
8442         } catch (RemoteException e) {
8443             Rlog.e(LOG_TAG, "fail to getImsConfig " + e.getMessage());
8444         }
8445     }
8446 
8447     @Override
isIccLockEnabled(int subId)8448     public boolean isIccLockEnabled(int subId) {
8449         enforceReadPrivilegedPermission("isIccLockEnabled");
8450 
8451         // Now that all security checks passes, perform the operation as ourselves.
8452         final long identity = Binder.clearCallingIdentity();
8453         try {
8454             Phone phone = getPhone(subId);
8455             if (phone != null && phone.getIccCard() != null) {
8456                 return phone.getIccCard().getIccLockEnabled();
8457             } else {
8458                 return false;
8459             }
8460         } finally {
8461             Binder.restoreCallingIdentity(identity);
8462         }
8463     }
8464 
8465     /**
8466      * Set the ICC pin lock enabled or disabled..
8467      *
8468      * @return Integer.MAX_VALUE if enable/disable IccLock successfully. If failed it will return
8469      * 0 or a positive integer as the attempts remaining value.
8470      *
8471      */
8472     @Override
setIccLockEnabled(int subId, boolean enabled, String password)8473     public int setIccLockEnabled(int subId, boolean enabled, String password) {
8474         enforceModifyPermission();
8475 
8476         Phone phone = getPhone(subId);
8477         if (phone == null) {
8478             return 0;
8479         }
8480         // Now that all security checks passes, perform the operation as ourselves.
8481         final long identity = Binder.clearCallingIdentity();
8482         try {
8483             int attemptsRemaining = (int) sendRequest(CMD_SET_ICC_LOCK_ENABLED,
8484                     new Pair<Boolean, String>(enabled, password), phone, null);
8485             return attemptsRemaining;
8486 
8487         } catch (Exception e) {
8488             Log.e(LOG_TAG, "setIccLockEnabled. Exception e =" + e);
8489         } finally {
8490             Binder.restoreCallingIdentity(identity);
8491         }
8492         return 0;
8493     }
8494 
8495     /**
8496      * Change the ICC password used in ICC pin lock.
8497      *
8498      * @return Integer.MAX_VALUE if enable/disable IccLock successfully. If failed it will return
8499      * 0 or a positive integer as the attempts remaining value.
8500      *
8501      */
8502     @Override
changeIccLockPassword(int subId, String oldPassword, String newPassword)8503     public int changeIccLockPassword(int subId, String oldPassword, String newPassword) {
8504         enforceModifyPermission();
8505 
8506         Phone phone = getPhone(subId);
8507         if (phone == null) {
8508             return 0;
8509         }
8510         // Now that all security checks passes, perform the operation as ourselves.
8511         final long identity = Binder.clearCallingIdentity();
8512         try {
8513             int attemptsRemaining = (int) sendRequest(CMD_CHANGE_ICC_LOCK_PASSWORD,
8514                     new Pair<String, String>(oldPassword, newPassword), phone, null);
8515             return attemptsRemaining;
8516 
8517         } catch (Exception e) {
8518             Log.e(LOG_TAG, "changeIccLockPassword. Exception e =" + e);
8519         } finally {
8520             Binder.restoreCallingIdentity(identity);
8521         }
8522         return 0;
8523     }
8524 
8525     @Override
canConnectTo5GInDsdsMode()8526     public boolean canConnectTo5GInDsdsMode() {
8527         return mApp.getResources().getBoolean(R.bool.config_5g_connection_in_dsds_mode);
8528     }
8529 }
8530