blob: 86eb0c975390c6cd0c4d8534d70ef512b7c8e5fb [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
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
17package com.android.phone;
18
Hall Liud892bec2018-11-30 14:51:45 -080019import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Malcolm Chendc8c10e2019-04-10 18:25:07 -070020import static android.telephony.data.ApnSetting.TYPE_MMS;
Hall Liud892bec2018-11-30 14:51:45 -080021
Ta-wei Yen87c49842016-05-13 21:19:52 -070022import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
23
Ta-wei Yen30a69c82016-12-27 14:52:32 -080024import android.Manifest.permission;
Tyler Gunnf70ed162019-04-03 15:28:53 -070025import android.annotation.Nullable;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070026import android.app.AppOpsManager;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080027import android.app.PendingIntent;
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -070028import android.content.ComponentName;
Amit Mahajan7dbbd822019-03-13 17:33:47 -070029import android.content.ContentResolver;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070030import android.content.Context;
31import android.content.Intent;
Derek Tan97ebb422014-09-05 16:55:38 -070032import android.content.SharedPreferences;
Nathan Harold31d7ff32018-10-15 20:20:30 -070033import android.content.pm.ApplicationInfo;
Derek Tan740e1672017-06-27 14:56:27 -070034import android.content.pm.ComponentInfo;
Amith Yamasani6e118872016-02-19 12:53:51 -080035import android.content.pm.PackageInfo;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070036import android.content.pm.PackageManager;
Jack Yu84291ec2017-05-26 16:07:50 -070037import android.net.NetworkStats;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070038import android.net.Uri;
39import android.os.AsyncResult;
40import android.os.Binder;
Hall Liuf19c44f2018-11-27 14:38:17 -080041import android.os.Build;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070042import android.os.Bundle;
43import android.os.Handler;
yinxu504e1392017-04-12 16:03:22 -070044import android.os.IBinder;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070045import android.os.Looper;
46import android.os.Message;
yinxu504e1392017-04-12 16:03:22 -070047import android.os.Messenger;
Tyler Gunn65d45c22017-06-05 11:22:26 -070048import android.os.PersistableBundle;
Brad Ebinger5f64b052017-12-14 14:26:15 -080049import android.os.RemoteException;
Adam Lesinski903a54c2016-04-11 14:49:52 -070050import android.os.ResultReceiver;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070051import android.os.ServiceManager;
Brad Ebingerdac2f002018-04-03 15:17:52 -070052import android.os.ShellCallback;
Pengquan Meng85728fb2018-03-12 16:31:21 -070053import android.os.SystemProperties;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070054import android.os.UserHandle;
Stuart Scott981d8582015-04-21 14:09:50 -070055import android.os.UserManager;
Sooraj Sasindran9a909312016-07-18 11:57:25 -070056import android.os.WorkSource;
Derek Tan97ebb422014-09-05 16:55:38 -070057import android.preference.PreferenceManager;
Ihab Awadf2177b72013-11-25 13:33:23 -080058import android.provider.Settings;
Amit Mahajan7dbbd822019-03-13 17:33:47 -070059import android.provider.Telephony;
Santos Cordon7a1885b2015-02-03 11:15:19 -080060import android.telecom.PhoneAccount;
Nancy Chen31f9ba12016-01-06 11:42:12 -080061import android.telecom.PhoneAccountHandle;
Andrew Lee9431b832015-03-09 18:46:45 -070062import android.telecom.TelecomManager;
Junda Liu12f7d802015-05-01 12:06:44 -070063import android.telephony.CarrierConfigManager;
Michele Berionne482f8202018-11-27 18:57:59 -080064import android.telephony.CarrierRestrictionRules;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070065import android.telephony.CellInfo;
Nathan Haroldf180aac2018-06-01 18:43:55 -070066import android.telephony.CellInfoGsm;
67import android.telephony.CellInfoWcdma;
Nathan Harold3ff88932018-08-14 10:19:49 -070068import android.telephony.CellLocation;
Sooraj Sasindran9a909312016-07-18 11:57:25 -070069import android.telephony.ClientRequestStats;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -070070import android.telephony.ICellInfoCallback;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070071import android.telephony.IccOpenLogicalChannelResponse;
Hall Liu1aa510f2017-11-22 17:40:08 -080072import android.telephony.LocationAccessPolicy;
Ta-wei Yen87c49842016-05-13 21:19:52 -070073import android.telephony.ModemActivityInfo;
Jake Hambye994d462014-02-03 13:10:13 -080074import android.telephony.NeighboringCellInfo;
yinxu504e1392017-04-12 16:03:22 -070075import android.telephony.NetworkScanRequest;
Michele4245e952019-02-04 11:36:23 -080076import android.telephony.PhoneCapability;
Hall Liud892bec2018-11-30 14:51:45 -080077import android.telephony.PhoneNumberRange;
Wink Saville5d475dd2014-10-17 15:00:58 -070078import android.telephony.RadioAccessFamily;
Hall Liub2ac8ef2019-02-28 15:56:23 -080079import android.telephony.RadioAccessSpecifier;
Tyler Gunn65d45c22017-06-05 11:22:26 -070080import android.telephony.Rlog;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070081import android.telephony.ServiceState;
Nathan Harold46b42aa2017-03-10 19:38:22 -080082import android.telephony.SignalStrength;
Jack Yu84291ec2017-05-26 16:07:50 -070083import android.telephony.SmsManager;
Wink Saville0f3b5fc2014-11-11 08:40:49 -080084import android.telephony.SubscriptionInfo;
Jeff Sharkey85190e62014-12-05 09:40:12 -080085import android.telephony.SubscriptionManager;
Sanket Padawe99ef1e32016-05-18 16:12:33 -070086import android.telephony.TelephonyHistogram;
Ta-wei Yenb6929602016-05-24 15:48:27 -070087import android.telephony.TelephonyManager;
Hall Liub2ac8ef2019-02-28 15:56:23 -080088import android.telephony.TelephonyScanManager;
Jordan Liu5aa07002018-12-18 15:44:48 -080089import android.telephony.UiccCardInfo;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000090import android.telephony.UiccSlotInfo;
Tyler Gunn65d45c22017-06-05 11:22:26 -070091import android.telephony.UssdResponse;
Ta-wei Yenb6929602016-05-24 15:48:27 -070092import android.telephony.VisualVoicemailSmsFilterSettings;
Nathan Harold3ff88932018-08-14 10:19:49 -070093import android.telephony.cdma.CdmaCellLocation;
Jack Yub5d8f642018-11-26 11:20:48 -080094import android.telephony.data.ApnSetting;
95import android.telephony.emergency.EmergencyNumber;
Nathan Harold3ff88932018-08-14 10:19:49 -070096import android.telephony.gsm.GsmCellLocation;
Brad Ebinger1c8542e2019-01-14 13:43:14 -080097import android.telephony.ims.ProvisioningManager;
Brad Ebinger35c841c2018-10-01 10:40:55 -070098import android.telephony.ims.aidl.IImsCapabilityCallback;
Brad Ebinger22bc3e42018-01-16 09:39:35 -080099import android.telephony.ims.aidl.IImsConfig;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -0700100import android.telephony.ims.aidl.IImsConfigCallback;
Brad Ebinger22bc3e42018-01-16 09:39:35 -0800101import android.telephony.ims.aidl.IImsMmTelFeature;
102import android.telephony.ims.aidl.IImsRcsFeature;
103import android.telephony.ims.aidl.IImsRegistration;
Brad Ebinger35c841c2018-10-01 10:40:55 -0700104import android.telephony.ims.aidl.IImsRegistrationCallback;
Brad Ebinger1c8542e2019-01-14 13:43:14 -0800105import android.telephony.ims.feature.MmTelFeature;
106import android.telephony.ims.stub.ImsConfigImplBase;
Brad Ebinger1f2b5082018-02-08 16:11:32 -0800107import android.telephony.ims.stub.ImsRegistrationImplBase;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700108import android.text.TextUtils;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800109import android.util.ArraySet;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700110import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -0800111import android.util.Pair;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800112import android.util.Slog;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800113
Brad Ebinger35c841c2018-10-01 10:40:55 -0700114import com.android.ims.ImsException;
Andrew Lee312e8172014-10-23 17:01:36 -0700115import com.android.ims.ImsManager;
Brad Ebinger34bef922017-11-09 10:27:08 -0800116import com.android.ims.internal.IImsServiceFeatureCallback;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700117import com.android.internal.telephony.CallManager;
Tyler Gunn52dcf772017-04-26 11:30:31 -0700118import com.android.internal.telephony.CallStateException;
pkanwar79ec0542017-07-31 14:10:01 -0700119import com.android.internal.telephony.CarrierInfoManager;
chen xu651eec72018-11-11 19:03:44 -0800120import com.android.internal.telephony.CarrierResolver;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700121import com.android.internal.telephony.CellNetworkScanResult;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700122import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700123import com.android.internal.telephony.DefaultPhoneNotifier;
Nathan Harold48d6fd52019-02-06 19:01:40 -0800124import com.android.internal.telephony.HalVersion;
Hall Liud892bec2018-11-30 14:51:45 -0800125import com.android.internal.telephony.INumberVerificationCallback;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700126import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -0800127import com.android.internal.telephony.IccCard;
Jack Yu5f7092c2018-04-13 14:05:37 -0700128import com.android.internal.telephony.LocaleTracker;
Narayan Kamath1c496c22015-04-16 14:40:19 +0100129import com.android.internal.telephony.MccTable;
yinxub1bed742017-04-17 11:45:04 -0700130import com.android.internal.telephony.NetworkScanRequestTracker;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700131import com.android.internal.telephony.OperatorInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700132import com.android.internal.telephony.Phone;
Malcolm Chen2c63d402018-08-14 16:00:53 -0700133import com.android.internal.telephony.PhoneConfigurationManager;
Nathan Harolda667c152016-12-14 11:27:20 -0800134import com.android.internal.telephony.PhoneConstantConversions;
Ta-wei Yen87c49842016-05-13 21:19:52 -0700135import com.android.internal.telephony.PhoneConstants;
Wink Saville36469e72014-06-11 15:17:00 -0700136import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -0700137import com.android.internal.telephony.ProxyController;
Sanket Padawe99ef1e32016-05-18 16:12:33 -0700138import com.android.internal.telephony.RIL;
Svet Ganovb320e182015-04-16 12:30:10 -0700139import com.android.internal.telephony.RILConstants;
Jack Yu5f7092c2018-04-13 14:05:37 -0700140import com.android.internal.telephony.ServiceStateTracker;
Makoto Onukida3bf792018-09-18 16:06:29 -0700141import com.android.internal.telephony.SmsApplication;
142import com.android.internal.telephony.SmsApplication.SmsApplicationData;
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800143import com.android.internal.telephony.SubscriptionController;
Jeff Davidson7e17e312018-02-13 18:17:36 -0800144import com.android.internal.telephony.TelephonyPermissions;
Malcolm Chendc8c10e2019-04-10 18:25:07 -0700145import com.android.internal.telephony.dataconnection.ApnSettingUtils;
sqianf4ca7ed2019-01-15 18:32:07 -0800146import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Derek Tan740e1672017-06-27 14:56:27 -0700147import com.android.internal.telephony.euicc.EuiccConnector;
Brad Ebinger9c0eb502019-01-23 15:06:19 -0800148import com.android.internal.telephony.ims.ImsResolver;
Pengquan Meng6c2dc9f2019-02-06 11:12:53 -0800149import com.android.internal.telephony.metrics.TelephonyMetrics;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700150import com.android.internal.telephony.uicc.IccIoResult;
151import com.android.internal.telephony.uicc.IccUtils;
Nathan Haroldb3014052017-01-25 15:57:32 -0800152import com.android.internal.telephony.uicc.SIMRecords;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700153import com.android.internal.telephony.uicc.UiccCard;
Nathan Haroldb3014052017-01-25 15:57:32 -0800154import com.android.internal.telephony.uicc.UiccCardApplication;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700155import com.android.internal.telephony.uicc.UiccController;
Jeff Davidson7e17e312018-02-13 18:17:36 -0800156import com.android.internal.telephony.uicc.UiccProfile;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000157import com.android.internal.telephony.uicc.UiccSlot;
fionaxu7ed723d2017-05-30 18:58:54 -0700158import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
Jake Hambye994d462014-02-03 13:10:13 -0800159import com.android.internal.util.HexDump;
Ta-wei Yenc9df0432017-04-17 17:09:07 -0700160import com.android.phone.vvm.PhoneAccountHandleConverter;
Ta-wei Yen527a9c02017-01-06 15:29:25 -0800161import com.android.phone.vvm.RemoteVvmTaskManager;
Ta-wei Yenc9df0432017-04-17 17:09:07 -0700162import com.android.phone.vvm.VisualVoicemailSettingsUtil;
Ta-wei Yenc8905312017-03-28 11:14:45 -0700163import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800164
Ta-wei Yenc236d6b2016-06-21 13:33:12 -0700165import java.io.FileDescriptor;
166import java.io.PrintWriter;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800167import java.nio.charset.StandardCharsets;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700168import java.util.ArrayList;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800169import java.util.Arrays;
Makoto Onukida3bf792018-09-18 16:06:29 -0700170import java.util.Collection;
sqian11b7a0e2018-12-05 18:48:28 -0800171import java.util.HashMap;
sqianf4ca7ed2019-01-15 18:32:07 -0800172import java.util.HashSet;
Jake Hambye994d462014-02-03 13:10:13 -0800173import java.util.List;
Narayan Kamath1c496c22015-04-16 14:40:19 +0100174import java.util.Locale;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800175import java.util.Map;
sqianf4ca7ed2019-01-15 18:32:07 -0800176import java.util.Set;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700177
178/**
179 * Implementation of the ITelephony interface.
180 */
Santos Cordon117fee72014-05-16 17:56:12 -0700181public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700182 private static final String LOG_TAG = "PhoneInterfaceManager";
183 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
184 private static final boolean DBG_LOC = false;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800185 private static final boolean DBG_MERGE = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700186
187 // Message codes used with mMainThreadHandler
188 private static final int CMD_HANDLE_PIN_MMI = 1;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700189 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
190 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700191 private static final int CMD_OPEN_CHANNEL = 9;
192 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
193 private static final int CMD_CLOSE_CHANNEL = 11;
194 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800195 private static final int CMD_NV_READ_ITEM = 13;
196 private static final int EVENT_NV_READ_ITEM_DONE = 14;
197 private static final int CMD_NV_WRITE_ITEM = 15;
198 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
199 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
200 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
chen xu6dac5ab2018-10-26 17:39:23 -0700201 private static final int CMD_RESET_MODEM_CONFIG = 19;
202 private static final int EVENT_RESET_MODEM_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800203 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
204 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
205 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
206 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800207 private static final int CMD_SEND_ENVELOPE = 25;
208 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Shuo Qian850e4d6a2018-04-25 21:02:08 +0000209 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
210 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
Derek Tan6b088ee2014-09-05 14:15:18 -0700211 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
212 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
213 private static final int CMD_EXCHANGE_SIM_IO = 31;
214 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800215 private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
216 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
Stuart Scott54788802015-03-30 13:18:01 -0700217 private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
218 private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700219 private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
220 private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700221 private static final int CMD_PERFORM_NETWORK_SCAN = 39;
222 private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
223 private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
224 private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
Meng Wang1a7c35a2016-05-05 20:56:15 -0700225 private static final int CMD_SET_ALLOWED_CARRIERS = 43;
226 private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
227 private static final int CMD_GET_ALLOWED_CARRIERS = 45;
228 private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
pkanwar32d516d2016-10-14 19:37:38 -0700229 private static final int CMD_HANDLE_USSD_REQUEST = 47;
Nathan Haroldb3014052017-01-25 15:57:32 -0800230 private static final int CMD_GET_FORBIDDEN_PLMNS = 48;
231 private static final int EVENT_GET_FORBIDDEN_PLMNS_DONE = 49;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000232 private static final int CMD_SWITCH_SLOTS = 50;
233 private static final int EVENT_SWITCH_SLOTS_DONE = 51;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700234 private static final int CMD_GET_NETWORK_SELECTION_MODE = 52;
235 private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 53;
236 private static final int CMD_GET_CDMA_ROAMING_MODE = 54;
237 private static final int EVENT_GET_CDMA_ROAMING_MODE_DONE = 55;
238 private static final int CMD_SET_CDMA_ROAMING_MODE = 56;
239 private static final int EVENT_SET_CDMA_ROAMING_MODE_DONE = 57;
240 private static final int CMD_SET_CDMA_SUBSCRIPTION_MODE = 58;
241 private static final int EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE = 59;
Nathan Harold3ff88932018-08-14 10:19:49 -0700242 private static final int CMD_GET_ALL_CELL_INFO = 60;
243 private static final int EVENT_GET_ALL_CELL_INFO_DONE = 61;
244 private static final int CMD_GET_CELL_LOCATION = 62;
245 private static final int EVENT_GET_CELL_LOCATION_DONE = 63;
chen xu6dac5ab2018-10-26 17:39:23 -0700246 private static final int CMD_MODEM_REBOOT = 64;
247 private static final int EVENT_CMD_MODEM_REBOOT_DONE = 65;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -0700248 private static final int CMD_REQUEST_CELL_INFO_UPDATE = 66;
249 private static final int EVENT_REQUEST_CELL_INFO_UPDATE_DONE = 67;
Malcolm Chen8e4ed912019-01-15 20:22:16 -0800250 private static final int CMD_REQUEST_ENABLE_MODEM = 68;
251 private static final int EVENT_ENABLE_MODEM_DONE = 69;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700252
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -0800253 // Parameters of select command.
254 private static final int SELECT_COMMAND = 0xA4;
255 private static final int SELECT_P1 = 0x04;
256 private static final int SELECT_P2 = 0;
257 private static final int SELECT_P3 = 0x10;
258
Pengquan Meng85728fb2018-03-12 16:31:21 -0700259 private static final String DEFAULT_NETWORK_MODE_PROPERTY_NAME = "ro.telephony.default_network";
260 private static final String DEFAULT_DATA_ROAMING_PROPERTY_NAME = "ro.com.android.dataroaming";
261 private static final String DEFAULT_MOBILE_DATA_PROPERTY_NAME = "ro.com.android.mobiledata";
262
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700263 /** The singleton instance. */
264 private static PhoneInterfaceManager sInstance;
265
Wink Saville3ab207e2014-11-20 13:07:20 -0800266 private PhoneGlobals mApp;
Wink Saville3ab207e2014-11-20 13:07:20 -0800267 private CallManager mCM;
Stuart Scott981d8582015-04-21 14:09:50 -0700268 private UserManager mUserManager;
Wink Saville3ab207e2014-11-20 13:07:20 -0800269 private AppOpsManager mAppOps;
270 private MainThreadHandler mMainThreadHandler;
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800271 private SubscriptionController mSubscriptionController;
Wink Saville3ab207e2014-11-20 13:07:20 -0800272 private SharedPreferences mTelephonySharedPreferences;
Malcolm Chen2c63d402018-08-14 16:00:53 -0700273 private PhoneConfigurationManager mPhoneConfigurationManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700274
Derek Tan97ebb422014-09-05 16:55:38 -0700275 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
276 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
Jeff Sharkey85190e62014-12-05 09:40:12 -0800277 private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
Brad Ebinger1c8542e2019-01-14 13:43:14 -0800278 private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
Derek Tan89e89d42014-07-08 17:00:10 -0700279
Michelecea4cf22018-12-21 15:00:11 -0800280 // String to store multi SIM allowed
281 private static final String PREF_MULTI_SIM_RESTRICTED = "multisim_restricted";
282
Derek Tan740e1672017-06-27 14:56:27 -0700283 // The AID of ISD-R.
284 private static final String ISDR_AID = "A0000005591010FFFFFFFF8900000100";
285
yinxub1bed742017-04-17 11:45:04 -0700286 private NetworkScanRequestTracker mNetworkScanRequestTracker;
287
David Kelly5e06a7f2018-03-12 14:10:59 +0000288 private static final int TYPE_ALLOCATION_CODE_LENGTH = 8;
289 private static final int MANUFACTURER_CODE_LENGTH = 8;
290
Derek Tan89e89d42014-07-08 17:00:10 -0700291 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700292 * A request object to use for transmitting data to an ICC.
293 */
294 private static final class IccAPDUArgument {
295 public int channel, cla, command, p1, p2, p3;
296 public String data;
297
298 public IccAPDUArgument(int channel, int cla, int command,
299 int p1, int p2, int p3, String data) {
300 this.channel = channel;
301 this.cla = cla;
302 this.command = command;
303 this.p1 = p1;
304 this.p2 = p2;
305 this.p3 = p3;
306 this.data = data;
307 }
308 }
309
310 /**
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700311 * A request object to use for transmitting data to an ICC.
312 */
313 private static final class ManualNetworkSelectionArgument {
314 public OperatorInfo operatorInfo;
315 public boolean persistSelection;
316
317 public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
318 this.operatorInfo = operatorInfo;
319 this.persistSelection = persistSelection;
320 }
321 }
322
323 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700324 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
325 * request after sending. The main thread will notify the request when it is complete.
326 */
327 private static final class MainThreadRequest {
328 /** The argument to use for the request */
329 public Object argument;
330 /** The result of the request that is run on the main thread */
331 public Object result;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800332 // The subscriber id that this request applies to. Defaults to
333 // SubscriptionManager.INVALID_SUBSCRIPTION_ID
334 public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700335
Nathan Harold92bed182018-10-12 18:16:49 -0700336 // In cases where subId is unavailable, the caller needs to specify the phone.
337 public Phone phone;
338
vagdeviaf9a5b92018-08-15 16:01:53 -0700339 public WorkSource workSource;
340
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700341 public MainThreadRequest(Object argument) {
342 this.argument = argument;
343 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800344
Nathan Harold92bed182018-10-12 18:16:49 -0700345 MainThreadRequest(Object argument, Phone phone, WorkSource workSource) {
346 this.argument = argument;
347 if (phone != null) {
348 this.phone = phone;
349 }
350 this.workSource = workSource;
351 }
352
vagdeviaf9a5b92018-08-15 16:01:53 -0700353 MainThreadRequest(Object argument, Integer subId, WorkSource workSource) {
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800354 this.argument = argument;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800355 if (subId != null) {
356 this.subId = subId;
357 }
vagdeviaf9a5b92018-08-15 16:01:53 -0700358 this.workSource = workSource;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800359 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700360 }
361
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800362 private static final class IncomingThirdPartyCallArgs {
363 public final ComponentName component;
364 public final String callId;
365 public final String callerDisplayName;
366
367 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
368 String callerDisplayName) {
369 this.component = component;
370 this.callId = callId;
371 this.callerDisplayName = callerDisplayName;
372 }
373 }
374
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700375 /**
376 * A handler that processes messages on the main thread in the phone process. Since many
377 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
378 * inbound binder threads to the main thread in the phone process. The Binder thread
379 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
380 * on, which will be notified when the operation completes and will contain the result of the
381 * request.
382 *
383 * <p>If a MainThreadRequest object is provided in the msg.obj field,
384 * note that request.result must be set to something non-null for the calling thread to
385 * unblock.
386 */
387 private final class MainThreadHandler extends Handler {
388 @Override
389 public void handleMessage(Message msg) {
390 MainThreadRequest request;
391 Message onCompleted;
392 AsyncResult ar;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800393 UiccCard uiccCard;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700394 IccAPDUArgument iccArgument;
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800395 final Phone defaultPhone = getDefaultPhone();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700396
397 switch (msg.what) {
Pengquan Menga1bb6272018-09-06 09:59:22 -0700398 case CMD_HANDLE_USSD_REQUEST: {
399 request = (MainThreadRequest) msg.obj;
400 final Phone phone = getPhoneFromRequest(request);
401 Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
402 String ussdRequest = ussdObject.first;
403 ResultReceiver wrappedCallback = ussdObject.second;
Tyler Gunn65d45c22017-06-05 11:22:26 -0700404
Pengquan Menga1bb6272018-09-06 09:59:22 -0700405 if (!isUssdApiAllowed(request.subId)) {
406 // Carrier does not support use of this API, return failure.
407 Rlog.w(LOG_TAG, "handleUssdRequest: carrier does not support USSD apis.");
408 UssdResponse response = new UssdResponse(ussdRequest, null);
409 Bundle returnData = new Bundle();
410 returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
411 wrappedCallback.send(TelephonyManager.USSD_RETURN_FAILURE, returnData);
Tyler Gunn65d45c22017-06-05 11:22:26 -0700412
Pengquan Menga1bb6272018-09-06 09:59:22 -0700413 request.result = true;
414 notifyRequester(request);
415 return;
416 }
Tyler Gunn65d45c22017-06-05 11:22:26 -0700417
Pengquan Menga1bb6272018-09-06 09:59:22 -0700418 try {
419 request.result = phone != null
420 ? phone.handleUssdRequest(ussdRequest, wrappedCallback) : false;
421 } catch (CallStateException cse) {
422 request.result = false;
423 }
424 // Wake up the requesting thread
425 notifyRequester(request);
426 break;
pkanwar32d516d2016-10-14 19:37:38 -0700427 }
428
Yorke Lee716f67e2015-06-17 15:39:16 -0700429 case CMD_HANDLE_PIN_MMI: {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700430 request = (MainThreadRequest) msg.obj;
Yorke Lee716f67e2015-06-17 15:39:16 -0700431 final Phone phone = getPhoneFromRequest(request);
432 request.result = phone != null ?
433 getPhoneFromRequest(request).handlePinMmi((String) request.argument)
434 : false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700435 // Wake up the requesting thread
Pengquan Menga1bb6272018-09-06 09:59:22 -0700436 notifyRequester(request);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700437 break;
Yorke Lee716f67e2015-06-17 15:39:16 -0700438 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700439
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700440 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700441 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700442 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800443 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700444 if (uiccCard == null) {
445 loge("iccTransmitApduLogicalChannel: No UICC");
446 request.result = new IccIoResult(0x6F, 0, (byte[])null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700447 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700448 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700449 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
450 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700451 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700452 iccArgument.channel, iccArgument.cla, iccArgument.command,
453 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700454 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700455 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700456 break;
457
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700458 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700459 ar = (AsyncResult) msg.obj;
460 request = (MainThreadRequest) ar.userObj;
461 if (ar.exception == null && ar.result != null) {
462 request.result = ar.result;
463 } else {
464 request.result = new IccIoResult(0x6F, 0, (byte[])null);
465 if (ar.result == null) {
466 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800467 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700468 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800469 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700470 } else {
471 loge("iccTransmitApduLogicalChannel: Unknown exception");
472 }
473 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700474 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700475 break;
476
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700477 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
478 request = (MainThreadRequest) msg.obj;
479 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800480 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700481 if (uiccCard == null) {
482 loge("iccTransmitApduBasicChannel: No UICC");
483 request.result = new IccIoResult(0x6F, 0, (byte[])null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700484 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700485 } else {
486 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
487 request);
488 uiccCard.iccTransmitApduBasicChannel(
489 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
490 iccArgument.p3, iccArgument.data, onCompleted);
491 }
492 break;
493
494 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
495 ar = (AsyncResult) msg.obj;
496 request = (MainThreadRequest) ar.userObj;
497 if (ar.exception == null && ar.result != null) {
498 request.result = ar.result;
499 } else {
500 request.result = new IccIoResult(0x6F, 0, (byte[])null);
501 if (ar.result == null) {
502 loge("iccTransmitApduBasicChannel: Empty response");
503 } else if (ar.exception instanceof CommandException) {
504 loge("iccTransmitApduBasicChannel: CommandException: " +
505 ar.exception);
506 } else {
507 loge("iccTransmitApduBasicChannel: Unknown exception");
508 }
509 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700510 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700511 break;
512
513 case CMD_EXCHANGE_SIM_IO:
514 request = (MainThreadRequest) msg.obj;
515 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800516 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700517 if (uiccCard == null) {
518 loge("iccExchangeSimIO: No UICC");
519 request.result = new IccIoResult(0x6F, 0, (byte[])null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700520 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700521 } else {
522 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
523 request);
524 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
525 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
526 iccArgument.data, onCompleted);
527 }
528 break;
529
530 case EVENT_EXCHANGE_SIM_IO_DONE:
531 ar = (AsyncResult) msg.obj;
532 request = (MainThreadRequest) ar.userObj;
533 if (ar.exception == null && ar.result != null) {
534 request.result = ar.result;
535 } else {
536 request.result = new IccIoResult(0x6f, 0, (byte[])null);
537 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700538 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700539 break;
540
Derek Tan4d5e5c12014-02-04 11:54:58 -0800541 case CMD_SEND_ENVELOPE:
542 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800543 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700544 if (uiccCard == null) {
545 loge("sendEnvelopeWithStatus: No UICC");
546 request.result = new IccIoResult(0x6F, 0, (byte[])null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700547 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700548 } else {
549 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
550 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
551 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800552 break;
553
554 case EVENT_SEND_ENVELOPE_DONE:
555 ar = (AsyncResult) msg.obj;
556 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700557 if (ar.exception == null && ar.result != null) {
558 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800559 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700560 request.result = new IccIoResult(0x6F, 0, (byte[])null);
561 if (ar.result == null) {
562 loge("sendEnvelopeWithStatus: Empty response");
563 } else if (ar.exception instanceof CommandException) {
564 loge("sendEnvelopeWithStatus: CommandException: " +
565 ar.exception);
566 } else {
567 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
568 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800569 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700570 notifyRequester(request);
Derek Tan4d5e5c12014-02-04 11:54:58 -0800571 break;
572
Shishir Agrawal566b7612013-10-28 14:41:00 -0700573 case CMD_OPEN_CHANNEL:
574 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800575 uiccCard = getUiccCardFromRequest(request);
Ajay Nambid7454d32015-12-03 13:50:00 -0800576 Pair<String, Integer> openChannelArgs = (Pair<String, Integer>) request.argument;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700577 if (uiccCard == null) {
578 loge("iccOpenLogicalChannel: No UICC");
Shishir Agrawalfc0492a2016-02-17 11:15:33 -0800579 request.result = new IccOpenLogicalChannelResponse(-1,
580 IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700581 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700582 } else {
583 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
Ajay Nambid7454d32015-12-03 13:50:00 -0800584 uiccCard.iccOpenLogicalChannel(openChannelArgs.first,
585 openChannelArgs.second, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700586 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700587 break;
588
589 case EVENT_OPEN_CHANNEL_DONE:
590 ar = (AsyncResult) msg.obj;
591 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700592 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700593 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700594 int[] result = (int[]) ar.result;
595 int channelId = result[0];
596 byte[] selectResponse = null;
597 if (result.length > 1) {
598 selectResponse = new byte[result.length - 1];
599 for (int i = 1; i < result.length; ++i) {
600 selectResponse[i - 1] = (byte) result[i];
601 }
602 }
603 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700604 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700605 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700606 if (ar.result == null) {
607 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700608 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700609 if (ar.exception != null) {
610 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
611 }
612
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700613 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Junda Liua754ba12015-05-20 01:17:52 -0700614 if (ar.exception instanceof CommandException) {
615 CommandException.Error error =
616 ((CommandException) (ar.exception)).getCommandError();
617 if (error == CommandException.Error.MISSING_RESOURCE) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700618 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Junda Liua754ba12015-05-20 01:17:52 -0700619 } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700620 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700621 }
622 }
623 openChannelResp = new IccOpenLogicalChannelResponse(
624 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700625 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700626 request.result = openChannelResp;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700627 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700628 break;
629
630 case CMD_CLOSE_CHANNEL:
631 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800632 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700633 if (uiccCard == null) {
634 loge("iccCloseLogicalChannel: No UICC");
Yoshiaki Naka2e29d822016-09-02 19:27:39 +0900635 request.result = false;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700636 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700637 } else {
638 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
639 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
640 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700641 break;
642
643 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800644 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
645 break;
646
647 case CMD_NV_READ_ITEM:
648 request = (MainThreadRequest) msg.obj;
649 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800650 defaultPhone.nvReadItem((Integer) request.argument, onCompleted,
651 request.workSource);
Jake Hambye994d462014-02-03 13:10:13 -0800652 break;
653
654 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700655 ar = (AsyncResult) msg.obj;
656 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800657 if (ar.exception == null && ar.result != null) {
658 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700659 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800660 request.result = "";
661 if (ar.result == null) {
662 loge("nvReadItem: Empty response");
663 } else if (ar.exception instanceof CommandException) {
664 loge("nvReadItem: CommandException: " +
665 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700666 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800667 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700668 }
669 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700670 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700671 break;
672
Jake Hambye994d462014-02-03 13:10:13 -0800673 case CMD_NV_WRITE_ITEM:
674 request = (MainThreadRequest) msg.obj;
675 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
676 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800677 defaultPhone.nvWriteItem(idValue.first, idValue.second, onCompleted,
vagdeviaf9a5b92018-08-15 16:01:53 -0700678 request.workSource);
Jake Hambye994d462014-02-03 13:10:13 -0800679 break;
680
681 case EVENT_NV_WRITE_ITEM_DONE:
682 handleNullReturnEvent(msg, "nvWriteItem");
683 break;
684
685 case CMD_NV_WRITE_CDMA_PRL:
686 request = (MainThreadRequest) msg.obj;
687 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800688 defaultPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
Jake Hambye994d462014-02-03 13:10:13 -0800689 break;
690
691 case EVENT_NV_WRITE_CDMA_PRL_DONE:
692 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
693 break;
694
chen xu6dac5ab2018-10-26 17:39:23 -0700695 case CMD_RESET_MODEM_CONFIG:
Jake Hambye994d462014-02-03 13:10:13 -0800696 request = (MainThreadRequest) msg.obj;
chen xu6dac5ab2018-10-26 17:39:23 -0700697 onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800698 defaultPhone.resetModemConfig(onCompleted);
Jake Hambye994d462014-02-03 13:10:13 -0800699 break;
700
chen xu6dac5ab2018-10-26 17:39:23 -0700701 case EVENT_RESET_MODEM_CONFIG_DONE:
702 handleNullReturnEvent(msg, "resetModemConfig");
Jake Hambye994d462014-02-03 13:10:13 -0800703 break;
704
Jake Hamby7c27be32014-03-03 13:25:59 -0800705 case CMD_GET_PREFERRED_NETWORK_TYPE:
706 request = (MainThreadRequest) msg.obj;
707 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
Stuart Scott54788802015-03-30 13:18:01 -0700708 getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -0800709 break;
710
711 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
712 ar = (AsyncResult) msg.obj;
713 request = (MainThreadRequest) ar.userObj;
714 if (ar.exception == null && ar.result != null) {
715 request.result = ar.result; // Integer
716 } else {
Sanket Padawecfc2d352016-01-05 19:52:14 -0800717 request.result = null;
Jake Hamby7c27be32014-03-03 13:25:59 -0800718 if (ar.result == null) {
719 loge("getPreferredNetworkType: Empty response");
720 } else if (ar.exception instanceof CommandException) {
721 loge("getPreferredNetworkType: CommandException: " +
722 ar.exception);
723 } else {
724 loge("getPreferredNetworkType: Unknown exception");
725 }
726 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700727 notifyRequester(request);
Jake Hamby7c27be32014-03-03 13:25:59 -0800728 break;
729
730 case CMD_SET_PREFERRED_NETWORK_TYPE:
731 request = (MainThreadRequest) msg.obj;
732 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
733 int networkType = (Integer) request.argument;
Stuart Scott54788802015-03-30 13:18:01 -0700734 getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -0800735 break;
736
737 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
738 handleNullReturnEvent(msg, "setPreferredNetworkType");
739 break;
740
Shuo Qian850e4d6a2018-04-25 21:02:08 +0000741 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
742 request = (MainThreadRequest)msg.obj;
743 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800744 defaultPhone.invokeOemRilRequestRaw((byte[]) request.argument, onCompleted);
Shuo Qian850e4d6a2018-04-25 21:02:08 +0000745 break;
746
747 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
748 ar = (AsyncResult)msg.obj;
749 request = (MainThreadRequest)ar.userObj;
750 request.result = ar;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700751 notifyRequester(request);
Shuo Qian850e4d6a2018-04-25 21:02:08 +0000752 break;
753
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800754 case CMD_SET_VOICEMAIL_NUMBER:
755 request = (MainThreadRequest) msg.obj;
756 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
757 Pair<String, String> tagNum = (Pair<String, String>) request.argument;
Stuart Scott584921c2015-01-15 17:10:34 -0800758 getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
759 onCompleted);
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800760 break;
761
762 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
763 handleNullReturnEvent(msg, "setVoicemailNumber");
764 break;
765
Stuart Scott54788802015-03-30 13:18:01 -0700766 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
767 request = (MainThreadRequest) msg.obj;
768 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
769 request);
770 getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
771 break;
772
773 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
774 handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
775 break;
776
Shishir Agrawal302c8692015-06-19 13:49:39 -0700777 case CMD_PERFORM_NETWORK_SCAN:
778 request = (MainThreadRequest) msg.obj;
779 onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
780 getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
781 break;
782
783 case EVENT_PERFORM_NETWORK_SCAN_DONE:
784 ar = (AsyncResult) msg.obj;
785 request = (MainThreadRequest) ar.userObj;
786 CellNetworkScanResult cellScanResult;
787 if (ar.exception == null && ar.result != null) {
788 cellScanResult = new CellNetworkScanResult(
789 CellNetworkScanResult.STATUS_SUCCESS,
790 (List<OperatorInfo>) ar.result);
791 } else {
792 if (ar.result == null) {
793 loge("getCellNetworkScanResults: Empty response");
794 }
795 if (ar.exception != null) {
796 loge("getCellNetworkScanResults: Exception: " + ar.exception);
797 }
798 int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
799 if (ar.exception instanceof CommandException) {
800 CommandException.Error error =
801 ((CommandException) (ar.exception)).getCommandError();
802 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
803 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
804 } else if (error == CommandException.Error.GENERIC_FAILURE) {
805 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
806 }
807 }
808 cellScanResult = new CellNetworkScanResult(errorCode, null);
809 }
810 request.result = cellScanResult;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700811 notifyRequester(request);
Shishir Agrawal302c8692015-06-19 13:49:39 -0700812 break;
813
814 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
815 request = (MainThreadRequest) msg.obj;
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700816 ManualNetworkSelectionArgument selArg =
817 (ManualNetworkSelectionArgument) request.argument;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700818 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
819 request);
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700820 getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
821 selArg.persistSelection, onCompleted);
Shishir Agrawal302c8692015-06-19 13:49:39 -0700822 break;
823
824 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
Pengquan Menge3d01e22018-09-20 15:25:35 -0700825 ar = (AsyncResult) msg.obj;
826 request = (MainThreadRequest) ar.userObj;
827 if (ar.exception == null) {
828 request.result = true;
829 } else {
830 request.result = false;
831 loge("setNetworkSelectionModeManual " + ar.exception);
832 }
833 notifyRequester(request);
834 mApp.onNetworkSelectionChanged(request.subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -0700835 break;
836
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700837 case CMD_GET_MODEM_ACTIVITY_INFO:
838 request = (MainThreadRequest) msg.obj;
839 onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
James Mattisab947702019-04-03 14:18:34 -0700840 if (defaultPhone != null) {
841 defaultPhone.getModemActivityInfo(onCompleted, request.workSource);
842 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700843 break;
844
845 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
846 ar = (AsyncResult) msg.obj;
847 request = (MainThreadRequest) ar.userObj;
848 if (ar.exception == null && ar.result != null) {
849 request.result = ar.result;
850 } else {
851 if (ar.result == null) {
852 loge("queryModemActivityInfo: Empty response");
853 } else if (ar.exception instanceof CommandException) {
854 loge("queryModemActivityInfo: CommandException: " +
855 ar.exception);
856 } else {
857 loge("queryModemActivityInfo: Unknown exception");
858 }
859 }
Amit Mahajand4766222016-01-28 15:28:28 -0800860 // Result cannot be null. Return ModemActivityInfo with all fields set to 0.
861 if (request.result == null) {
862 request.result = new ModemActivityInfo(0, 0, 0, null, 0, 0);
863 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700864 notifyRequester(request);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700865 break;
866
Meng Wang1a7c35a2016-05-05 20:56:15 -0700867 case CMD_SET_ALLOWED_CARRIERS:
868 request = (MainThreadRequest) msg.obj;
Michele Berionne482f8202018-11-27 18:57:59 -0800869 CarrierRestrictionRules argument =
870 (CarrierRestrictionRules) request.argument;
Meng Wang1a7c35a2016-05-05 20:56:15 -0700871 onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
Michele Berionne482f8202018-11-27 18:57:59 -0800872 defaultPhone.setAllowedCarriers(argument, onCompleted, request.workSource);
Meng Wang1a7c35a2016-05-05 20:56:15 -0700873 break;
874
875 case EVENT_SET_ALLOWED_CARRIERS_DONE:
876 ar = (AsyncResult) msg.obj;
877 request = (MainThreadRequest) ar.userObj;
878 if (ar.exception == null && ar.result != null) {
879 request.result = ar.result;
880 } else {
Michele Berionne482f8202018-11-27 18:57:59 -0800881 request.result = TelephonyManager.SET_CARRIER_RESTRICTION_ERROR;
882 if (ar.exception instanceof CommandException) {
883 loge("setAllowedCarriers: CommandException: " + ar.exception);
884 CommandException.Error error =
885 ((CommandException) (ar.exception)).getCommandError();
886 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
887 request.result =
888 TelephonyManager.SET_CARRIER_RESTRICTION_NOT_SUPPORTED;
889 }
Meng Wang1a7c35a2016-05-05 20:56:15 -0700890 } else {
891 loge("setAllowedCarriers: Unknown exception");
892 }
893 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700894 notifyRequester(request);
Meng Wang1a7c35a2016-05-05 20:56:15 -0700895 break;
896
897 case CMD_GET_ALLOWED_CARRIERS:
898 request = (MainThreadRequest) msg.obj;
899 onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800900 defaultPhone.getAllowedCarriers(onCompleted, request.workSource);
Meng Wang1a7c35a2016-05-05 20:56:15 -0700901 break;
902
903 case EVENT_GET_ALLOWED_CARRIERS_DONE:
904 ar = (AsyncResult) msg.obj;
905 request = (MainThreadRequest) ar.userObj;
906 if (ar.exception == null && ar.result != null) {
907 request.result = ar.result;
908 } else {
Michele Berionne482f8202018-11-27 18:57:59 -0800909 request.result = new IllegalStateException(
910 "Failed to get carrier restrictions");
Meng Wang1a7c35a2016-05-05 20:56:15 -0700911 if (ar.result == null) {
912 loge("getAllowedCarriers: Empty response");
913 } else if (ar.exception instanceof CommandException) {
914 loge("getAllowedCarriers: CommandException: " +
915 ar.exception);
916 } else {
917 loge("getAllowedCarriers: Unknown exception");
918 }
919 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700920 notifyRequester(request);
Meng Wang1a7c35a2016-05-05 20:56:15 -0700921 break;
922
Nathan Haroldb3014052017-01-25 15:57:32 -0800923 case EVENT_GET_FORBIDDEN_PLMNS_DONE:
924 ar = (AsyncResult) msg.obj;
925 request = (MainThreadRequest) ar.userObj;
926 if (ar.exception == null && ar.result != null) {
927 request.result = ar.result;
928 } else {
929 request.result = new IllegalArgumentException(
930 "Failed to retrieve Forbidden Plmns");
931 if (ar.result == null) {
932 loge("getForbiddenPlmns: Empty response");
933 } else {
934 loge("getForbiddenPlmns: Unknown exception");
935 }
936 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700937 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -0800938 break;
939
940 case CMD_GET_FORBIDDEN_PLMNS:
941 request = (MainThreadRequest) msg.obj;
942 uiccCard = getUiccCardFromRequest(request);
943 if (uiccCard == null) {
944 loge("getForbiddenPlmns() UiccCard is null");
945 request.result = new IllegalArgumentException(
946 "getForbiddenPlmns() UiccCard is null");
Pengquan Menga1bb6272018-09-06 09:59:22 -0700947 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -0800948 break;
949 }
950 Integer appType = (Integer) request.argument;
951 UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
952 if (uiccApp == null) {
953 loge("getForbiddenPlmns() no app with specified type -- "
954 + appType);
955 request.result = new IllegalArgumentException("Failed to get UICC App");
Pengquan Menga1bb6272018-09-06 09:59:22 -0700956 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -0800957 break;
958 } else {
959 if (DBG) logv("getForbiddenPlmns() found app " + uiccApp.getAid()
960 + " specified type -- " + appType);
961 }
962 onCompleted = obtainMessage(EVENT_GET_FORBIDDEN_PLMNS_DONE, request);
963 ((SIMRecords) uiccApp.getIccRecords()).getForbiddenPlmns(
964 onCompleted);
965 break;
966
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000967 case CMD_SWITCH_SLOTS:
968 request = (MainThreadRequest) msg.obj;
969 int[] physicalSlots = (int[]) request.argument;
970 onCompleted = obtainMessage(EVENT_SWITCH_SLOTS_DONE, request);
971 UiccController.getInstance().switchSlots(physicalSlots, onCompleted);
972 break;
973
974 case EVENT_SWITCH_SLOTS_DONE:
975 ar = (AsyncResult) msg.obj;
976 request = (MainThreadRequest) ar.userObj;
977 request.result = (ar.exception == null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700978 notifyRequester(request);
979 break;
980 case CMD_GET_NETWORK_SELECTION_MODE:
981 request = (MainThreadRequest) msg.obj;
982 onCompleted = obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, request);
983 getPhoneFromRequest(request).getNetworkSelectionMode(onCompleted);
984 break;
985
986 case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
987 ar = (AsyncResult) msg.obj;
988 request = (MainThreadRequest) ar.userObj;
989 if (ar.exception != null) {
990 request.result = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
991 } else {
992 int mode = ((int[]) ar.result)[0];
993 if (mode == 0) {
994 request.result = TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
995 } else {
996 request.result = TelephonyManager.NETWORK_SELECTION_MODE_MANUAL;
997 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000998 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700999 notifyRequester(request);
1000 break;
1001 case CMD_GET_CDMA_ROAMING_MODE:
1002 request = (MainThreadRequest) msg.obj;
1003 onCompleted = obtainMessage(EVENT_GET_CDMA_ROAMING_MODE_DONE, request);
1004 getPhoneFromRequest(request).queryCdmaRoamingPreference(onCompleted);
1005 break;
1006 case EVENT_GET_CDMA_ROAMING_MODE_DONE:
1007 ar = (AsyncResult) msg.obj;
1008 request = (MainThreadRequest) ar.userObj;
1009 if (ar.exception != null) {
1010 request.result = TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT;
1011 } else {
1012 request.result = ((int[]) ar.result)[0];
1013 }
1014 notifyRequester(request);
1015 break;
1016 case CMD_SET_CDMA_ROAMING_MODE:
1017 request = (MainThreadRequest) msg.obj;
1018 onCompleted = obtainMessage(EVENT_SET_CDMA_ROAMING_MODE_DONE, request);
1019 int mode = (int) request.argument;
1020 getPhoneFromRequest(request).setCdmaRoamingPreference(mode, onCompleted);
1021 break;
1022 case EVENT_SET_CDMA_ROAMING_MODE_DONE:
1023 ar = (AsyncResult) msg.obj;
1024 request = (MainThreadRequest) ar.userObj;
1025 request.result = ar.exception == null;
1026 notifyRequester(request);
1027 break;
1028 case CMD_SET_CDMA_SUBSCRIPTION_MODE:
1029 request = (MainThreadRequest) msg.obj;
1030 onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
1031 int subscriptionMode = (int) request.argument;
1032 getPhoneFromRequest(request).setCdmaSubscription(subscriptionMode, onCompleted);
1033 break;
1034 case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
1035 ar = (AsyncResult) msg.obj;
1036 request = (MainThreadRequest) ar.userObj;
1037 request.result = ar.exception == null;
1038 notifyRequester(request);
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001039 break;
Nathan Harold3ff88932018-08-14 10:19:49 -07001040 case CMD_GET_ALL_CELL_INFO:
1041 request = (MainThreadRequest) msg.obj;
Nathan Harold3ff88932018-08-14 10:19:49 -07001042 onCompleted = obtainMessage(EVENT_GET_ALL_CELL_INFO_DONE, request);
Nathan Harold92bed182018-10-12 18:16:49 -07001043 request.phone.requestCellInfoUpdate(request.workSource, onCompleted);
Nathan Harold3ff88932018-08-14 10:19:49 -07001044 break;
Nathan Harold3ff88932018-08-14 10:19:49 -07001045 case EVENT_GET_ALL_CELL_INFO_DONE:
1046 ar = (AsyncResult) msg.obj;
1047 request = (MainThreadRequest) ar.userObj;
Nathan Harold8d0f1742018-10-02 12:14:47 -07001048 // If a timeout occurs, the response will be null
1049 request.result = (ar.exception == null && ar.result != null)
1050 ? ar.result : new ArrayList<CellInfo>();
Nathan Harold3ff88932018-08-14 10:19:49 -07001051 synchronized (request) {
1052 request.notifyAll();
1053 }
1054 break;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001055 case CMD_REQUEST_CELL_INFO_UPDATE:
1056 request = (MainThreadRequest) msg.obj;
1057 request.phone.requestCellInfoUpdate(request.workSource,
1058 obtainMessage(EVENT_REQUEST_CELL_INFO_UPDATE_DONE, request));
1059 break;
1060 case EVENT_REQUEST_CELL_INFO_UPDATE_DONE:
1061 ar = (AsyncResult) msg.obj;
1062 request = (MainThreadRequest) ar.userObj;
1063 ICellInfoCallback cb = (ICellInfoCallback) request.argument;
1064 try {
1065 if (ar.exception != null) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001066 Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
Nathan Harolde82c4b82018-12-18 19:40:37 -08001067 cb.onError(TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
1068 new android.os.ParcelableException(ar.exception));
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001069 } else if (ar.result == null) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001070 Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
Nathan Harolde82c4b82018-12-18 19:40:37 -08001071 cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001072 } else {
1073 // use the result as returned
1074 cb.onCellInfo((List<CellInfo>) ar.result);
1075 }
1076 } catch (RemoteException re) {
1077 Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
1078 }
1079 break;
1080 case CMD_GET_CELL_LOCATION:
Nathan Harold3ff88932018-08-14 10:19:49 -07001081 request = (MainThreadRequest) msg.obj;
1082 WorkSource ws = (WorkSource) request.argument;
1083 Phone phone = getPhoneFromRequest(request);
1084 phone.getCellLocation(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
1085 break;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001086 case EVENT_GET_CELL_LOCATION_DONE:
Nathan Harold3ff88932018-08-14 10:19:49 -07001087 ar = (AsyncResult) msg.obj;
1088 request = (MainThreadRequest) ar.userObj;
1089 if (ar.exception == null) {
1090 request.result = ar.result;
1091 } else {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001092 phone = getPhoneFromRequest(request);
Nathan Harold3ff88932018-08-14 10:19:49 -07001093 request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
1094 ? new CdmaCellLocation() : new GsmCellLocation();
1095 }
1096
1097 synchronized (request) {
1098 request.notifyAll();
1099 }
1100 break;
chen xu6dac5ab2018-10-26 17:39:23 -07001101 case CMD_MODEM_REBOOT:
1102 request = (MainThreadRequest) msg.obj;
1103 onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001104 defaultPhone.rebootModem(onCompleted);
chen xu6dac5ab2018-10-26 17:39:23 -07001105 break;
chen xu6dac5ab2018-10-26 17:39:23 -07001106 case EVENT_CMD_MODEM_REBOOT_DONE:
1107 handleNullReturnEvent(msg, "rebootModem");
1108 break;
Malcolm Chen8e4ed912019-01-15 20:22:16 -08001109 case CMD_REQUEST_ENABLE_MODEM:
1110 request = (MainThreadRequest) msg.obj;
1111 boolean enable = (boolean) request.argument;
1112 onCompleted = obtainMessage(EVENT_ENABLE_MODEM_DONE, request);
Nazanin Bakhshi33d584b2019-02-27 10:44:32 -08001113 onCompleted.arg1 = enable ? 1 : 0;
Malcolm Chen8e4ed912019-01-15 20:22:16 -08001114 PhoneConfigurationManager.getInstance()
1115 .enablePhone(request.phone, enable, onCompleted);
1116 break;
1117 case EVENT_ENABLE_MODEM_DONE:
1118 ar = (AsyncResult) msg.obj;
1119 request = (MainThreadRequest) ar.userObj;
1120 request.result = (ar.exception == null);
Nazanin Bakhshi33d584b2019-02-27 10:44:32 -08001121 //update the cache as modem status has changed
1122 mPhoneConfigurationManager.addToPhoneStatusCache(
1123 request.phone.getPhoneId(), msg.arg1 == 1);
Pengquan Meng6c2dc9f2019-02-06 11:12:53 -08001124 updateModemStateMetrics();
Malcolm Chen8e4ed912019-01-15 20:22:16 -08001125 notifyRequester(request);
1126 break;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001127 default:
1128 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
1129 break;
1130 }
1131 }
Jake Hambye994d462014-02-03 13:10:13 -08001132
Pengquan Menga1bb6272018-09-06 09:59:22 -07001133 private void notifyRequester(MainThreadRequest request) {
1134 synchronized (request) {
1135 request.notifyAll();
1136 }
1137 }
1138
Jake Hambye994d462014-02-03 13:10:13 -08001139 private void handleNullReturnEvent(Message msg, String command) {
1140 AsyncResult ar = (AsyncResult) msg.obj;
1141 MainThreadRequest request = (MainThreadRequest) ar.userObj;
1142 if (ar.exception == null) {
1143 request.result = true;
1144 } else {
1145 request.result = false;
1146 if (ar.exception instanceof CommandException) {
1147 loge(command + ": CommandException: " + ar.exception);
1148 } else {
1149 loge(command + ": Unknown exception");
1150 }
1151 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001152 notifyRequester(request);
Jake Hambye994d462014-02-03 13:10:13 -08001153 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001154 }
1155
1156 /**
1157 * Posts the specified command to be executed on the main thread,
1158 * waits for the request to complete, and returns the result.
1159 * @see #sendRequestAsync
1160 */
1161 private Object sendRequest(int command, Object argument) {
Nathan Harold92bed182018-10-12 18:16:49 -07001162 return sendRequest(
1163 command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, null, null);
vagdeviaf9a5b92018-08-15 16:01:53 -07001164 }
1165
1166 /**
1167 * Posts the specified command to be executed on the main thread,
1168 * waits for the request to complete, and returns the result.
1169 * @see #sendRequestAsync
1170 */
1171 private Object sendRequest(int command, Object argument, WorkSource workSource) {
1172 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
Nathan Harold92bed182018-10-12 18:16:49 -07001173 null, workSource);
Wink Saville36469e72014-06-11 15:17:00 -07001174 }
1175
1176 /**
1177 * Posts the specified command to be executed on the main thread,
1178 * waits for the request to complete, and returns the result.
1179 * @see #sendRequestAsync
1180 */
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001181 private Object sendRequest(int command, Object argument, Integer subId) {
Nathan Harold92bed182018-10-12 18:16:49 -07001182 return sendRequest(command, argument, subId, null, null);
vagdeviaf9a5b92018-08-15 16:01:53 -07001183 }
1184
1185 /**
1186 * Posts the specified command to be executed on the main thread,
1187 * waits for the request to complete, and returns the result.
1188 * @see #sendRequestAsync
1189 */
Nathan Harold92bed182018-10-12 18:16:49 -07001190 private Object sendRequest(int command, Object argument, int subId, WorkSource workSource) {
1191 return sendRequest(command, argument, subId, null, workSource);
1192 }
1193
1194 /**
1195 * Posts the specified command to be executed on the main thread,
1196 * waits for the request to complete, and returns the result.
1197 * @see #sendRequestAsync
1198 */
1199 private Object sendRequest(int command, Object argument, Phone phone, WorkSource workSource) {
1200 return sendRequest(
1201 command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phone, workSource);
1202 }
1203
1204 /**
1205 * Posts the specified command to be executed on the main thread,
1206 * waits for the request to complete, and returns the result.
1207 * @see #sendRequestAsync
1208 */
1209 private Object sendRequest(
1210 int command, Object argument, Integer subId, Phone phone, WorkSource workSource) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001211 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
1212 throw new RuntimeException("This method will deadlock if called from the main thread.");
1213 }
1214
Nathan Harold92bed182018-10-12 18:16:49 -07001215 MainThreadRequest request = null;
1216 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && phone != null) {
1217 throw new IllegalArgumentException("subId and phone cannot both be specified!");
1218 } else if (phone != null) {
1219 request = new MainThreadRequest(argument, phone, workSource);
1220 } else {
1221 request = new MainThreadRequest(argument, subId, workSource);
1222 }
1223
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001224 Message msg = mMainThreadHandler.obtainMessage(command, request);
1225 msg.sendToTarget();
1226
1227 // Wait for the request to complete
1228 synchronized (request) {
1229 while (request.result == null) {
1230 try {
1231 request.wait();
1232 } catch (InterruptedException e) {
1233 // Do nothing, go back and wait until the request is complete
1234 }
1235 }
1236 }
1237 return request.result;
1238 }
1239
1240 /**
1241 * Asynchronous ("fire and forget") version of sendRequest():
1242 * Posts the specified command to be executed on the main thread, and
1243 * returns immediately.
1244 * @see #sendRequest
1245 */
1246 private void sendRequestAsync(int command) {
1247 mMainThreadHandler.sendEmptyMessage(command);
1248 }
1249
1250 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001251 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001252 * @see {@link #sendRequest(int)}
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001253 */
1254 private void sendRequestAsync(int command, Object argument) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07001255 sendRequestAsync(command, argument, null, null);
1256 }
1257
1258 /**
1259 * Same as {@link #sendRequestAsync(int,Object)} except it takes a Phone and WorkSource.
1260 * @see {@link #sendRequest(int,Object)}
1261 */
1262 private void sendRequestAsync(
1263 int command, Object argument, Phone phone, WorkSource workSource) {
1264 MainThreadRequest request = new MainThreadRequest(argument, phone, workSource);
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001265 Message msg = mMainThreadHandler.obtainMessage(command, request);
1266 msg.sendToTarget();
1267 }
1268
1269 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001270 * Initialize the singleton PhoneInterfaceManager instance.
1271 * This is only done once, at startup, from PhoneApp.onCreate().
1272 */
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001273 /* package */ static PhoneInterfaceManager init(PhoneGlobals app) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001274 synchronized (PhoneInterfaceManager.class) {
1275 if (sInstance == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001276 sInstance = new PhoneInterfaceManager(app);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001277 } else {
1278 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
1279 }
1280 return sInstance;
1281 }
1282 }
1283
1284 /** Private constructor; @see init() */
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001285 private PhoneInterfaceManager(PhoneGlobals app) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001286 mApp = app;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001287 mCM = PhoneGlobals.getInstance().mCM;
Stuart Scott981d8582015-04-21 14:09:50 -07001288 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001289 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
1290 mMainThreadHandler = new MainThreadHandler();
Tobias Thiererb19e1f12018-12-11 17:54:03 +00001291 mSubscriptionController = SubscriptionController.getInstance();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001292 mTelephonySharedPreferences =
1293 PreferenceManager.getDefaultSharedPreferences(mApp);
yinxub1bed742017-04-17 11:45:04 -07001294 mNetworkScanRequestTracker = new NetworkScanRequestTracker();
Malcolm Chen2c63d402018-08-14 16:00:53 -07001295 mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
Wink Saville3ab207e2014-11-20 13:07:20 -08001296
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001297 publish();
1298 }
1299
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001300 private Phone getDefaultPhone() {
1301 Phone thePhone = getPhone(getDefaultSubscription());
1302 return (thePhone != null) ? thePhone : PhoneFactory.getDefaultPhone();
1303 }
1304
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001305 private void publish() {
1306 if (DBG) log("publish: " + this);
1307
1308 ServiceManager.addService("phone", this);
1309 }
1310
Stuart Scott584921c2015-01-15 17:10:34 -08001311 private Phone getPhoneFromRequest(MainThreadRequest request) {
Jordan Liu4c733742019-02-28 12:03:40 -08001312 if (request.phone != null) {
1313 return request.phone;
1314 } else {
1315 return getPhoneFromSubId(request.subId);
1316 }
1317 }
1318
1319 private Phone getPhoneFromSubId(int subId) {
1320 return (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
1321 ? getDefaultPhone() : getPhone(subId);
Stuart Scott584921c2015-01-15 17:10:34 -08001322 }
1323
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001324 private UiccCard getUiccCardFromRequest(MainThreadRequest request) {
1325 Phone phone = getPhoneFromRequest(request);
1326 return phone == null ? null :
1327 UiccController.getInstance().getUiccCard(phone.getPhoneId());
1328 }
1329
Wink Saville36469e72014-06-11 15:17:00 -07001330 // returns phone associated with the subId.
Wink Savilleb564aae2014-10-23 10:18:09 -07001331 private Phone getPhone(int subId) {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001332 return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -07001333 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001334
1335 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001336 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -07001337 }
1338
Wink Savilleb564aae2014-10-23 10:18:09 -07001339 public void dialForSubscriber(int subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001340 if (DBG) log("dial: " + number);
1341 // No permission check needed here: This is just a wrapper around the
1342 // ACTION_DIAL intent, which is available to any app since it puts up
1343 // the UI before it does anything.
1344
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001345 final long identity = Binder.clearCallingIdentity();
1346 try {
1347 String url = createTelUrl(number);
1348 if (url == null) {
1349 return;
1350 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001351
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001352 // PENDING: should we just silently fail if phone is offhook or ringing?
1353 PhoneConstants.State state = mCM.getState(subId);
1354 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
1355 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
1356 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1357 mApp.startActivity(intent);
1358 }
1359 } finally {
1360 Binder.restoreCallingIdentity(identity);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001361 }
1362 }
1363
1364 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001365 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -07001366 }
1367
Wink Savilleb564aae2014-10-23 10:18:09 -07001368 public void callForSubscriber(int subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001369 if (DBG) log("call: " + number);
1370
1371 // This is just a wrapper around the ACTION_CALL intent, but we still
1372 // need to do a permission check since we're calling startActivity()
1373 // from the context of the phone app.
1374 enforceCallPermission();
1375
1376 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
1377 != AppOpsManager.MODE_ALLOWED) {
1378 return;
1379 }
1380
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001381 final long identity = Binder.clearCallingIdentity();
1382 try {
1383 String url = createTelUrl(number);
1384 if (url == null) {
1385 return;
1386 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001387
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001388 boolean isValid = false;
1389 final List<SubscriptionInfo> slist = getActiveSubscriptionInfoListPrivileged();
1390 if (slist != null) {
1391 for (SubscriptionInfo subInfoRecord : slist) {
1392 if (subInfoRecord.getSubscriptionId() == subId) {
1393 isValid = true;
1394 break;
1395 }
Wink Saville3ab207e2014-11-20 13:07:20 -08001396 }
Wink Saville08874612014-08-31 19:19:58 -07001397 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001398 if (!isValid) {
1399 return;
1400 }
Wink Saville08874612014-08-31 19:19:58 -07001401
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001402 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
1403 intent.putExtra(SUBSCRIPTION_KEY, subId);
1404 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1405 mApp.startActivity(intent);
1406 } finally {
1407 Binder.restoreCallingIdentity(identity);
1408 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001409 }
1410
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001411 public boolean supplyPin(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001412 return supplyPinForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -07001413 }
1414
Wink Savilleb564aae2014-10-23 10:18:09 -07001415 public boolean supplyPinForSubscriber(int subId, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001416 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07001417 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1418 }
1419
1420 public boolean supplyPuk(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001421 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -07001422 }
1423
Wink Savilleb564aae2014-10-23 10:18:09 -07001424 public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001425 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07001426 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1427 }
1428
1429 /** {@hide} */
1430 public int[] supplyPinReportResult(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001431 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -07001432 }
1433
Wink Savilleb564aae2014-10-23 10:18:09 -07001434 public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001435 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001436
1437 final long identity = Binder.clearCallingIdentity();
1438 try {
1439 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
1440 checkSimPin.start();
1441 return checkSimPin.unlockSim(null, pin);
1442 } finally {
1443 Binder.restoreCallingIdentity(identity);
1444 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001445 }
1446
Wink Saville9de0f752013-10-22 19:04:03 -07001447 /** {@hide} */
1448 public int[] supplyPukReportResult(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001449 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -07001450 }
1451
Wink Savilleb564aae2014-10-23 10:18:09 -07001452 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001453 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001454
1455 final long identity = Binder.clearCallingIdentity();
1456 try {
1457 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
1458 checkSimPuk.start();
1459 return checkSimPuk.unlockSim(puk, pin);
1460 } finally {
1461 Binder.restoreCallingIdentity(identity);
1462 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001463 }
1464
1465 /**
Wink Saville9de0f752013-10-22 19:04:03 -07001466 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001467 * a synchronous one.
1468 */
1469 private static class UnlockSim extends Thread {
1470
1471 private final IccCard mSimCard;
1472
1473 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -07001474 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1475 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001476
1477 // For replies from SimCard interface
1478 private Handler mHandler;
1479
1480 // For async handler to identify request type
1481 private static final int SUPPLY_PIN_COMPLETE = 100;
1482
1483 public UnlockSim(IccCard simCard) {
1484 mSimCard = simCard;
1485 }
1486
1487 @Override
1488 public void run() {
1489 Looper.prepare();
1490 synchronized (UnlockSim.this) {
1491 mHandler = new Handler() {
1492 @Override
1493 public void handleMessage(Message msg) {
1494 AsyncResult ar = (AsyncResult) msg.obj;
1495 switch (msg.what) {
1496 case SUPPLY_PIN_COMPLETE:
1497 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
1498 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -07001499 mRetryCount = msg.arg1;
1500 if (ar.exception != null) {
1501 if (ar.exception instanceof CommandException &&
1502 ((CommandException)(ar.exception)).getCommandError()
1503 == CommandException.Error.PASSWORD_INCORRECT) {
1504 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1505 } else {
1506 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1507 }
1508 } else {
1509 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1510 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001511 mDone = true;
1512 UnlockSim.this.notifyAll();
1513 }
1514 break;
1515 }
1516 }
1517 };
1518 UnlockSim.this.notifyAll();
1519 }
1520 Looper.loop();
1521 }
1522
1523 /*
1524 * Use PIN or PUK to unlock SIM card
1525 *
1526 * If PUK is null, unlock SIM card with PIN
1527 *
1528 * If PUK is not null, unlock SIM card with PUK and set PIN code
1529 */
Wink Saville9de0f752013-10-22 19:04:03 -07001530 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001531
1532 while (mHandler == null) {
1533 try {
1534 wait();
1535 } catch (InterruptedException e) {
1536 Thread.currentThread().interrupt();
1537 }
1538 }
1539 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1540
1541 if (puk == null) {
1542 mSimCard.supplyPin(pin, callback);
1543 } else {
1544 mSimCard.supplyPuk(puk, pin, callback);
1545 }
1546
1547 while (!mDone) {
1548 try {
1549 Log.d(LOG_TAG, "wait for done");
1550 wait();
1551 } catch (InterruptedException e) {
1552 // Restore the interrupted status
1553 Thread.currentThread().interrupt();
1554 }
1555 }
1556 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001557 int[] resultArray = new int[2];
1558 resultArray[0] = mResult;
1559 resultArray[1] = mRetryCount;
1560 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001561 }
1562 }
1563
1564 public void updateServiceLocation() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001565 updateServiceLocationForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001566
1567 }
1568
Wink Savilleb564aae2014-10-23 10:18:09 -07001569 public void updateServiceLocationForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001570 // No permission check needed here: this call is harmless, and it's
1571 // needed for the ServiceState.requestStateUpdate() call (which is
1572 // already intentionally exposed to 3rd parties.)
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001573 final long identity = Binder.clearCallingIdentity();
1574 try {
1575 final Phone phone = getPhone(subId);
1576 if (phone != null) {
1577 phone.updateServiceLocation();
1578 }
1579 } finally {
1580 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001581 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001582 }
1583
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001584 @Override
1585 public boolean isRadioOn(String callingPackage) {
1586 return isRadioOnForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001587 }
1588
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001589 @Override
1590 public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08001591 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08001592 mApp, subId, callingPackage, "isRadioOnForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001593 return false;
1594 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001595
1596 final long identity = Binder.clearCallingIdentity();
1597 try {
1598 return isRadioOnForSubscriber(subId);
1599 } finally {
1600 Binder.restoreCallingIdentity(identity);
1601 }
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001602 }
1603
1604 private boolean isRadioOnForSubscriber(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001605 final long identity = Binder.clearCallingIdentity();
1606 try {
1607 final Phone phone = getPhone(subId);
1608 if (phone != null) {
1609 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1610 } else {
1611 return false;
1612 }
1613 } finally {
1614 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001615 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001616 }
1617
1618 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001619 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001620 }
Wink Saville36469e72014-06-11 15:17:00 -07001621
Wink Savilleb564aae2014-10-23 10:18:09 -07001622 public void toggleRadioOnOffForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001623 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001624
1625 final long identity = Binder.clearCallingIdentity();
1626 try {
1627 final Phone phone = getPhone(subId);
1628 if (phone != null) {
1629 phone.setRadioPower(!isRadioOnForSubscriber(subId));
1630 }
1631 } finally {
1632 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001633 }
Wink Saville36469e72014-06-11 15:17:00 -07001634 }
1635
1636 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001637 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001638 }
1639
Wink Savilleb564aae2014-10-23 10:18:09 -07001640 public boolean setRadioForSubscriber(int subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001641 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001642
1643 final long identity = Binder.clearCallingIdentity();
1644 try {
1645 final Phone phone = getPhone(subId);
1646 if (phone == null) {
1647 return false;
1648 }
1649 if ((phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF) != turnOn) {
1650 toggleRadioOnOffForSubscriber(subId);
1651 }
1652 return true;
1653 } finally {
1654 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001655 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001656 }
Wink Saville36469e72014-06-11 15:17:00 -07001657
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001658 public boolean needMobileRadioShutdown() {
1659 /*
1660 * If any of the Radios are available, it will need to be
1661 * shutdown. So return true if any Radio is available.
1662 */
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001663 final long identity = Binder.clearCallingIdentity();
1664 try {
1665 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1666 Phone phone = PhoneFactory.getPhone(i);
1667 if (phone != null && phone.isRadioAvailable()) return true;
1668 }
1669 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1670 return false;
1671 } finally {
1672 Binder.restoreCallingIdentity(identity);
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001673 }
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001674 }
1675
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001676 @Override
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001677 public void shutdownMobileRadios() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001678 enforceModifyPermission();
1679
1680 final long identity = Binder.clearCallingIdentity();
1681 try {
1682 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1683 logv("Shutting down Phone " + i);
1684 shutdownRadioUsingPhoneId(i);
1685 }
1686 } finally {
1687 Binder.restoreCallingIdentity(identity);
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001688 }
1689 }
1690
1691 private void shutdownRadioUsingPhoneId(int phoneId) {
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001692 Phone phone = PhoneFactory.getPhone(phoneId);
1693 if (phone != null && phone.isRadioAvailable()) {
1694 phone.shutdownRadio();
1695 }
1696 }
1697
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001698 public boolean setRadioPower(boolean turnOn) {
Jack Yub4e16162017-05-15 12:48:40 -07001699 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001700
1701 final long identity = Binder.clearCallingIdentity();
1702 try {
1703 final Phone defaultPhone = PhoneFactory.getDefaultPhone();
1704 if (defaultPhone != null) {
1705 defaultPhone.setRadioPower(turnOn);
1706 return true;
1707 } else {
1708 loge("There's no default phone.");
1709 return false;
1710 }
1711 } finally {
1712 Binder.restoreCallingIdentity(identity);
Wei Liu9ae2a062016-08-08 11:09:34 -07001713 }
Wink Saville36469e72014-06-11 15:17:00 -07001714 }
1715
Wink Savilleb564aae2014-10-23 10:18:09 -07001716 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001717 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001718
1719 final long identity = Binder.clearCallingIdentity();
1720 try {
1721 final Phone phone = getPhone(subId);
1722 if (phone != null) {
1723 phone.setRadioPower(turnOn);
1724 return true;
1725 } else {
1726 return false;
1727 }
1728 } finally {
1729 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001730 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001731 }
1732
Wink Saville36469e72014-06-11 15:17:00 -07001733 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001734 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001735 public boolean enableDataConnectivity() {
1736 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001737
1738 final long identity = Binder.clearCallingIdentity();
1739 try {
1740 int subId = mSubscriptionController.getDefaultDataSubId();
1741 final Phone phone = getPhone(subId);
1742 if (phone != null) {
Jack Yud79fba22018-12-13 11:51:28 -08001743 phone.getDataEnabledSettings().setUserDataEnabled(true);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001744 return true;
1745 } else {
1746 return false;
1747 }
1748 } finally {
1749 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001750 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001751 }
1752
Wink Saville36469e72014-06-11 15:17:00 -07001753 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001754 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001755 public boolean disableDataConnectivity() {
1756 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001757
1758 final long identity = Binder.clearCallingIdentity();
1759 try {
1760 int subId = mSubscriptionController.getDefaultDataSubId();
1761 final Phone phone = getPhone(subId);
1762 if (phone != null) {
Jack Yud79fba22018-12-13 11:51:28 -08001763 phone.getDataEnabledSettings().setUserDataEnabled(false);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001764 return true;
1765 } else {
1766 return false;
1767 }
1768 } finally {
1769 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001770 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001771 }
1772
Sanket Padawe356d7632015-06-22 14:03:32 -07001773 @Override
Jack Yuacf8a132017-05-01 17:00:48 -07001774 public boolean isDataConnectivityPossible(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001775 final long identity = Binder.clearCallingIdentity();
1776 try {
1777 final Phone phone = getPhone(subId);
1778 if (phone != null) {
Jack Yub5d8f642018-11-26 11:20:48 -08001779 return phone.isDataAllowed(ApnSetting.TYPE_DEFAULT);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001780 } else {
1781 return false;
1782 }
1783 } finally {
1784 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001785 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001786 }
1787
1788 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001789 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07001790 }
1791
pkanwarae03a6b2016-11-06 20:37:09 -08001792 public void handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001793 enforceCallPermission();
1794
1795 final long identity = Binder.clearCallingIdentity();
1796 try {
1797 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1798 return;
1799 }
1800 Pair<String, ResultReceiver> ussdObject = new Pair(ussdRequest, wrappedCallback);
1801 sendRequest(CMD_HANDLE_USSD_REQUEST, ussdObject, subId);
1802 } finally {
1803 Binder.restoreCallingIdentity(identity);
1804 }
pkanwar32d516d2016-10-14 19:37:38 -07001805 };
1806
Wink Savilleb564aae2014-10-23 10:18:09 -07001807 public boolean handlePinMmiForSubscriber(int subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001808 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001809
1810 final long identity = Binder.clearCallingIdentity();
1811 try {
1812 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1813 return false;
1814 }
1815 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
1816 } finally {
1817 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001818 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001819 }
1820
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001821 public int getCallState() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001822 return getCallStateForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001823 }
1824
Sanket Padawe13bac7b2017-03-20 15:04:47 -07001825 public int getCallStateForSlot(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001826 final long identity = Binder.clearCallingIdentity();
1827 try {
1828 Phone phone = PhoneFactory.getPhone(slotIndex);
1829 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
1830 PhoneConstantConversions.convertCallState(phone.getState());
1831 } finally {
1832 Binder.restoreCallingIdentity(identity);
1833 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001834 }
1835
Sanket Padawe356d7632015-06-22 14:03:32 -07001836 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001837 public int getDataState() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001838 final long identity = Binder.clearCallingIdentity();
1839 try {
1840 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1841 if (phone != null) {
1842 return PhoneConstantConversions.convertDataState(phone.getDataConnectionState());
1843 } else {
1844 return PhoneConstantConversions.convertDataState(
1845 PhoneConstants.DataState.DISCONNECTED);
1846 }
1847 } finally {
1848 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001849 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001850 }
1851
Sanket Padawe356d7632015-06-22 14:03:32 -07001852 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001853 public int getDataActivity() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001854 final long identity = Binder.clearCallingIdentity();
1855 try {
1856 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1857 if (phone != null) {
1858 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
1859 } else {
1860 return TelephonyManager.DATA_ACTIVITY_NONE;
1861 }
1862 } finally {
1863 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001864 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001865 }
1866
1867 @Override
Svetoslav64fad262015-04-14 14:35:21 -07001868 public Bundle getCellLocation(String callingPackage) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001869 mApp.getSystemService(AppOpsManager.class)
Hall Liu1aa510f2017-11-22 17:40:08 -08001870 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08001871
1872 LocationAccessPolicy.LocationPermissionResult locationResult =
1873 LocationAccessPolicy.checkLocationPermission(mApp,
1874 new LocationAccessPolicy.LocationPermissionQuery.Builder()
1875 .setCallingPackage(callingPackage)
1876 .setCallingPid(Binder.getCallingPid())
1877 .setCallingUid(Binder.getCallingUid())
1878 .setMethod("getCellLocation")
1879 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
1880 .build());
1881 switch (locationResult) {
1882 case DENIED_HARD:
1883 throw new SecurityException("Not allowed to access cell location");
1884 case DENIED_SOFT:
1885 return new Bundle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001886 }
1887
Narayan Kamathf04b5a12018-01-09 11:47:15 +00001888 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001889 final long identity = Binder.clearCallingIdentity();
1890 try {
1891 if (DBG_LOC) log("getCellLocation: is active user");
1892 Bundle data = new Bundle();
Nathan Harold3ff88932018-08-14 10:19:49 -07001893 int subId = mSubscriptionController.getDefaultDataSubId();
1894 CellLocation cl = (CellLocation) sendRequest(CMD_GET_CELL_LOCATION, workSource, subId);
1895 cl.fillInNotifierBundle(data);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001896 return data;
1897 } finally {
1898 Binder.restoreCallingIdentity(identity);
1899 }
Svetoslav64fad262015-04-14 14:35:21 -07001900 }
1901
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001902 @Override
Jonathan Basseribf5362b2017-07-19 12:22:35 -07001903 public String getNetworkCountryIsoForPhone(int phoneId) {
1904 // Reporting the correct network country is ambiguous when IWLAN could conflict with
1905 // registered cell info, so return a NULL country instead.
1906 final long identity = Binder.clearCallingIdentity();
1907 try {
Malcolm Chen3732c2b2018-07-18 20:15:24 -07001908 if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
1909 // Get default phone in this case.
1910 phoneId = SubscriptionManager.DEFAULT_PHONE_INDEX;
1911 }
Jonathan Basseribf5362b2017-07-19 12:22:35 -07001912 final int subId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
Jack Yu5f7092c2018-04-13 14:05:37 -07001913 // Todo: fix this when we can get the actual cellular network info when the device
1914 // is on IWLAN.
Jonathan Basseribf5362b2017-07-19 12:22:35 -07001915 if (TelephonyManager.NETWORK_TYPE_IWLAN
1916 == getVoiceNetworkTypeForSubscriber(subId, mApp.getPackageName())) {
1917 return "";
1918 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001919 Phone phone = PhoneFactory.getPhone(phoneId);
1920 if (phone != null) {
1921 ServiceStateTracker sst = phone.getServiceStateTracker();
1922 if (sst != null) {
1923 LocaleTracker lt = sst.getLocaleTracker();
1924 if (lt != null) {
1925 return lt.getCurrentCountry();
1926 }
1927 }
1928 }
1929 return "";
Jonathan Basseribf5362b2017-07-19 12:22:35 -07001930 } finally {
1931 Binder.restoreCallingIdentity(identity);
1932 }
Jonathan Basseribf5362b2017-07-19 12:22:35 -07001933 }
1934
1935 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001936 public void enableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001937 enableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001938 }
1939
Sanket Padawe356d7632015-06-22 14:03:32 -07001940 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001941 public void enableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001942 mApp.enforceCallingOrSelfPermission(
1943 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001944
1945 final long identity = Binder.clearCallingIdentity();
1946 try {
1947 final Phone phone = getPhone(subId);
1948 if (phone != null) {
1949 phone.enableLocationUpdates();
1950 }
1951 } finally {
1952 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001953 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001954 }
1955
1956 @Override
1957 public void disableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001958 disableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001959 }
1960
Sanket Padawe356d7632015-06-22 14:03:32 -07001961 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001962 public void disableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001963 mApp.enforceCallingOrSelfPermission(
1964 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08001965
1966 final long identity = Binder.clearCallingIdentity();
1967 try {
1968 final Phone phone = getPhone(subId);
1969 if (phone != null) {
1970 phone.disableLocationUpdates();
1971 }
1972 } finally {
1973 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07001974 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001975 }
1976
Nathan Harold31d7ff32018-10-15 20:20:30 -07001977 /**
1978 * Returns the target SDK version number for a given package name.
1979 *
1980 * @return target SDK if the package is found or INT_MAX.
1981 */
1982 private int getTargetSdk(String packageName) {
1983 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001984 final ApplicationInfo ai = mApp.getPackageManager().getApplicationInfo(
1985 packageName, 0);
Nathan Harold31d7ff32018-10-15 20:20:30 -07001986 if (ai != null) return ai.targetSdkVersion;
1987 } catch (PackageManager.NameNotFoundException unexpected) {
1988 }
1989 return Integer.MAX_VALUE;
1990 }
1991
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001992 @Override
1993 @SuppressWarnings("unchecked")
Nathan Harold31d7ff32018-10-15 20:20:30 -07001994 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1995 final int targetSdk = getTargetSdk(callingPackage);
Nathan Harolddbea45a2018-08-30 14:35:07 -07001996 if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
1997 throw new SecurityException(
1998 "getNeighboringCellInfo() is unavailable to callers targeting Q+ SDK levels.");
1999 }
Nathan Haroldb4d55612018-07-20 13:13:08 -07002000
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002001 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
2002 callingPackage) != AppOpsManager.MODE_ALLOWED) {
2003 return null;
2004 }
Svetoslav64fad262015-04-14 14:35:21 -07002005
Svetoslav Ganov4a9d4482017-06-20 19:53:35 -07002006 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002007
Nathan Haroldf180aac2018-06-01 18:43:55 -07002008 List<CellInfo> info = getAllCellInfo(callingPackage);
2009 if (info == null) return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002010
Nathan Haroldf180aac2018-06-01 18:43:55 -07002011 List<NeighboringCellInfo> neighbors = new ArrayList<NeighboringCellInfo>();
2012 for (CellInfo ci : info) {
2013 if (ci instanceof CellInfoGsm) {
2014 neighbors.add(new NeighboringCellInfo((CellInfoGsm) ci));
2015 } else if (ci instanceof CellInfoWcdma) {
2016 neighbors.add(new NeighboringCellInfo((CellInfoWcdma) ci));
2017 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002018 }
Nathan Haroldf180aac2018-06-01 18:43:55 -07002019 return (neighbors.size()) > 0 ? neighbors : null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002020 }
2021
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002022 private List<CellInfo> getCachedCellInfo() {
2023 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
2024 for (Phone phone : PhoneFactory.getPhones()) {
2025 List<CellInfo> info = phone.getAllCellInfo();
2026 if (info != null) cellInfos.addAll(info);
2027 }
2028 return cellInfos;
2029 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002030
2031 @Override
Svetoslav64fad262015-04-14 14:35:21 -07002032 public List<CellInfo> getAllCellInfo(String callingPackage) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002033 mApp.getSystemService(AppOpsManager.class)
Hall Liu1aa510f2017-11-22 17:40:08 -08002034 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08002035
2036 LocationAccessPolicy.LocationPermissionResult locationResult =
2037 LocationAccessPolicy.checkLocationPermission(mApp,
2038 new LocationAccessPolicy.LocationPermissionQuery.Builder()
2039 .setCallingPackage(callingPackage)
2040 .setCallingPid(Binder.getCallingPid())
2041 .setCallingUid(Binder.getCallingUid())
2042 .setMethod("getAllCellInfo")
Nathan Harold5ae50b52019-02-20 15:46:36 -08002043 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08002044 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
2045 .build());
2046 switch (locationResult) {
2047 case DENIED_HARD:
2048 throw new SecurityException("Not allowed to access cell info");
2049 case DENIED_SOFT:
2050 return new ArrayList<>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002051 }
2052
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002053 final int targetSdk = getTargetSdk(callingPackage);
2054 if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
2055 return getCachedCellInfo();
2056 }
2057
Svetoslav Ganov4a9d4482017-06-20 19:53:35 -07002058 if (DBG_LOC) log("getAllCellInfo: is active user");
Narayan Kamathf04b5a12018-01-09 11:47:15 +00002059 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002060 final long identity = Binder.clearCallingIdentity();
2061 try {
2062 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
2063 for (Phone phone : PhoneFactory.getPhones()) {
Nathan Harold3ff88932018-08-14 10:19:49 -07002064 final List<CellInfo> info = (List<CellInfo>) sendRequest(
Nathan Harold92bed182018-10-12 18:16:49 -07002065 CMD_GET_ALL_CELL_INFO, null, phone, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002066 if (info != null) cellInfos.addAll(info);
2067 }
2068 return cellInfos;
2069 } finally {
2070 Binder.restoreCallingIdentity(identity);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002071 }
2072 }
2073
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07002074 @Override
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002075 public void requestCellInfoUpdate(int subId, ICellInfoCallback cb, String callingPackage) {
2076 requestCellInfoUpdateInternal(
2077 subId, cb, callingPackage, getWorkSource(Binder.getCallingUid()));
2078 }
2079
2080 @Override
2081 public void requestCellInfoUpdateWithWorkSource(
2082 int subId, ICellInfoCallback cb, String callingPackage, WorkSource workSource) {
2083 enforceModifyPermission();
2084 requestCellInfoUpdateInternal(subId, cb, callingPackage, workSource);
2085 }
2086
2087 private void requestCellInfoUpdateInternal(
2088 int subId, ICellInfoCallback cb, String callingPackage, WorkSource workSource) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002089 mApp.getSystemService(AppOpsManager.class)
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002090 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08002091
2092 LocationAccessPolicy.LocationPermissionResult locationResult =
2093 LocationAccessPolicy.checkLocationPermission(mApp,
2094 new LocationAccessPolicy.LocationPermissionQuery.Builder()
2095 .setCallingPackage(callingPackage)
2096 .setCallingPid(Binder.getCallingPid())
2097 .setCallingUid(Binder.getCallingUid())
2098 .setMethod("requestCellInfoUpdate")
2099 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
2100 .build());
2101 switch (locationResult) {
2102 case DENIED_HARD:
2103 throw new SecurityException("Not allowed to access cell info");
2104 case DENIED_SOFT:
2105 return;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002106 }
2107
2108 final Phone phone = getPhone(subId);
2109 if (phone == null) throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
2110
2111 sendRequestAsync(CMD_REQUEST_CELL_INFO_UPDATE, cb, phone, workSource);
2112 }
2113
2114 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002115 public void setCellInfoListRate(int rateInMillis) {
Jack Yua8d8cb82017-01-16 10:15:34 -08002116 enforceModifyPermission();
Narayan Kamathf04b5a12018-01-09 11:47:15 +00002117 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002118
2119 final long identity = Binder.clearCallingIdentity();
2120 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002121 getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002122 } finally {
2123 Binder.restoreCallingIdentity(identity);
2124 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002125 }
2126
Shishir Agrawala9f32182016-04-12 12:00:16 -07002127 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07002128 public String getImeiForSlot(int slotIndex, String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08002129 Phone phone = PhoneFactory.getPhone(slotIndex);
2130 if (phone == null) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002131 return null;
2132 }
Jeff Davidson913390f2018-02-23 17:11:49 -08002133 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07002134 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
2135 callingPackage, "getImeiForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08002136 return null;
2137 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002138
2139 final long identity = Binder.clearCallingIdentity();
2140 try {
2141 return phone.getImei();
2142 } finally {
2143 Binder.restoreCallingIdentity(identity);
2144 }
Shishir Agrawala9f32182016-04-12 12:00:16 -07002145 }
2146
2147 @Override
David Kelly5e06a7f2018-03-12 14:10:59 +00002148 public String getTypeAllocationCodeForSlot(int slotIndex) {
2149 Phone phone = PhoneFactory.getPhone(slotIndex);
2150 String tac = null;
2151 if (phone != null) {
2152 String imei = phone.getImei();
2153 tac = imei == null ? null : imei.substring(0, TYPE_ALLOCATION_CODE_LENGTH);
2154 }
2155 return tac;
2156 }
2157
2158 @Override
Jack Yu2af8d712017-03-15 17:14:14 -07002159 public String getMeidForSlot(int slotIndex, String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08002160 Phone phone = PhoneFactory.getPhone(slotIndex);
2161 if (phone == null) {
Jack Yu2af8d712017-03-15 17:14:14 -07002162 return null;
2163 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002164
Jeff Davidson913390f2018-02-23 17:11:49 -08002165 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07002166 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
2167 callingPackage, "getMeidForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08002168 return null;
2169 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002170
2171 final long identity = Binder.clearCallingIdentity();
2172 try {
2173 return phone.getMeid();
2174 } finally {
2175 Binder.restoreCallingIdentity(identity);
2176 }
Jack Yu2af8d712017-03-15 17:14:14 -07002177 }
2178
2179 @Override
David Kelly5e06a7f2018-03-12 14:10:59 +00002180 public String getManufacturerCodeForSlot(int slotIndex) {
2181 Phone phone = PhoneFactory.getPhone(slotIndex);
2182 String manufacturerCode = null;
2183 if (phone != null) {
2184 String meid = phone.getMeid();
2185 manufacturerCode = meid == null ? null : meid.substring(0, MANUFACTURER_CODE_LENGTH);
2186 }
2187 return manufacturerCode;
2188 }
2189
2190 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07002191 public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08002192 Phone phone = PhoneFactory.getPhone(slotIndex);
2193 if (phone == null) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002194 return null;
2195 }
Jeff Davidson913390f2018-02-23 17:11:49 -08002196 int subId = phone.getSubId();
2197 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2198 mApp, subId, callingPackage, "getDeviceSoftwareVersionForSlot")) {
2199 return null;
2200 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002201
2202 final long identity = Binder.clearCallingIdentity();
2203 try {
2204 return phone.getDeviceSvn();
2205 } finally {
2206 Binder.restoreCallingIdentity(identity);
2207 }
Shishir Agrawala9f32182016-04-12 12:00:16 -07002208 }
2209
fionaxu43304da2017-11-27 22:51:16 -08002210 @Override
2211 public int getSubscriptionCarrierId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002212 final long identity = Binder.clearCallingIdentity();
2213 try {
2214 final Phone phone = getPhone(subId);
2215 return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID : phone.getCarrierId();
2216 } finally {
2217 Binder.restoreCallingIdentity(identity);
2218 }
fionaxu43304da2017-11-27 22:51:16 -08002219 }
2220
2221 @Override
2222 public String getSubscriptionCarrierName(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002223 final long identity = Binder.clearCallingIdentity();
2224 try {
2225 final Phone phone = getPhone(subId);
2226 return phone == null ? null : phone.getCarrierName();
2227 } finally {
2228 Binder.restoreCallingIdentity(identity);
2229 }
fionaxu43304da2017-11-27 22:51:16 -08002230 }
2231
calvinpanffe225e2018-11-01 19:43:06 +08002232 @Override
chen xu0026ca62019-03-06 15:28:50 -08002233 public int getSubscriptionSpecificCarrierId(int subId) {
chen xu25637222018-11-04 17:17:00 -08002234 final long identity = Binder.clearCallingIdentity();
2235 try {
2236 final Phone phone = getPhone(subId);
2237 return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID
chen xu0026ca62019-03-06 15:28:50 -08002238 : phone.getSpecificCarrierId();
chen xu25637222018-11-04 17:17:00 -08002239 } finally {
2240 Binder.restoreCallingIdentity(identity);
2241 }
2242 }
2243
2244 @Override
chen xu0026ca62019-03-06 15:28:50 -08002245 public String getSubscriptionSpecificCarrierName(int subId) {
chen xu25637222018-11-04 17:17:00 -08002246 final long identity = Binder.clearCallingIdentity();
2247 try {
2248 final Phone phone = getPhone(subId);
chen xu0026ca62019-03-06 15:28:50 -08002249 return phone == null ? null : phone.getSpecificCarrierName();
chen xu25637222018-11-04 17:17:00 -08002250 } finally {
2251 Binder.restoreCallingIdentity(identity);
2252 }
2253 }
2254
chen xu651eec72018-11-11 19:03:44 -08002255 @Override
chen xu864e11c2018-12-06 22:10:03 -08002256 public int getCarrierIdFromMccMnc(int slotIndex, String mccmnc, boolean isSubscriptionMccMnc) {
2257 if (!isSubscriptionMccMnc) {
2258 enforceReadPrivilegedPermission("getCarrierIdFromMccMnc");
2259 }
chen xu651eec72018-11-11 19:03:44 -08002260 final Phone phone = PhoneFactory.getPhone(slotIndex);
2261 if (phone == null) {
2262 return TelephonyManager.UNKNOWN_CARRIER_ID;
2263 }
2264 final long identity = Binder.clearCallingIdentity();
2265 try {
2266 return CarrierResolver.getCarrierIdFromMccMnc(phone.getContext(), mccmnc);
2267 } finally {
2268 Binder.restoreCallingIdentity(identity);
2269 }
2270 }
2271
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002272 //
2273 // Internal helper methods.
2274 //
2275
Sanket Padaweee13a9b2016-03-08 17:30:28 -08002276 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002277 * Make sure the caller has the MODIFY_PHONE_STATE permission.
2278 *
2279 * @throws SecurityException if the caller does not have the required permission
2280 */
2281 private void enforceModifyPermission() {
2282 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
2283 }
2284
2285 /**
2286 * Make sure the caller has the CALL_PHONE permission.
2287 *
2288 * @throws SecurityException if the caller does not have the required permission
2289 */
2290 private void enforceCallPermission() {
2291 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
2292 }
2293
Stuart Scott8eef64f2015-04-08 15:13:54 -07002294 private void enforceConnectivityInternalPermission() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002295 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL,
Stuart Scott8eef64f2015-04-08 15:13:54 -07002296 "ConnectivityService");
2297 }
2298
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002299 private String createTelUrl(String number) {
2300 if (TextUtils.isEmpty(number)) {
2301 return null;
2302 }
2303
Jake Hambye994d462014-02-03 13:10:13 -08002304 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002305 }
2306
Ihab Awadf9e92732013-12-05 18:02:52 -08002307 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002308 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
2309 }
2310
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07002311 private static void logv(String msg) {
2312 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
2313 }
2314
Ihab Awadf9e92732013-12-05 18:02:52 -08002315 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002316 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
2317 }
2318
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002319 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002320 public int getActivePhoneType() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07002321 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07002322 }
2323
Sanket Padawe356d7632015-06-22 14:03:32 -07002324 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07002325 public int getActivePhoneTypeForSlot(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002326 final long identity = Binder.clearCallingIdentity();
2327 try {
2328 final Phone phone = PhoneFactory.getPhone(slotIndex);
2329 if (phone == null) {
2330 return PhoneConstants.PHONE_TYPE_NONE;
2331 } else {
2332 return phone.getPhoneType();
2333 }
2334 } finally {
2335 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07002336 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002337 }
2338
2339 /**
2340 * Returns the CDMA ERI icon index to display
2341 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002342 @Override
2343 public int getCdmaEriIconIndex(String callingPackage) {
2344 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002345 }
2346
Sanket Padawe356d7632015-06-22 14:03:32 -07002347 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002348 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002349 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08002350 mApp, subId, callingPackage, "getCdmaEriIconIndexForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002351 return -1;
2352 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002353
2354 final long identity = Binder.clearCallingIdentity();
2355 try {
2356 final Phone phone = getPhone(subId);
2357 if (phone != null) {
2358 return phone.getCdmaEriIconIndex();
2359 } else {
2360 return -1;
2361 }
2362 } finally {
2363 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07002364 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002365 }
2366
2367 /**
2368 * Returns the CDMA ERI icon mode,
2369 * 0 - ON
2370 * 1 - FLASHING
2371 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002372 @Override
2373 public int getCdmaEriIconMode(String callingPackage) {
2374 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002375 }
2376
Sanket Padawe356d7632015-06-22 14:03:32 -07002377 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002378 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002379 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08002380 mApp, subId, callingPackage, "getCdmaEriIconModeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002381 return -1;
2382 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002383
2384 final long identity = Binder.clearCallingIdentity();
2385 try {
2386 final Phone phone = getPhone(subId);
2387 if (phone != null) {
2388 return phone.getCdmaEriIconMode();
2389 } else {
2390 return -1;
2391 }
2392 } finally {
2393 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07002394 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002395 }
2396
2397 /**
2398 * Returns the CDMA ERI text,
2399 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002400 @Override
2401 public String getCdmaEriText(String callingPackage) {
2402 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002403 }
2404
Sanket Padawe356d7632015-06-22 14:03:32 -07002405 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002406 public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002407 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08002408 mApp, subId, callingPackage, "getCdmaEriIconTextForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002409 return null;
2410 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002411
2412 final long identity = Binder.clearCallingIdentity();
2413 try {
2414 final Phone phone = getPhone(subId);
2415 if (phone != null) {
2416 return phone.getCdmaEriText();
2417 } else {
2418 return null;
2419 }
2420 } finally {
2421 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07002422 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002423 }
2424
2425 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07002426 * Returns the CDMA MDN.
2427 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002428 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002429 public String getCdmaMdn(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002430 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
2431 mApp, subId, "getCdmaMdn");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002432
2433 final long identity = Binder.clearCallingIdentity();
2434 try {
2435 final Phone phone = getPhone(subId);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002436 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002437 return phone.getLine1Number();
2438 } else {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002439 loge("getCdmaMdn: no phone found. Invalid subId: " + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002440 return null;
2441 }
2442 } finally {
2443 Binder.restoreCallingIdentity(identity);
Junda Liuca05d5d2014-08-14 22:36:34 -07002444 }
2445 }
2446
2447 /**
2448 * Returns the CDMA MIN.
2449 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002450 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002451 public String getCdmaMin(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002452 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
2453 mApp, subId, "getCdmaMin");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002454
2455 final long identity = Binder.clearCallingIdentity();
2456 try {
2457 final Phone phone = getPhone(subId);
2458 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
2459 return phone.getCdmaMin();
2460 } else {
2461 return null;
2462 }
2463 } finally {
2464 Binder.restoreCallingIdentity(identity);
Junda Liuca05d5d2014-08-14 22:36:34 -07002465 }
2466 }
2467
Hall Liud892bec2018-11-30 14:51:45 -08002468 @Override
2469 public void requestNumberVerification(PhoneNumberRange range, long timeoutMillis,
2470 INumberVerificationCallback callback, String callingPackage) {
2471 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
2472 != PERMISSION_GRANTED) {
2473 throw new SecurityException("Caller must hold the MODIFY_PHONE_STATE permission");
2474 }
2475 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
2476
2477 String authorizedPackage = NumberVerificationManager.getAuthorizedPackage(mApp);
2478 if (!TextUtils.equals(callingPackage, authorizedPackage)) {
2479 throw new SecurityException("Calling package must be configured in the device config");
2480 }
2481
2482 if (range == null) {
2483 throw new NullPointerException("Range must be non-null");
2484 }
2485
2486 timeoutMillis = Math.min(timeoutMillis,
Hall Liubd069e32019-02-28 18:56:30 -08002487 TelephonyManager.getMaxNumberVerificationTimeoutMillis());
Hall Liud892bec2018-11-30 14:51:45 -08002488
2489 NumberVerificationManager.getInstance().requestVerification(range, callback, timeoutMillis);
2490 }
2491
Junda Liuca05d5d2014-08-14 22:36:34 -07002492 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002493 * Returns true if CDMA provisioning needs to run.
2494 */
2495 public boolean needsOtaServiceProvisioning() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002496 final long identity = Binder.clearCallingIdentity();
2497 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002498 return getDefaultPhone().needsOtaServiceProvisioning();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002499 } finally {
2500 Binder.restoreCallingIdentity(identity);
2501 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002502 }
2503
2504 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002505 * Sets the voice mail number of a given subId.
2506 */
2507 @Override
2508 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002509 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, "setVoiceMailNumber");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002510
2511 final long identity = Binder.clearCallingIdentity();
2512 try {
2513 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
2514 new Pair<String, String>(alphaTag, number), new Integer(subId));
2515 return success;
2516 } finally {
2517 Binder.restoreCallingIdentity(identity);
2518 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002519 }
2520
Ta-wei Yen87c49842016-05-13 21:19:52 -07002521 @Override
Ta-wei Yenc9df0432017-04-17 17:09:07 -07002522 public Bundle getVisualVoicemailSettings(String callingPackage, int subId) {
2523 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002524 String systemDialer = TelecomManager.from(mApp).getSystemDialerPackage();
Ta-wei Yenc9df0432017-04-17 17:09:07 -07002525 if (!TextUtils.equals(callingPackage, systemDialer)) {
2526 throw new SecurityException("caller must be system dialer");
2527 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002528
2529 final long identity = Binder.clearCallingIdentity();
2530 try {
2531 PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(subId);
2532 if (phoneAccountHandle == null) {
2533 return null;
2534 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002535 return VisualVoicemailSettingsUtil.dump(mApp, phoneAccountHandle);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002536 } finally {
2537 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc9df0432017-04-17 17:09:07 -07002538 }
Ta-wei Yenc9df0432017-04-17 17:09:07 -07002539 }
2540
2541 @Override
Ta-wei Yen409ac562017-03-06 16:00:44 -08002542 public String getVisualVoicemailPackageName(String callingPackage, int subId) {
Ta-wei Yendca928f2017-01-10 16:17:08 -08002543 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jeff Davidson7e17e312018-02-13 18:17:36 -08002544 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08002545 mApp, subId, callingPackage, "getVisualVoicemailPackageName")) {
Ta-wei Yendca928f2017-01-10 16:17:08 -08002546 return null;
2547 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002548
Jeff Davidsona8e4e242018-03-15 17:16:18 -07002549 final long identity = Binder.clearCallingIdentity();
2550 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002551 return RemoteVvmTaskManager.getRemotePackage(mApp, subId).getPackageName();
Jeff Davidsona8e4e242018-03-15 17:16:18 -07002552 } finally {
2553 Binder.restoreCallingIdentity(identity);
2554 }
Ta-wei Yendca928f2017-01-10 16:17:08 -08002555 }
2556
2557 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002558 public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
2559 VisualVoicemailSmsFilterSettings settings) {
2560 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002561
2562 final long identity = Binder.clearCallingIdentity();
2563 try {
2564 VisualVoicemailSmsFilterConfig.enableVisualVoicemailSmsFilter(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002565 mApp, callingPackage, subId, settings);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002566 } finally {
2567 Binder.restoreCallingIdentity(identity);
2568 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07002569 }
2570
2571 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002572 public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
2573 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002574
2575 final long identity = Binder.clearCallingIdentity();
2576 try {
2577 VisualVoicemailSmsFilterConfig.disableVisualVoicemailSmsFilter(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002578 mApp, callingPackage, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002579 } finally {
2580 Binder.restoreCallingIdentity(identity);
2581 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07002582 }
2583
2584 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002585 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
2586 String callingPackage, int subId) {
2587 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002588
2589 final long identity = Binder.clearCallingIdentity();
2590 try {
2591 return VisualVoicemailSmsFilterConfig.getVisualVoicemailSmsFilterSettings(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002592 mApp, callingPackage, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002593 } finally {
2594 Binder.restoreCallingIdentity(identity);
2595 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07002596 }
2597
2598 @Override
Ta-wei Yen30a69c82016-12-27 14:52:32 -08002599 public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07002600 enforceReadPrivilegedPermission("getActiveVisualVoicemailSmsFilterSettings");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002601
2602 final long identity = Binder.clearCallingIdentity();
2603 try {
2604 return VisualVoicemailSmsFilterConfig.getActiveVisualVoicemailSmsFilterSettings(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002605 mApp, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002606 } finally {
2607 Binder.restoreCallingIdentity(identity);
2608 }
Ta-wei Yen30a69c82016-12-27 14:52:32 -08002609 }
2610
2611 @Override
2612 public void sendVisualVoicemailSmsForSubscriber(String callingPackage, int subId,
2613 String number, int port, String text, PendingIntent sentIntent) {
2614 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen527a9c02017-01-06 15:29:25 -08002615 enforceVisualVoicemailPackage(callingPackage, subId);
Ta-wei Yen30a69c82016-12-27 14:52:32 -08002616 enforceSendSmsPermission();
2617 // Make the calls as the phone process.
2618 final long identity = Binder.clearCallingIdentity();
2619 try {
2620 SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
2621 if (port == 0) {
2622 smsManager.sendTextMessageWithSelfPermissions(number, null, text,
2623 sentIntent, null, false);
2624 } else {
2625 byte[] data = text.getBytes(StandardCharsets.UTF_8);
2626 smsManager.sendDataMessageWithSelfPermissions(number, null,
2627 (short) port, data, sentIntent, null);
2628 }
2629 } finally {
2630 Binder.restoreCallingIdentity(identity);
2631 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07002632 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002633 /**
fionaxu0152e512016-11-14 13:36:14 -08002634 * Sets the voice activation state of a given subId.
2635 */
2636 @Override
2637 public void setVoiceActivationState(int subId, int activationState) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002638 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
2639 mApp, subId, "setVoiceActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002640
2641 final long identity = Binder.clearCallingIdentity();
2642 try {
2643 final Phone phone = getPhone(subId);
2644 if (phone != null) {
2645 phone.setVoiceActivationState(activationState);
2646 } else {
2647 loge("setVoiceActivationState fails with invalid subId: " + subId);
2648 }
2649 } finally {
2650 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08002651 }
2652 }
2653
2654 /**
2655 * Sets the data activation state of a given subId.
2656 */
2657 @Override
2658 public void setDataActivationState(int subId, int activationState) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002659 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
2660 mApp, subId, "setDataActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002661
2662 final long identity = Binder.clearCallingIdentity();
2663 try {
2664 final Phone phone = getPhone(subId);
2665 if (phone != null) {
2666 phone.setDataActivationState(activationState);
2667 } else {
2668 loge("setVoiceActivationState fails with invalid subId: " + subId);
2669 }
2670 } finally {
2671 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08002672 }
2673 }
2674
2675 /**
2676 * Returns the voice activation state of a given subId.
2677 */
2678 @Override
2679 public int getVoiceActivationState(int subId, String callingPackage) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07002680 enforceReadPrivilegedPermission("getVoiceActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002681
fionaxu0152e512016-11-14 13:36:14 -08002682 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002683 final long identity = Binder.clearCallingIdentity();
2684 try {
2685 if (phone != null) {
2686 return phone.getVoiceActivationState();
2687 } else {
2688 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2689 }
2690 } finally {
2691 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08002692 }
2693 }
2694
2695 /**
2696 * Returns the data activation state of a given subId.
2697 */
2698 @Override
2699 public int getDataActivationState(int subId, String callingPackage) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07002700 enforceReadPrivilegedPermission("getDataActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002701
fionaxu0152e512016-11-14 13:36:14 -08002702 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002703 final long identity = Binder.clearCallingIdentity();
2704 try {
2705 if (phone != null) {
2706 return phone.getDataActivationState();
2707 } else {
2708 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2709 }
2710 } finally {
2711 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08002712 }
2713 }
2714
2715 /**
Wink Saville36469e72014-06-11 15:17:00 -07002716 * Returns the unread count of voicemails for a subId
2717 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002718 @Override
Brad Ebingerf7664ba2018-11-29 12:43:38 -08002719 public int getVoiceMessageCountForSubscriber(int subId, String callingPackage) {
2720 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
2721 mApp, subId, callingPackage, "getVoiceMessageCountForSubscriber")) {
2722 return 0;
2723 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002724 final long identity = Binder.clearCallingIdentity();
2725 try {
2726 final Phone phone = getPhone(subId);
2727 if (phone != null) {
2728 return phone.getVoiceMessageCount();
2729 } else {
2730 return 0;
2731 }
2732 } finally {
2733 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07002734 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002735 }
2736
2737 /**
pkanwar8a4dcfb2017-01-19 13:43:16 -08002738 * returns true, if the device is in a state where both voice and data
2739 * are supported simultaneously. This can change based on location or network condition.
2740 */
2741 @Override
2742 public boolean isConcurrentVoiceAndDataAllowed(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002743 final long identity = Binder.clearCallingIdentity();
2744 try {
2745 final Phone phone = getPhone(subId);
2746 return (phone == null ? false : phone.isConcurrentVoiceAndDataAllowed());
2747 } finally {
2748 Binder.restoreCallingIdentity(identity);
2749 }
pkanwar8a4dcfb2017-01-19 13:43:16 -08002750 }
2751
2752 /**
fionaxu235cc5e2017-03-06 22:25:57 -08002753 * Send the dialer code if called from the current default dialer or the caller has
2754 * carrier privilege.
2755 * @param inputCode The dialer code to send
2756 */
2757 @Override
2758 public void sendDialerSpecialCode(String callingPackage, String inputCode) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002759 final Phone defaultPhone = getDefaultPhone();
fionaxu235cc5e2017-03-06 22:25:57 -08002760 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002761 String defaultDialer = TelecomManager.from(defaultPhone.getContext())
2762 .getDefaultDialerPackage();
fionaxu235cc5e2017-03-06 22:25:57 -08002763 if (!TextUtils.equals(callingPackage, defaultDialer)) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08002764 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
2765 getDefaultSubscription(), "sendDialerSpecialCode");
fionaxu235cc5e2017-03-06 22:25:57 -08002766 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002767
2768 final long identity = Binder.clearCallingIdentity();
2769 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002770 defaultPhone.sendDialerSpecialCode(inputCode);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002771 } finally {
2772 Binder.restoreCallingIdentity(identity);
2773 }
fionaxu235cc5e2017-03-06 22:25:57 -08002774 }
2775
2776 /**
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002777 * Returns the data network type.
2778 * Legacy call, permission-free.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002779 *
2780 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
2781 */
2782 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002783 public int getNetworkType() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08002784 final long identity = Binder.clearCallingIdentity();
2785 try {
2786 final Phone phone = getPhone(getDefaultSubscription());
2787 if (phone != null) {
2788 return phone.getServiceState().getDataNetworkType();
2789 } else {
2790 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2791 }
2792 } finally {
2793 Binder.restoreCallingIdentity(identity);
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002794 }
Wink Saville36469e72014-06-11 15:17:00 -07002795 }
2796
Pengquan Menga1bb6272018-09-06 09:59:22 -07002797 @Override
2798 public int getNetworkSelectionMode(int subId) {
Pengquan Menge92a50d2018-09-21 15:54:48 -07002799 if (!isActiveSubscription(subId)) {
2800 return TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
2801 }
2802
Pengquan Menga1bb6272018-09-06 09:59:22 -07002803 return (int) sendRequest(CMD_GET_NETWORK_SELECTION_MODE, null /* argument */, subId);
2804 }
2805
Brad Ebinger35c841c2018-10-01 10:40:55 -07002806 @Override
Brad Ebingerb2b65522019-03-15 13:48:47 -07002807 public boolean isInEmergencySmsMode() {
2808 enforceReadPrivilegedPermission("isInEmergencySmsMode");
2809 final long identity = Binder.clearCallingIdentity();
2810 try {
2811 for (Phone phone : PhoneFactory.getPhones()) {
2812 if (phone.isInEmergencySmsMode()) {
2813 return true;
2814 }
2815 }
2816 } finally {
2817 Binder.restoreCallingIdentity(identity);
2818 }
2819 return false;
2820 }
2821
2822 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002823 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
2824 throws RemoteException {
2825 enforceReadPrivilegedPermission("registerImsRegistrationCallback");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002826 final long token = Binder.clearCallingIdentity();
2827 try {
Brad Ebinger4ae57f92019-01-09 16:51:30 -08002828 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002829 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
Brad Ebinger35c841c2018-10-01 10:40:55 -07002830 .addRegistrationCallbackForSubscription(c, subId);
2831 } finally {
2832 Binder.restoreCallingIdentity(token);
2833 }
2834 }
2835
2836 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002837 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c) {
2838 enforceReadPrivilegedPermission("unregisterImsRegistrationCallback");
Brad Ebinger4ae57f92019-01-09 16:51:30 -08002839 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2840 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
2841 }
2842 Binder.withCleanCallingIdentity(() -> {
2843 try {
2844 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002845 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
Brad Ebinger4ae57f92019-01-09 16:51:30 -08002846 .removeRegistrationCallbackForSubscription(c, subId);
2847 } catch (IllegalArgumentException e) {
2848 Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
2849 + "is inactive, ignoring unregister.");
2850 // If the subscription is no longer active, just return, since the callback
2851 // will already have been removed internally.
2852 }
2853 });
Brad Ebinger35c841c2018-10-01 10:40:55 -07002854 }
2855
2856 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002857 public void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)
2858 throws RemoteException {
2859 enforceReadPrivilegedPermission("registerMmTelCapabilityCallback");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002860 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
2861 final long token = Binder.clearCallingIdentity();
2862 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002863 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
Brad Ebinger35c841c2018-10-01 10:40:55 -07002864 .addCapabilitiesCallbackForSubscription(c, subId);
2865 } finally {
2866 Binder.restoreCallingIdentity(token);
2867 }
2868 }
2869
2870 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002871 public void unregisterMmTelCapabilityCallback(int subId, IImsCapabilityCallback c) {
2872 enforceReadPrivilegedPermission("unregisterMmTelCapabilityCallback");
Brad Ebinger4ae57f92019-01-09 16:51:30 -08002873
2874 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2875 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
2876 }
2877 Binder.withCleanCallingIdentity(() -> {
2878 try {
2879 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002880 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
Brad Ebinger4ae57f92019-01-09 16:51:30 -08002881 .removeCapabilitiesCallbackForSubscription(c, subId);
2882 } catch (IllegalArgumentException e) {
2883 Log.i(LOG_TAG, "unregisterMmTelCapabilityCallback: " + subId
2884 + "is inactive, ignoring unregister.");
2885 // If the subscription is no longer active, just return, since the callback
2886 // will already have been removed internally.
2887 }
2888 });
Brad Ebinger35c841c2018-10-01 10:40:55 -07002889 }
2890
2891 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002892 public boolean isCapable(int subId, int capability, int regTech) {
2893 enforceReadPrivilegedPermission("isCapable");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002894 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
2895 final long token = Binder.clearCallingIdentity();
2896 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002897 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07002898 getSlotIndexOrException(subId)).queryMmTelCapability(capability, regTech);
2899 } catch (ImsException e) {
2900 Log.w(LOG_TAG, "IMS isCapable - service unavailable: " + e.getMessage());
2901 return false;
Brad Ebinger6b5ac222019-02-04 14:36:52 -08002902 } catch (IllegalArgumentException e) {
2903 Log.i(LOG_TAG, "isCapable: " + subId + " is inactive, returning false.");
2904 return false;
Brad Ebinger35c841c2018-10-01 10:40:55 -07002905 } finally {
2906 Binder.restoreCallingIdentity(token);
2907 }
2908 }
2909
2910 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002911 public boolean isAvailable(int subId, int capability, int regTech) {
2912 enforceReadPrivilegedPermission("isAvailable");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002913 final long token = Binder.clearCallingIdentity();
2914 try {
2915 Phone phone = getPhone(subId);
2916 if (phone == null) return false;
2917 return phone.isImsCapabilityAvailable(capability, regTech);
2918 } finally {
2919 Binder.restoreCallingIdentity(token);
2920 }
2921 }
2922
2923 @Override
2924 public boolean isAdvancedCallingSettingEnabled(int subId) {
2925 enforceReadPrivilegedPermission("enforceReadPrivilegedPermission");
2926 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
2927 final long token = Binder.clearCallingIdentity();
2928 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002929 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07002930 getSlotIndexOrException(subId)).isEnhanced4gLteModeSettingEnabledByUser();
2931 } finally {
2932 Binder.restoreCallingIdentity(token);
2933 }
2934 }
2935
2936 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08002937 public void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07002938 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08002939 "setAdvancedCallingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002940 final long identity = Binder.clearCallingIdentity();
2941 try {
2942 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002943 ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07002944 getSlotIndexOrException(subId)).setEnhanced4gLteModeSetting(isEnabled);
2945 } finally {
2946 Binder.restoreCallingIdentity(identity);
2947 }
2948 }
2949
2950 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08002951 public boolean isVtSettingEnabled(int subId) {
2952 enforceReadPrivilegedPermission("isVtSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002953 final long identity = Binder.clearCallingIdentity();
2954 try {
2955 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002956 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07002957 getSlotIndexOrException(subId)).isVtEnabledByUser();
2958 } finally {
2959 Binder.restoreCallingIdentity(identity);
2960 }
2961 }
2962
2963 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08002964 public void setVtSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07002965 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08002966 "setVtSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002967 final long identity = Binder.clearCallingIdentity();
2968 try {
2969 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002970 ImsManager.getInstance(mApp, getSlotIndexOrException(subId)).setVtSetting(isEnabled);
Brad Ebinger35c841c2018-10-01 10:40:55 -07002971 } finally {
2972 Binder.restoreCallingIdentity(identity);
2973 }
2974 }
2975
2976 @Override
2977 public boolean isVoWiFiSettingEnabled(int subId) {
2978 enforceReadPrivilegedPermission("isVoWiFiSettingEnabled");
2979 final long identity = Binder.clearCallingIdentity();
2980 try {
2981 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002982 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07002983 getSlotIndexOrException(subId)).isWfcEnabledByUser();
2984 } finally {
2985 Binder.restoreCallingIdentity(identity);
2986 }
2987 }
2988
2989 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08002990 public void setVoWiFiSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07002991 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08002992 "setVoWiFiSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07002993 final long identity = Binder.clearCallingIdentity();
2994 try {
2995 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002996 ImsManager.getInstance(mApp, getSlotIndexOrException(subId)).setWfcSetting(isEnabled);
Brad Ebinger35c841c2018-10-01 10:40:55 -07002997 } finally {
2998 Binder.restoreCallingIdentity(identity);
2999 }
3000 }
3001
3002 @Override
3003 public boolean isVoWiFiRoamingSettingEnabled(int subId) {
3004 enforceReadPrivilegedPermission("isVoWiFiRoamingSettingEnabled");
3005 final long identity = Binder.clearCallingIdentity();
3006 try {
3007 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003008 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003009 getSlotIndexOrException(subId)).isWfcRoamingEnabledByUser();
3010 } finally {
3011 Binder.restoreCallingIdentity(identity);
3012 }
3013 }
3014
3015 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08003016 public void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07003017 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08003018 "setVoWiFiRoamingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07003019 final long identity = Binder.clearCallingIdentity();
3020 try {
3021 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003022 ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003023 getSlotIndexOrException(subId)).setWfcRoamingSetting(isEnabled);
3024 } finally {
3025 Binder.restoreCallingIdentity(identity);
3026 }
3027 }
3028
3029 @Override
3030 public void setVoWiFiNonPersistent(int subId, boolean isCapable, int mode) {
3031 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3032 "setVoWiFiNonPersistent");
3033 final long identity = Binder.clearCallingIdentity();
3034 try {
3035 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger43e66f12019-01-15 12:40:04 -08003036 boolean isRoaming = TelephonyManager.from(
3037 getPhone(subId).getContext()).isNetworkRoaming(subId);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003038 ImsManager.getInstance(mApp,
Brad Ebinger43e66f12019-01-15 12:40:04 -08003039 getSlotIndexOrException(subId)).setWfcNonPersistent(isCapable, mode, isRoaming);
Brad Ebinger35c841c2018-10-01 10:40:55 -07003040 } finally {
3041 Binder.restoreCallingIdentity(identity);
3042 }
3043 }
3044
3045 @Override
3046 public int getVoWiFiModeSetting(int subId) {
3047 enforceReadPrivilegedPermission("getVoWiFiModeSetting");
3048 final long identity = Binder.clearCallingIdentity();
3049 try {
3050 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003051 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003052 getSlotIndexOrException(subId)).getWfcMode(false /*isRoaming*/);
3053 } finally {
3054 Binder.restoreCallingIdentity(identity);
3055 }
3056 }
3057
3058 @Override
3059 public void setVoWiFiModeSetting(int subId, int mode) {
3060 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3061 "setVoWiFiModeSetting");
3062 final long identity = Binder.clearCallingIdentity();
3063 try {
3064 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003065 ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003066 getSlotIndexOrException(subId)).setWfcMode(mode, false /*isRoaming*/);
3067 } finally {
3068 Binder.restoreCallingIdentity(identity);
3069 }
3070 }
3071
3072 @Override
3073 public int getVoWiFiRoamingModeSetting(int subId) {
3074 enforceReadPrivilegedPermission("getVoWiFiRoamingModeSetting");
3075 final long identity = Binder.clearCallingIdentity();
3076 try {
3077 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003078 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003079 getSlotIndexOrException(subId)).getWfcMode(true /*isRoaming*/);
3080 } finally {
3081 Binder.restoreCallingIdentity(identity);
3082 }
3083 }
3084
3085 @Override
3086 public void setVoWiFiRoamingModeSetting(int subId, int mode) {
3087 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3088 "setVoWiFiRoamingModeSetting");
3089 final long identity = Binder.clearCallingIdentity();
3090 try {
3091 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003092 ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003093 getSlotIndexOrException(subId)).setWfcMode(mode, true /*isRoaming*/);
3094 } finally {
3095 Binder.restoreCallingIdentity(identity);
3096 }
3097 }
3098
3099 @Override
3100 public void setRttCapabilitySetting(int subId, boolean isEnabled) {
3101 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3102 "setRttCapabilityEnabled");
3103 final long identity = Binder.clearCallingIdentity();
3104 try {
3105 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003106 ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003107 getSlotIndexOrException(subId)).setRttEnabled(isEnabled);
3108 } finally {
3109 Binder.restoreCallingIdentity(identity);
3110 }
3111 }
3112
3113 @Override
3114 public boolean isTtyOverVolteEnabled(int subId) {
3115 enforceReadPrivilegedPermission("isTtyOverVolteEnabled");
3116 final long identity = Binder.clearCallingIdentity();
3117 try {
3118 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003119 return ImsManager.getInstance(mApp,
Brad Ebinger35c841c2018-10-01 10:40:55 -07003120 getSlotIndexOrException(subId)).isTtyOnVoLteCapable();
3121 } finally {
3122 Binder.restoreCallingIdentity(identity);
3123 }
3124 }
3125
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003126 @Override
3127 public void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
3128 enforceReadPrivilegedPermission("registerImsProvisioningChangedCallback");
3129 final long identity = Binder.clearCallingIdentity();
3130 try {
3131 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003132 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
Brad Ebinger4ae57f92019-01-09 16:51:30 -08003133 .addProvisioningCallbackForSubscription(callback, subId);
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003134 } finally {
3135 Binder.restoreCallingIdentity(identity);
3136 }
3137 }
3138
3139 @Override
3140 public void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
3141 enforceReadPrivilegedPermission("unregisterImsProvisioningChangedCallback");
3142 final long identity = Binder.clearCallingIdentity();
Brad Ebinger4ae57f92019-01-09 16:51:30 -08003143 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3144 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
3145 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003146 try {
3147 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003148 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
Brad Ebinger4ae57f92019-01-09 16:51:30 -08003149 .removeProvisioningCallbackForSubscription(callback, subId);
3150 } catch (IllegalArgumentException e) {
3151 Log.i(LOG_TAG, "unregisterImsProvisioningChangedCallback: " + subId
3152 + "is inactive, ignoring unregister.");
3153 // If the subscription is no longer active, just return, since the callback will already
3154 // have been removed internally.
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003155 } finally {
3156 Binder.restoreCallingIdentity(identity);
3157 }
3158 }
3159
3160 @Override
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003161 public void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
3162 boolean isProvisioned) {
3163 if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3164 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3165 throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3166 }
3167 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3168 "setProvisioningStatusForCapability");
3169 final long identity = Binder.clearCallingIdentity();
3170 try {
3171 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3172 Phone phone = getPhone(subId);
3173 if (phone == null) {
3174 loge("setImsProvisioningStatusForCapability: phone instance null for subid "
3175 + subId);
3176 return;
3177 }
3178 if (!doesImsCapabilityRequireProvisioning(phone.getContext(), subId, capability)) {
3179 return;
3180 }
3181
3182 // this capability requires provisioning, route to the correct API.
3183 ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
3184 switch (capability) {
3185 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE: {
3186 if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3187 ims.setVolteProvisioned(isProvisioned);
3188 } else if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
3189 ims.setWfcProvisioned(isProvisioned);
3190 }
3191 break;
3192 }
3193 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
3194 // There is currently no difference in VT provisioning type.
3195 ims.setVtProvisioned(isProvisioned);
3196 break;
3197 }
3198 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
3199 // There is no "deprecated" UT provisioning mechanism through ImsConfig, so
3200 // change the capability of the feature instead if needed.
3201 if (isMmTelCapabilityProvisionedInCache(subId, capability, tech)
3202 == isProvisioned) {
3203 // No change in provisioning.
3204 return;
3205 }
3206 cacheMmTelCapabilityProvisioning(subId, capability, tech, isProvisioned);
3207 try {
3208 ims.changeMmTelCapability(capability, tech, isProvisioned);
3209 } catch (ImsException e) {
3210 loge("setImsProvisioningStatusForCapability: couldn't change UT capability"
3211 + ", Exception" + e.getMessage());
3212 }
3213 break;
3214 }
3215 default: {
3216 throw new IllegalArgumentException("Tried to set provisioning for capability '"
3217 + capability + "', which does not require provisioning.");
3218 }
3219 }
3220
3221 } finally {
3222 Binder.restoreCallingIdentity(identity);
3223 }
3224 }
3225
3226 @Override
3227 public boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech) {
3228 if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3229 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3230 throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3231 }
3232 enforceReadPrivilegedPermission("getProvisioningStatusForCapability");
3233 final long identity = Binder.clearCallingIdentity();
3234 try {
3235 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
3236 Phone phone = getPhone(subId);
3237 if (phone == null) {
3238 loge("getImsProvisioningStatusForCapability: phone instance null for subid "
3239 + subId);
3240 // We will fail with "true" as the provisioning status because this is the default
3241 // if we do not require provisioning.
3242 return true;
3243 }
3244
3245 if (!doesImsCapabilityRequireProvisioning(phone.getContext(), subId, capability)) {
3246 return true;
3247 }
3248
3249 ImsManager ims = ImsManager.getInstance(mApp, getSlotIndex(subId));
3250 switch (capability) {
3251 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE: {
3252 if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3253 return ims.isVolteProvisionedOnDevice();
3254 } else if (tech == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN) {
3255 return ims.isWfcProvisionedOnDevice();
3256 }
3257 // This should never happen, since we are checking tech above to make sure it
3258 // is either LTE or IWLAN.
3259 throw new IllegalArgumentException("Invalid radio technology for voice "
3260 + "capability.");
3261 }
3262 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
3263 // There is currently no difference in VT provisioning type.
3264 return ims.isVtProvisionedOnDevice();
3265 }
3266 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
3267 // There is no "deprecated" UT provisioning mechanism, so get from shared prefs.
3268 return isMmTelCapabilityProvisionedInCache(subId, capability, tech);
3269 }
3270 default: {
3271 throw new IllegalArgumentException("Tried to get provisioning for capability '"
3272 + capability + "', which does not require provisioning.");
3273 }
3274 }
3275
3276 } finally {
3277 Binder.restoreCallingIdentity(identity);
3278 }
3279 }
3280
3281 @Override
3282 public boolean isMmTelCapabilityProvisionedInCache(int subId, int capability, int tech) {
3283 if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3284 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3285 throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3286 }
3287 enforceReadPrivilegedPermission("isMmTelCapabilityProvisionedInCache");
3288 int provisionedBits = getMmTelCapabilityProvisioningBitfield(subId, tech);
3289 return (provisionedBits & capability) > 0;
3290 }
3291
3292 @Override
3293 public void cacheMmTelCapabilityProvisioning(int subId, int capability, int tech,
3294 boolean isProvisioned) {
3295 if (tech != ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
3296 && tech != ImsRegistrationImplBase.REGISTRATION_TECH_LTE) {
3297 throw new IllegalArgumentException("Registration technology '" + tech + "' is invalid");
3298 }
3299 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3300 "setProvisioningStatusForCapability");
3301 int provisionedBits = getMmTelCapabilityProvisioningBitfield(subId, tech);
3302 // If the current provisioning status for capability already matches isProvisioned,
3303 // do nothing.
3304 if (((provisionedBits & capability) > 0) == isProvisioned) {
3305 return;
3306 }
3307 if (isProvisioned) {
3308 setMmTelCapabilityProvisioningBitfield(subId, tech, (provisionedBits | capability));
3309 } else {
3310 setMmTelCapabilityProvisioningBitfield(subId, tech, (provisionedBits & ~capability));
3311 }
3312 }
3313
3314 /**
3315 * @return the bitfield containing the MmTel provisioning for the provided subscription and
3316 * technology. The bitfield should mirror the bitfield defined by
3317 * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}.
3318 */
3319 private int getMmTelCapabilityProvisioningBitfield(int subId, int tech) {
3320 String key = getMmTelProvisioningKey(subId, tech);
3321 // Default is no capabilities are provisioned.
3322 return mTelephonySharedPreferences.getInt(key, 0 /*default*/);
3323 }
3324
3325 /**
3326 * Sets the MmTel capability provisioning bitfield (defined by
3327 * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}) for the subscription and
3328 * technology specified.
3329 *
3330 * Note: This is a synchronous command and should not be called on UI thread.
3331 */
3332 private void setMmTelCapabilityProvisioningBitfield(int subId, int tech, int newField) {
3333 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
3334 String key = getMmTelProvisioningKey(subId, tech);
3335 editor.putInt(key, newField);
3336 editor.commit();
3337 }
3338
3339 private static String getMmTelProvisioningKey(int subId, int tech) {
3340 // resulting key is provision_ims_mmtel_{subId}_{tech}
3341 return PREF_PROVISION_IMS_MMTEL_PREFIX + subId + "_" + tech;
3342 }
3343
3344 /**
3345 * Query CarrierConfig to see if the specified capability requires provisioning for the
3346 * carrier associated with the subscription id.
3347 */
3348 private boolean doesImsCapabilityRequireProvisioning(Context context, int subId,
3349 int capability) {
3350 CarrierConfigManager configManager = new CarrierConfigManager(context);
3351 PersistableBundle c = configManager.getConfigForSubId(subId);
3352 boolean requireUtProvisioning = c.getBoolean(
3353 // By default, this config is true (even if there is no SIM). We also check to make
3354 // sure the subscription needs provisioning here, so we do not need to check for
3355 // the no-SIM case, where we would normally shortcut this to false.
3356 CarrierConfigManager.KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, true)
3357 && c.getBoolean(CarrierConfigManager.KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL,
3358 false);
3359 boolean requireVoiceVtProvisioning = c.getBoolean(
3360 CarrierConfigManager.KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
3361
3362 // First check to make sure that the capability requires provisioning.
3363 switch (capability) {
3364 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE:
3365 // intentional fallthrough
3366 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO: {
3367 if (requireVoiceVtProvisioning) {
3368 // Voice and Video requires provisioning
3369 return true;
3370 }
3371 break;
3372 }
3373 case MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT: {
3374 if (requireUtProvisioning) {
3375 // UT requires provisioning
3376 return true;
3377 }
3378 break;
3379 }
3380 }
3381 return false;
3382 }
3383
3384 @Override
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003385 public int getImsProvisioningInt(int subId, int key) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003386 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3387 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
3388 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003389 enforceReadPrivilegedPermission("getImsProvisioningInt");
3390 final long identity = Binder.clearCallingIdentity();
3391 try {
3392 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003393 int slotId = getSlotIndex(subId);
3394 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
3395 Log.w(LOG_TAG, "getImsProvisioningInt: called with an inactive subscription '"
3396 + subId + "' for key:" + key);
3397 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
3398 }
3399 return ImsManager.getInstance(mApp, slotId).getConfigInterface().getConfigInt(key);
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003400 } catch (ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003401 Log.w(LOG_TAG, "getImsProvisioningInt: ImsService is not available for subscription '"
3402 + subId + "' for key:" + key);
3403 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003404 } finally {
3405 Binder.restoreCallingIdentity(identity);
3406 }
3407 }
3408
3409 @Override
3410 public String getImsProvisioningString(int subId, int key) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003411 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3412 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
3413 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003414 enforceReadPrivilegedPermission("getImsProvisioningString");
3415 final long identity = Binder.clearCallingIdentity();
3416 try {
3417 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003418 int slotId = getSlotIndex(subId);
3419 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
3420 Log.w(LOG_TAG, "getImsProvisioningString: called for an inactive subscription id '"
3421 + subId + "' for key:" + key);
3422 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_GENERIC;
3423 }
3424 return ImsManager.getInstance(mApp, slotId).getConfigInterface().getConfigString(key);
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003425 } catch (ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003426 Log.w(LOG_TAG, "getImsProvisioningString: ImsService is not available for sub '"
3427 + subId + "' for key:" + key);
3428 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_NOT_READY;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003429 } finally {
3430 Binder.restoreCallingIdentity(identity);
3431 }
3432 }
3433
3434 @Override
3435 public int setImsProvisioningInt(int subId, int key, int value) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003436 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3437 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
3438 }
Brad Ebinger3d0b34e2018-11-15 14:13:12 -08003439 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3440 "setImsProvisioningInt");
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003441 final long identity = Binder.clearCallingIdentity();
3442 try {
3443 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003444 int slotId = getSlotIndex(subId);
3445 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
3446 Log.w(LOG_TAG, "setImsProvisioningInt: called with an inactive subscription id '"
3447 + subId + "' for key:" + key);
3448 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
3449 }
3450 return ImsManager.getInstance(mApp, slotId).getConfigInterface().setConfig(key, value);
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003451 } catch (ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003452 Log.w(LOG_TAG, "setImsProvisioningInt: ImsService unavailable for sub '" + subId
3453 + "' for key:" + key);
3454 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003455 } finally {
3456 Binder.restoreCallingIdentity(identity);
3457 }
3458 }
3459
3460 @Override
3461 public int setImsProvisioningString(int subId, int key, String value) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003462 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3463 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
3464 }
Brad Ebinger3d0b34e2018-11-15 14:13:12 -08003465 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
3466 "setImsProvisioningString");
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003467 final long identity = Binder.clearCallingIdentity();
3468 try {
3469 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003470 int slotId = getSlotIndex(subId);
3471 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
3472 Log.w(LOG_TAG, "setImsProvisioningString: called with an inactive subscription id '"
3473 + subId + "' for key:" + key);
3474 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
3475 }
3476 return ImsManager.getInstance(mApp, slotId).getConfigInterface().setConfig(key, value);
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003477 } catch (ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003478 Log.w(LOG_TAG, "setImsProvisioningString: ImsService unavailable for sub '" + subId
3479 + "' for key:" + key);
3480 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07003481 } finally {
3482 Binder.restoreCallingIdentity(identity);
3483 }
3484 }
3485
Brad Ebinger35c841c2018-10-01 10:40:55 -07003486 private int getSlotIndexOrException(int subId) throws IllegalArgumentException {
3487 int slotId = SubscriptionManager.getSlotIndex(subId);
3488 if (!SubscriptionManager.isValidSlotIndex(slotId)) {
Brad Ebinger6b5ac222019-02-04 14:36:52 -08003489 throw new IllegalArgumentException("Invalid Subscription Id, subId=" + subId);
Brad Ebinger35c841c2018-10-01 10:40:55 -07003490 }
3491 return slotId;
3492 }
3493
Brad Ebinger1c8542e2019-01-14 13:43:14 -08003494 private int getSlotIndex(int subId) {
3495 int slotId = SubscriptionManager.getSlotIndex(subId);
3496 if (!SubscriptionManager.isValidSlotIndex(slotId)) {
3497 return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
3498 }
3499 return slotId;
3500 }
3501
Wink Saville36469e72014-06-11 15:17:00 -07003502 /**
3503 * Returns the network type for a subId
3504 */
3505 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003506 public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003507 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08003508 mApp, subId, callingPackage, "getNetworkTypeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003509 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
3510 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07003511
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003512 final long identity = Binder.clearCallingIdentity();
3513 try {
3514 final Phone phone = getPhone(subId);
3515 if (phone != null) {
3516 return phone.getServiceState().getDataNetworkType();
3517 } else {
3518 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
3519 }
3520 } finally {
3521 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003522 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003523 }
3524
3525 /**
3526 * Returns the data network type
3527 */
3528 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003529 public int getDataNetworkType(String callingPackage) {
3530 return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07003531 }
3532
3533 /**
3534 * Returns the data network type for a subId
3535 */
3536 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003537 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003538 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08003539 mApp, subId, callingPackage, "getDataNetworkTypeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003540 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
3541 }
3542
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003543 final long identity = Binder.clearCallingIdentity();
3544 try {
3545 final Phone phone = getPhone(subId);
3546 if (phone != null) {
3547 return phone.getServiceState().getDataNetworkType();
3548 } else {
3549 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
3550 }
3551 } finally {
3552 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003553 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003554 }
3555
3556 /**
Wink Saville36469e72014-06-11 15:17:00 -07003557 * Returns the Voice network type for a subId
3558 */
3559 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07003560 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003561 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08003562 mApp, subId, callingPackage, "getDataNetworkTypeForSubscriber")) {
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07003563 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
3564 }
3565
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003566 final long identity = Binder.clearCallingIdentity();
3567 try {
3568 final Phone phone = getPhone(subId);
3569 if (phone != null) {
3570 return phone.getServiceState().getVoiceNetworkType();
3571 } else {
3572 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
3573 }
3574 } finally {
3575 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003576 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003577 }
3578
3579 /**
3580 * @return true if a ICC card is present
3581 */
3582 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07003583 // FIXME Make changes to pass defaultSimId of type int
Sanket Padawe13bac7b2017-03-20 15:04:47 -07003584 return hasIccCardUsingSlotIndex(mSubscriptionController.getSlotIndex(
3585 getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -07003586 }
3587
3588 /**
Sanket Padawe13bac7b2017-03-20 15:04:47 -07003589 * @return true if a ICC card is present for a slotIndex
Wink Saville36469e72014-06-11 15:17:00 -07003590 */
Sanket Padawe356d7632015-06-22 14:03:32 -07003591 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07003592 public boolean hasIccCardUsingSlotIndex(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003593 final long identity = Binder.clearCallingIdentity();
3594 try {
3595 final Phone phone = PhoneFactory.getPhone(slotIndex);
3596 if (phone != null) {
3597 return phone.getIccCard().hasIccCard();
3598 } else {
3599 return false;
3600 }
3601 } finally {
3602 Binder.restoreCallingIdentity(identity);
Amit Mahajana6fc2a82015-01-06 11:53:51 -08003603 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003604 }
3605
3606 /**
3607 * Return if the current radio is LTE on CDMA. This
3608 * is a tri-state return value as for a period of time
3609 * the mode may be unknown.
3610 *
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003611 * @param callingPackage the name of the package making the call.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003612 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08003613 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003614 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003615 @Override
3616 public int getLteOnCdmaMode(String callingPackage) {
3617 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07003618 }
3619
Sanket Padawe356d7632015-06-22 14:03:32 -07003620 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003621 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003622 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08003623 mApp, subId, callingPackage, "getLteOnCdmaModeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003624 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
3625 }
3626
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003627 final long identity = Binder.clearCallingIdentity();
3628 try {
3629 final Phone phone = getPhone(subId);
3630 if (phone == null) {
3631 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
3632 } else {
3633 return phone.getLteOnCdmaMode();
3634 }
3635 } finally {
3636 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003637 }
Wink Saville36469e72014-06-11 15:17:00 -07003638 }
3639
Wink Saville36469e72014-06-11 15:17:00 -07003640 /**
3641 * {@hide}
3642 * Returns Default subId, 0 in the case of single standby.
3643 */
Wink Savilleb564aae2014-10-23 10:18:09 -07003644 private int getDefaultSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08003645 return mSubscriptionController.getDefaultSubId();
Wink Saville36469e72014-06-11 15:17:00 -07003646 }
3647
Shishir Agrawala9f32182016-04-12 12:00:16 -07003648 private int getSlotForDefaultSubscription() {
3649 return mSubscriptionController.getPhoneId(getDefaultSubscription());
3650 }
3651
Wink Savilleb564aae2014-10-23 10:18:09 -07003652 private int getPreferredVoiceSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08003653 return mSubscriptionController.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003654 }
Ihab Awadf2177b72013-11-25 13:33:23 -08003655
Pengquan Menge92a50d2018-09-21 15:54:48 -07003656 private boolean isActiveSubscription(int subId) {
3657 return mSubscriptionController.isActiveSubId(subId);
3658 }
3659
Ihab Awadf2177b72013-11-25 13:33:23 -08003660 /**
3661 * @see android.telephony.TelephonyManager.WifiCallingChoices
3662 */
3663 public int getWhenToMakeWifiCalls() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003664 final long identity = Binder.clearCallingIdentity();
3665 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003666 return Settings.System.getInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003667 Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
3668 getWhenToMakeWifiCallsDefaultPreference());
3669 } finally {
3670 Binder.restoreCallingIdentity(identity);
3671 }
Ihab Awadf2177b72013-11-25 13:33:23 -08003672 }
3673
3674 /**
3675 * @see android.telephony.TelephonyManager.WifiCallingChoices
3676 */
3677 public void setWhenToMakeWifiCalls(int preference) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003678 final long identity = Binder.clearCallingIdentity();
3679 try {
3680 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003681 Settings.System.putInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003682 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
3683 } finally {
3684 Binder.restoreCallingIdentity(identity);
3685 }
Ihab Awadf9e92732013-12-05 18:02:52 -08003686 }
3687
Sailesh Nepald1e68152013-12-12 19:08:02 -08003688 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07003689 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08003690 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08003691 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08003692
Jordan Liu4c733742019-02-28 12:03:40 -08003693 private Phone getPhoneFromSlotIdOrThrowException(int slotIndex) {
3694 int phoneId = UiccController.getInstance().getPhoneIdFromSlotId(slotIndex);
3695 if (phoneId == -1) {
3696 throw new IllegalArgumentException("Given slot index: " + slotIndex
3697 + " does not correspond to an active phone");
3698 }
3699 return PhoneFactory.getPhone(phoneId);
3700 }
3701
Shishir Agrawal566b7612013-10-28 14:41:00 -07003702 @Override
Derek Tan740e1672017-06-27 14:56:27 -07003703 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
3704 int subId, String callingPackage, String aid, int p2) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003705 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3706 mApp, subId, "iccOpenLogicalChannel");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003707 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jordan Liu4c733742019-02-28 12:03:40 -08003708 if (DBG) {
3709 log("iccOpenLogicalChannel: subId=" + subId + " aid=" + aid + " p2=" + p2);
3710 }
3711 return iccOpenLogicalChannelWithPermission(getPhoneFromSubId(subId), callingPackage, aid,
3712 p2);
3713 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003714
Jordan Liu4c733742019-02-28 12:03:40 -08003715
3716 @Override
3717 public IccOpenLogicalChannelResponse iccOpenLogicalChannelBySlot(
3718 int slotIndex, String callingPackage, String aid, int p2) {
3719 enforceModifyPermission();
3720 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3721 if (DBG) {
3722 log("iccOpenLogicalChannelBySlot: slot=" + slotIndex + " aid=" + aid + " p2=" + p2);
3723 }
3724 return iccOpenLogicalChannelWithPermission(getPhoneFromSlotIdOrThrowException(slotIndex),
3725 callingPackage, aid, p2);
3726 }
3727
3728 private IccOpenLogicalChannelResponse iccOpenLogicalChannelWithPermission(Phone phone,
3729 String callingPackage, String aid, int p2) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003730 final long identity = Binder.clearCallingIdentity();
3731 try {
3732 if (TextUtils.equals(ISDR_AID, aid)) {
3733 // Only allows LPA to open logical channel to ISD-R.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003734 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
3735 .getContext().getPackageManager());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003736 if (bestComponent == null
3737 || !TextUtils.equals(callingPackage, bestComponent.packageName)) {
3738 loge("The calling package is not allowed to access ISD-R.");
3739 throw new SecurityException(
3740 "The calling package is not allowed to access ISD-R.");
3741 }
Derek Tan740e1672017-06-27 14:56:27 -07003742 }
Derek Tan740e1672017-06-27 14:56:27 -07003743
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003744 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse) sendRequest(
Jordan Liu4c733742019-02-28 12:03:40 -08003745 CMD_OPEN_CHANNEL, new Pair<String, Integer>(aid, p2), phone,
3746 null /* workSource */);
3747 if (DBG) log("iccOpenLogicalChannelWithPermission: " + response);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003748 return response;
3749 } finally {
3750 Binder.restoreCallingIdentity(identity);
3751 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003752 }
3753
3754 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003755 public boolean iccCloseLogicalChannel(int subId, int channel) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003756 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3757 mApp, subId, "iccCloseLogicalChannel");
Jordan Liu4c733742019-02-28 12:03:40 -08003758 if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
3759 return iccCloseLogicalChannelWithPermission(getPhoneFromSubId(subId), channel);
3760 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003761
Jordan Liu4c733742019-02-28 12:03:40 -08003762 @Override
3763 public boolean iccCloseLogicalChannelBySlot(int slotIndex, int channel) {
3764 enforceModifyPermission();
3765 if (DBG) log("iccCloseLogicalChannelBySlot: slotIndex=" + slotIndex + " chnl=" + channel);
3766 return iccCloseLogicalChannelWithPermission(getPhoneFromSlotIdOrThrowException(slotIndex),
3767 channel);
3768 }
3769
3770 private boolean iccCloseLogicalChannelWithPermission(Phone phone, int channel) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003771 final long identity = Binder.clearCallingIdentity();
3772 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003773 if (channel < 0) {
3774 return false;
3775 }
Jordan Liu4c733742019-02-28 12:03:40 -08003776 Boolean success = (Boolean) sendRequest(CMD_CLOSE_CHANNEL, channel, phone,
3777 null /* workSource */);
3778 if (DBG) log("iccCloseLogicalChannelWithPermission: " + success);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003779 return success;
3780 } finally {
3781 Binder.restoreCallingIdentity(identity);
Shishir Agrawal566b7612013-10-28 14:41:00 -07003782 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003783 }
3784
3785 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003786 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
Shishir Agrawal566b7612013-10-28 14:41:00 -07003787 int command, int p1, int p2, int p3, String data) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003788 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3789 mApp, subId, "iccTransmitApduLogicalChannel");
Jordan Liu4c733742019-02-28 12:03:40 -08003790 if (DBG) {
3791 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
3792 + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
3793 + p3 + " data=" + data);
3794 }
3795 return iccTransmitApduLogicalChannelWithPermission(getPhoneFromSubId(subId), channel, cla,
3796 command, p1, p2, p3, data);
3797 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003798
Jordan Liu4c733742019-02-28 12:03:40 -08003799 @Override
3800 public String iccTransmitApduLogicalChannelBySlot(int slotIndex, int channel, int cla,
3801 int command, int p1, int p2, int p3, String data) {
3802 enforceModifyPermission();
3803 if (DBG) {
3804 log("iccTransmitApduLogicalChannelBySlot: slotIndex=" + slotIndex + " chnl=" + channel
3805 + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
3806 + p3 + " data=" + data);
3807 }
3808 return iccTransmitApduLogicalChannelWithPermission(
3809 getPhoneFromSlotIdOrThrowException(slotIndex), channel, cla, command, p1, p2, p3,
3810 data);
3811 }
3812
3813 private String iccTransmitApduLogicalChannelWithPermission(Phone phone, int channel, int cla,
3814 int command, int p1, int p2, int p3, String data) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003815 final long identity = Binder.clearCallingIdentity();
3816 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003817 if (channel < 0) {
3818 return "";
3819 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003820
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003821 IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Jordan Liu4c733742019-02-28 12:03:40 -08003822 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), phone,
3823 null /* workSource */);
3824 if (DBG) log("iccTransmitApduLogicalChannelWithPermission: " + response);
Shishir Agrawal566b7612013-10-28 14:41:00 -07003825
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003826 // Append the returned status code to the end of the response payload.
3827 String s = Integer.toHexString(
3828 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
3829 if (response.payload != null) {
3830 s = IccUtils.bytesToHexString(response.payload) + s;
3831 }
3832 return s;
3833 } finally {
3834 Binder.restoreCallingIdentity(identity);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07003835 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07003836 }
Jake Hambye994d462014-02-03 13:10:13 -08003837
Evan Charltonc66da362014-05-16 14:06:40 -07003838 @Override
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08003839 public String iccTransmitApduBasicChannel(int subId, String callingPackage, int cla,
3840 int command, int p1, int p2, int p3, String data) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003841 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3842 mApp, subId, "iccTransmitApduBasicChannel");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003843 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jordan Liu4c733742019-02-28 12:03:40 -08003844 if (DBG) {
3845 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
3846 + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
3847 }
3848 return iccTransmitApduBasicChannelWithPermission(getPhoneFromSubId(subId), callingPackage,
3849 cla, command, p1, p2, p3, data);
3850 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003851
Jordan Liu4c733742019-02-28 12:03:40 -08003852 @Override
3853 public String iccTransmitApduBasicChannelBySlot(int slotIndex, String callingPackage, int cla,
3854 int command, int p1, int p2, int p3, String data) {
3855 enforceModifyPermission();
3856 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
3857 if (DBG) {
3858 log("iccTransmitApduBasicChannelBySlot: slotIndex=" + slotIndex + " cla=" + cla
3859 + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3
3860 + " data=" + data);
3861 }
3862
3863 return iccTransmitApduBasicChannelWithPermission(
3864 getPhoneFromSlotIdOrThrowException(slotIndex), callingPackage, cla, command, p1,
3865 p2, p3, data);
3866 }
3867
3868 // open APDU basic channel assuming the caller has sufficient permissions
3869 private String iccTransmitApduBasicChannelWithPermission(Phone phone, String callingPackage,
3870 int cla, int command, int p1, int p2, int p3, String data) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003871 final long identity = Binder.clearCallingIdentity();
3872 try {
3873 if (command == SELECT_COMMAND && p1 == SELECT_P1 && p2 == SELECT_P2 && p3 == SELECT_P3
3874 && TextUtils.equals(ISDR_AID, data)) {
3875 // Only allows LPA to select ISD-R.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003876 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
3877 .getContext().getPackageManager());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003878 if (bestComponent == null
3879 || !TextUtils.equals(callingPackage, bestComponent.packageName)) {
3880 loge("The calling package is not allowed to select ISD-R.");
3881 throw new SecurityException(
3882 "The calling package is not allowed to select ISD-R.");
3883 }
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08003884 }
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08003885
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003886 IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
Jordan Liu4c733742019-02-28 12:03:40 -08003887 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), phone,
3888 null /* workSource */);
3889 if (DBG) log("iccTransmitApduBasicChannelWithPermission: " + response);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003890
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003891 // Append the returned status code to the end of the response payload.
3892 String s = Integer.toHexString(
3893 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
3894 if (response.payload != null) {
3895 s = IccUtils.bytesToHexString(response.payload) + s;
3896 }
3897 return s;
3898 } finally {
3899 Binder.restoreCallingIdentity(identity);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07003900 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003901 }
3902
3903 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003904 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003905 String filePath) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003906 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3907 mApp, subId, "iccExchangeSimIO");
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003908
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003909 final long identity = Binder.clearCallingIdentity();
3910 try {
3911 if (DBG) {
3912 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " "
3913 + p1 + " " + p2 + " " + p3 + ":" + filePath);
3914 }
3915
3916 IccIoResult response =
3917 (IccIoResult) sendRequest(CMD_EXCHANGE_SIM_IO,
3918 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
3919 subId);
3920
3921 if (DBG) {
3922 log("Exchange SIM_IO [R]" + response);
3923 }
3924
3925 byte[] result = null;
3926 int length = 2;
3927 if (response.payload != null) {
3928 length = 2 + response.payload.length;
3929 result = new byte[length];
3930 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
3931 } else {
3932 result = new byte[length];
3933 }
3934
3935 result[length - 1] = (byte) response.sw2;
3936 result[length - 2] = (byte) response.sw1;
3937 return result;
3938 } finally {
3939 Binder.restoreCallingIdentity(identity);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003940 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003941 }
3942
Nathan Haroldb3014052017-01-25 15:57:32 -08003943 /**
3944 * Get the forbidden PLMN List from the given app type (ex APPTYPE_USIM)
3945 * on a particular subscription
3946 */
sqianb6e41952018-03-12 14:54:01 -07003947 public String[] getForbiddenPlmns(int subId, int appType, String callingPackage) {
3948 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
3949 mApp, subId, callingPackage, "getForbiddenPlmns")) {
3950 return null;
3951 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003952
3953 final long identity = Binder.clearCallingIdentity();
3954 try {
3955 if (appType != TelephonyManager.APPTYPE_USIM
3956 && appType != TelephonyManager.APPTYPE_SIM) {
3957 loge("getForbiddenPlmnList(): App Type must be USIM or SIM");
3958 return null;
3959 }
3960 Object response = sendRequest(
3961 CMD_GET_FORBIDDEN_PLMNS, new Integer(appType), subId);
3962 if (response instanceof String[]) {
3963 return (String[]) response;
3964 }
3965 // Response is an Exception of some kind,
3966 // which is signalled to the user as a NULL retval
Nathan Haroldb3014052017-01-25 15:57:32 -08003967 return null;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003968 } finally {
3969 Binder.restoreCallingIdentity(identity);
Nathan Haroldb3014052017-01-25 15:57:32 -08003970 }
Nathan Haroldb3014052017-01-25 15:57:32 -08003971 }
3972
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07003973 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003974 public String sendEnvelopeWithStatus(int subId, String content) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003975 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
3976 mApp, subId, "sendEnvelopeWithStatus");
Evan Charltonc66da362014-05-16 14:06:40 -07003977
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003978 final long identity = Binder.clearCallingIdentity();
3979 try {
3980 IccIoResult response = (IccIoResult) sendRequest(CMD_SEND_ENVELOPE, content, subId);
3981 if (response.payload == null) {
3982 return "";
3983 }
Evan Charltonc66da362014-05-16 14:06:40 -07003984
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003985 // Append the returned status code to the end of the response payload.
3986 String s = Integer.toHexString(
3987 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
3988 s = IccUtils.bytesToHexString(response.payload) + s;
3989 return s;
3990 } finally {
3991 Binder.restoreCallingIdentity(identity);
3992 }
Evan Charltonc66da362014-05-16 14:06:40 -07003993 }
3994
Jake Hambye994d462014-02-03 13:10:13 -08003995 /**
3996 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
3997 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
3998 *
3999 * @param itemID the ID of the item to read
4000 * @return the NV item as a String, or null on error.
4001 */
4002 @Override
4003 public String nvReadItem(int itemID) {
vagdeviaf9a5b92018-08-15 16:01:53 -07004004 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Jeff Davidson7e17e312018-02-13 18:17:36 -08004005 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4006 mApp, getDefaultSubscription(), "nvReadItem");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004007
4008 final long identity = Binder.clearCallingIdentity();
4009 try {
4010 if (DBG) log("nvReadItem: item " + itemID);
vagdeviaf9a5b92018-08-15 16:01:53 -07004011 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004012 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
4013 return value;
4014 } finally {
4015 Binder.restoreCallingIdentity(identity);
4016 }
Jake Hambye994d462014-02-03 13:10:13 -08004017 }
4018
4019 /**
4020 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
4021 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
4022 *
4023 * @param itemID the ID of the item to read
4024 * @param itemValue the value to write, as a String
4025 * @return true on success; false on any failure
4026 */
4027 @Override
4028 public boolean nvWriteItem(int itemID, String itemValue) {
vagdeviaf9a5b92018-08-15 16:01:53 -07004029 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Jeff Davidson7e17e312018-02-13 18:17:36 -08004030 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4031 mApp, getDefaultSubscription(), "nvWriteItem");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004032
4033 final long identity = Binder.clearCallingIdentity();
4034 try {
4035 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
4036 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
vagdeviaf9a5b92018-08-15 16:01:53 -07004037 new Pair<Integer, String>(itemID, itemValue), workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004038 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
4039 return success;
4040 } finally {
4041 Binder.restoreCallingIdentity(identity);
4042 }
Jake Hambye994d462014-02-03 13:10:13 -08004043 }
4044
4045 /**
4046 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
4047 * Used for device configuration by some CDMA operators.
4048 *
4049 * @param preferredRoamingList byte array containing the new PRL
4050 * @return true on success; false on any failure
4051 */
4052 @Override
4053 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004054 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4055 mApp, getDefaultSubscription(), "nvWriteCdmaPrl");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004056
4057 final long identity = Binder.clearCallingIdentity();
4058 try {
4059 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
4060 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
4061 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
4062 return success;
4063 } finally {
4064 Binder.restoreCallingIdentity(identity);
4065 }
Jake Hambye994d462014-02-03 13:10:13 -08004066 }
4067
4068 /**
chen xu6dac5ab2018-10-26 17:39:23 -07004069 * Rollback modem configurations to factory default except some config which are in whitelist.
Jake Hambye994d462014-02-03 13:10:13 -08004070 * Used for device configuration by some CDMA operators.
4071 *
chen xu6dac5ab2018-10-26 17:39:23 -07004072 * @param slotIndex - device slot.
4073 *
Jake Hambye994d462014-02-03 13:10:13 -08004074 * @return true on success; false on any failure
4075 */
4076 @Override
chen xu6dac5ab2018-10-26 17:39:23 -07004077 public boolean resetModemConfig(int slotIndex) {
4078 Phone phone = PhoneFactory.getPhone(slotIndex);
4079 if (phone != null) {
4080 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4081 mApp, phone.getSubId(), "resetModemConfig");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004082
chen xu6dac5ab2018-10-26 17:39:23 -07004083 final long identity = Binder.clearCallingIdentity();
4084 try {
4085 Boolean success = (Boolean) sendRequest(CMD_RESET_MODEM_CONFIG, null);
4086 if (DBG) log("resetModemConfig:" + ' ' + (success ? "ok" : "fail"));
4087 return success;
4088 } finally {
4089 Binder.restoreCallingIdentity(identity);
4090 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004091 }
chen xu6dac5ab2018-10-26 17:39:23 -07004092 return false;
4093 }
4094
4095 /**
4096 * Generate a radio modem reset. Used for device configuration by some CDMA operators.
4097 *
4098 * @param slotIndex - device slot.
4099 *
4100 * @return true on success; false on any failure
4101 */
4102 @Override
4103 public boolean rebootModem(int slotIndex) {
4104 Phone phone = PhoneFactory.getPhone(slotIndex);
4105 if (phone != null) {
4106 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4107 mApp, phone.getSubId(), "rebootModem");
4108
4109 final long identity = Binder.clearCallingIdentity();
4110 try {
4111 Boolean success = (Boolean) sendRequest(CMD_MODEM_REBOOT, null);
4112 if (DBG) log("rebootModem:" + ' ' + (success ? "ok" : "fail"));
4113 return success;
4114 } finally {
4115 Binder.restoreCallingIdentity(identity);
4116 }
4117 }
4118 return false;
Jake Hambye994d462014-02-03 13:10:13 -08004119 }
Jake Hamby7c27be32014-03-03 13:25:59 -08004120
Svet Ganovb320e182015-04-16 12:30:10 -07004121 public String[] getPcscfAddress(String apnType, String callingPackage) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004122 final Phone defaultPhone = getDefaultPhone();
Jeff Davidson7e17e312018-02-13 18:17:36 -08004123 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004124 mApp, defaultPhone.getSubId(), callingPackage, "getPcscfAddress")) {
Svet Ganovb320e182015-04-16 12:30:10 -07004125 return new String[0];
4126 }
4127
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004128 final long identity = Binder.clearCallingIdentity();
4129 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004130 return defaultPhone.getPcscfAddress(apnType);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004131 } finally {
4132 Binder.restoreCallingIdentity(identity);
4133 }
Wink Saville36469e72014-06-11 15:17:00 -07004134 }
4135
Brad Ebinger51f743a2017-01-23 13:50:20 -08004136 /**
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004137 * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
4138 * status updates, if not already enabled.
Brad Ebinger51f743a2017-01-23 13:50:20 -08004139 */
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004140 public void enableIms(int slotId) {
Brad Ebinger51f743a2017-01-23 13:50:20 -08004141 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004142
4143 final long identity = Binder.clearCallingIdentity();
4144 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004145 ImsResolver resolver = PhoneFactory.getImsResolver();
4146 if (resolver == null) {
4147 // may happen if the device does not support IMS.
4148 return;
4149 }
4150 resolver.enableIms(slotId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004151 } finally {
4152 Binder.restoreCallingIdentity(identity);
4153 }
Brad Ebinger34bef922017-11-09 10:27:08 -08004154 }
4155
4156 /**
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004157 * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature
4158 * status updates to disabled.
Brad Ebinger34bef922017-11-09 10:27:08 -08004159 */
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004160 public void disableIms(int slotId) {
4161 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004162
4163 final long identity = Binder.clearCallingIdentity();
4164 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004165 ImsResolver resolver = PhoneFactory.getImsResolver();
4166 if (resolver == null) {
4167 // may happen if the device does not support IMS.
4168 return;
4169 }
4170 resolver.disableIms(slotId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004171 } finally {
4172 Binder.restoreCallingIdentity(identity);
4173 }
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004174 }
4175
4176 /**
4177 * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id for the MMTel
4178 * feature or {@link null} if the service is not available. If the feature is available, the
4179 * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
4180 */
4181 public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
Brad Ebinger34bef922017-11-09 10:27:08 -08004182 IImsServiceFeatureCallback callback) {
4183 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004184
4185 final long identity = Binder.clearCallingIdentity();
4186 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004187 ImsResolver resolver = PhoneFactory.getImsResolver();
4188 if (resolver == null) {
4189 // may happen if the device does not support IMS.
4190 return null;
4191 }
4192 return resolver.getMmTelFeatureAndListen(slotId, callback);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004193 } finally {
4194 Binder.restoreCallingIdentity(identity);
4195 }
Brad Ebinger34bef922017-11-09 10:27:08 -08004196 }
4197
4198 /**
4199 * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for the RCS
4200 * feature during emergency calling or {@link null} if the service is not available. If the
4201 * feature is available, the {@link IImsServiceFeatureCallback} callback is registered as a
4202 * listener for feature updates.
4203 */
4204 public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
4205 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004206
4207 final long identity = Binder.clearCallingIdentity();
4208 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004209 ImsResolver resolver = PhoneFactory.getImsResolver();
4210 if (resolver == null) {
4211 // may happen if the device does not support IMS.
4212 return null;
4213 }
4214 return resolver.getRcsFeatureAndListen(slotId, callback);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004215 } finally {
4216 Binder.restoreCallingIdentity(identity);
4217 }
Brad Ebinger51f743a2017-01-23 13:50:20 -08004218 }
4219
Brad Ebinger5f64b052017-12-14 14:26:15 -08004220 /**
4221 * Returns the {@link IImsRegistration} structure associated with the slotId and feature
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004222 * specified or null if IMS is not supported on the slot specified.
Brad Ebinger5f64b052017-12-14 14:26:15 -08004223 */
4224 public IImsRegistration getImsRegistration(int slotId, int feature) throws RemoteException {
4225 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004226
4227 final long identity = Binder.clearCallingIdentity();
4228 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004229 ImsResolver resolver = PhoneFactory.getImsResolver();
4230 if (resolver == null) {
4231 // may happen if the device does not support IMS.
4232 return null;
4233 }
4234 return resolver.getImsRegistration(slotId, feature);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004235 } finally {
4236 Binder.restoreCallingIdentity(identity);
4237 }
Brad Ebinger5f64b052017-12-14 14:26:15 -08004238 }
4239
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004240 /**
4241 * Returns the {@link IImsConfig} structure associated with the slotId and feature
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004242 * specified or null if IMS is not supported on the slot specified.
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004243 */
4244 public IImsConfig getImsConfig(int slotId, int feature) throws RemoteException {
4245 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004246
4247 final long identity = Binder.clearCallingIdentity();
4248 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004249 ImsResolver resolver = PhoneFactory.getImsResolver();
4250 if (resolver == null) {
4251 // may happen if the device does not support IMS.
4252 return null;
4253 }
4254 return resolver.getImsConfig(slotId, feature);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004255 } finally {
4256 Binder.restoreCallingIdentity(identity);
4257 }
Brad Ebinger22bc3e42018-01-16 09:39:35 -08004258 }
4259
Brad Ebinger884c07b2018-02-15 16:17:40 -08004260 /**
Brad Ebingerdac2f002018-04-03 15:17:52 -07004261 * Sets the ImsService Package Name that Telephony will bind to.
4262 *
4263 * @param slotId the slot ID that the ImsService should bind for.
4264 * @param isCarrierImsService true if the ImsService is the carrier override, false if the
4265 * ImsService is the device default ImsService.
4266 * @param packageName The package name of the application that contains the ImsService to bind
4267 * to.
4268 * @return true if setting the ImsService to bind to succeeded, false if it did not.
4269 * @hide
4270 */
4271 public boolean setImsService(int slotId, boolean isCarrierImsService, String packageName) {
Brad Ebingerde696de2018-04-06 09:56:40 -07004272 int[] subIds = SubscriptionManager.getSubId(slotId);
4273 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
4274 (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
4275 "setImsService");
4276
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004277 final long identity = Binder.clearCallingIdentity();
4278 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004279 ImsResolver resolver = PhoneFactory.getImsResolver();
4280 if (resolver == null) {
4281 // may happen if the device does not support IMS.
4282 return false;
4283 }
4284 return resolver.overrideImsServiceConfiguration(slotId, isCarrierImsService,
4285 packageName);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004286 } finally {
4287 Binder.restoreCallingIdentity(identity);
4288 }
Brad Ebingerdac2f002018-04-03 15:17:52 -07004289 }
4290
4291 /**
4292 * Return the ImsService configuration.
4293 *
4294 * @param slotId The slot that the ImsService is associated with.
4295 * @param isCarrierImsService true, if the ImsService is a carrier override, false if it is
4296 * the device default.
4297 * @return the package name of the ImsService configuration.
4298 */
4299 public String getImsService(int slotId, boolean isCarrierImsService) {
Brad Ebingerde696de2018-04-06 09:56:40 -07004300 int[] subIds = SubscriptionManager.getSubId(slotId);
4301 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
4302 (subIds != null ? subIds[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID),
4303 "getImsService");
4304
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004305 final long identity = Binder.clearCallingIdentity();
4306 try {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08004307 ImsResolver resolver = PhoneFactory.getImsResolver();
4308 if (resolver == null) {
4309 // may happen if the device does not support IMS.
4310 return "";
4311 }
4312 return resolver.getImsServiceConfiguration(slotId, isCarrierImsService);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004313 } finally {
4314 Binder.restoreCallingIdentity(identity);
4315 }
Brad Ebingerdac2f002018-04-03 15:17:52 -07004316 }
4317
Wink Saville36469e72014-06-11 15:17:00 -07004318 public void setImsRegistrationState(boolean registered) {
4319 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004320
4321 final long identity = Binder.clearCallingIdentity();
4322 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004323 getDefaultPhone().setImsRegistrationState(registered);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004324 } finally {
4325 Binder.restoreCallingIdentity(identity);
4326 }
Wink Saville36469e72014-06-11 15:17:00 -07004327 }
4328
4329 /**
Stuart Scott54788802015-03-30 13:18:01 -07004330 * Set the network selection mode to automatic.
4331 *
4332 */
4333 @Override
4334 public void setNetworkSelectionModeAutomatic(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004335 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4336 mApp, subId, "setNetworkSelectionModeAutomatic");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004337
Pengquan Menge92a50d2018-09-21 15:54:48 -07004338 if (!isActiveSubscription(subId)) {
4339 return;
4340 }
4341
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004342 final long identity = Binder.clearCallingIdentity();
4343 try {
4344 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
4345 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
4346 } finally {
4347 Binder.restoreCallingIdentity(identity);
4348 }
Stuart Scott54788802015-03-30 13:18:01 -07004349 }
4350
Pengquan Mengea84e042018-09-20 14:57:26 -07004351 /**
4352 * Ask the radio to connect to the input network and change selection mode to manual.
4353 *
4354 * @param subId the id of the subscription.
4355 * @param operatorInfo the operator information, included the PLMN, long name and short name of
4356 * the operator to attach to.
4357 * @param persistSelection whether the selection will persist until reboot. If true, only allows
4358 * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
4359 * normal network selection next time.
4360 * @return {@code true} on success; {@code true} on any failure.
Shishir Agrawal302c8692015-06-19 13:49:39 -07004361 */
4362 @Override
Pengquan Mengea84e042018-09-20 14:57:26 -07004363 public boolean setNetworkSelectionModeManual(
4364 int subId, OperatorInfo operatorInfo, boolean persistSelection) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004365 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4366 mApp, subId, "setNetworkSelectionModeManual");
Pengquan Menge92a50d2018-09-21 15:54:48 -07004367
4368 if (!isActiveSubscription(subId)) {
4369 return false;
4370 }
4371
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004372 final long identity = Binder.clearCallingIdentity();
4373 try {
Pengquan Mengea84e042018-09-20 14:57:26 -07004374 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operatorInfo,
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004375 persistSelection);
Pengquan Mengea84e042018-09-20 14:57:26 -07004376 if (DBG) {
4377 log("setNetworkSelectionModeManual: subId: " + subId
4378 + " operator: " + operatorInfo);
4379 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004380 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
4381 } finally {
4382 Binder.restoreCallingIdentity(identity);
4383 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07004384 }
4385
4386 /**
4387 * Scans for available networks.
4388 */
4389 @Override
Hall Liuf19c44f2018-11-27 14:38:17 -08004390 public CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004391 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4392 mApp, subId, "getCellNetworkScanResults");
Hall Liuf19c44f2018-11-27 14:38:17 -08004393 LocationAccessPolicy.LocationPermissionResult locationResult =
4394 LocationAccessPolicy.checkLocationPermission(mApp,
4395 new LocationAccessPolicy.LocationPermissionQuery.Builder()
4396 .setCallingPackage(callingPackage)
4397 .setCallingPid(Binder.getCallingPid())
4398 .setCallingUid(Binder.getCallingUid())
4399 .setMethod("getCellNetworkScanResults")
4400 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
4401 .build());
4402 switch (locationResult) {
4403 case DENIED_HARD:
4404 throw new SecurityException("Not allowed to access scan results -- location");
4405 case DENIED_SOFT:
4406 return null;
4407 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004408
Pengquan Menga1bb6272018-09-06 09:59:22 -07004409 long identity = Binder.clearCallingIdentity();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004410 try {
4411 if (DBG) log("getCellNetworkScanResults: subId " + subId);
Pengquan Menga1bb6272018-09-06 09:59:22 -07004412 return (CellNetworkScanResult) sendRequest(
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004413 CMD_PERFORM_NETWORK_SCAN, null, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004414 } finally {
4415 Binder.restoreCallingIdentity(identity);
4416 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07004417 }
4418
4419 /**
yinxub1bed742017-04-17 11:45:04 -07004420 * Starts a new network scan and returns the id of this scan.
yinxu504e1392017-04-12 16:03:22 -07004421 *
yinxub1bed742017-04-17 11:45:04 -07004422 * @param subId id of the subscription
4423 * @param request contains the radio access networks with bands/channels to scan
4424 * @param messenger callback messenger for scan results or errors
4425 * @param binder for the purpose of auto clean when the user thread crashes
yinxu504e1392017-04-12 16:03:22 -07004426 * @return the id of the requested scan which can be used to stop the scan.
4427 */
4428 @Override
4429 public int requestNetworkScan(int subId, NetworkScanRequest request, Messenger messenger,
Hall Liuf19c44f2018-11-27 14:38:17 -08004430 IBinder binder, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004431 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4432 mApp, subId, "requestNetworkScan");
Hall Liuf19c44f2018-11-27 14:38:17 -08004433 LocationAccessPolicy.LocationPermissionResult locationResult =
4434 LocationAccessPolicy.checkLocationPermission(mApp,
4435 new LocationAccessPolicy.LocationPermissionQuery.Builder()
4436 .setCallingPackage(callingPackage)
4437 .setCallingPid(Binder.getCallingPid())
4438 .setCallingUid(Binder.getCallingUid())
4439 .setMethod("requestNetworkScan")
4440 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
4441 .build());
Hall Liub2ac8ef2019-02-28 15:56:23 -08004442 if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
4443 SecurityException e = checkNetworkRequestForSanitizedLocationAccess(request);
4444 if (e != null) {
4445 if (locationResult == LocationAccessPolicy.LocationPermissionResult.DENIED_HARD) {
4446 throw e;
4447 } else {
4448 return TelephonyScanManager.INVALID_SCAN_ID;
4449 }
4450 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004451 }
Hall Liuf19c44f2018-11-27 14:38:17 -08004452 return mNetworkScanRequestTracker.startNetworkScan(
4453 request, messenger, binder, getPhone(subId),
4454 callingPackage);
yinxu504e1392017-04-12 16:03:22 -07004455 }
4456
Hall Liub2ac8ef2019-02-28 15:56:23 -08004457 private SecurityException checkNetworkRequestForSanitizedLocationAccess(
4458 NetworkScanRequest request) {
4459 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
4460 != PERMISSION_GRANTED) {
4461 return new SecurityException("permission.NETWORK_SCAN is needed for network scans"
4462 + " without location access.");
4463 }
4464
4465 if (request.getSpecifiers() != null && request.getSpecifiers().length > 0) {
4466 for (RadioAccessSpecifier ras : request.getSpecifiers()) {
4467 if (ras.getBands() != null && ras.getBands().length > 0) {
4468 return new SecurityException("Specific bands must not be"
4469 + " scanned without location access.");
4470 }
4471 if (ras.getChannels() != null && ras.getChannels().length > 0) {
4472 return new SecurityException("Specific channels must not be"
4473 + " scanned without location access.");
4474 }
4475 }
4476 }
4477
Brad Ebinger798b2f02019-04-09 18:31:18 -07004478 // STOPSHIP Revisit PLMN check (b/130253962).
4479 //List<String> allowedMccMncs =
4480 // NetworkScanRequestTracker.getAllowedMccMncsForLocationRestrictedScan(mApp);
4481 //for (String mccmnc : request.getPlmns()) {
4482 // if (!allowedMccMncs.contains(mccmnc)) {
4483 // return new SecurityException("Requested mccmnc " + mccmnc + " is not known to the"
4484 // + " device and cannot be scanned for without location access.");
4485 // }
4486 //}
Hall Liub2ac8ef2019-02-28 15:56:23 -08004487
4488 return null;
4489 }
4490
yinxu504e1392017-04-12 16:03:22 -07004491 /**
4492 * Stops an existing network scan with the given scanId.
yinxub1bed742017-04-17 11:45:04 -07004493 *
4494 * @param subId id of the subscription
4495 * @param scanId id of the scan that needs to be stopped
yinxu504e1392017-04-12 16:03:22 -07004496 */
4497 @Override
4498 public void stopNetworkScan(int subId, int scanId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004499 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4500 mApp, subId, "stopNetworkScan");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004501
4502 final long identity = Binder.clearCallingIdentity();
4503 try {
4504 mNetworkScanRequestTracker.stopNetworkScan(scanId);
4505 } finally {
4506 Binder.restoreCallingIdentity(identity);
4507 }
yinxu504e1392017-04-12 16:03:22 -07004508 }
4509
4510 /**
Junda Liu84d15a22014-07-02 11:21:04 -07004511 * Get the calculated preferred network type.
4512 * Used for debugging incorrect network type.
4513 *
4514 * @return the preferred network type, defined in RILConstants.java.
4515 */
4516 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07004517 public int getCalculatedPreferredNetworkType(String callingPackage) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004518 final Phone defaultPhone = getDefaultPhone();
4519 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
4520 callingPackage, "getCalculatedPreferredNetworkType")) {
Svet Ganovb320e182015-04-16 12:30:10 -07004521 return RILConstants.PREFERRED_NETWORK_MODE;
4522 }
4523
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004524 final long identity = Binder.clearCallingIdentity();
4525 try {
4526 // FIXME: need to get SubId from somewhere.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004527 return PhoneFactory.calculatePreferredNetworkType(defaultPhone.getContext(), 0);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004528 } finally {
4529 Binder.restoreCallingIdentity(identity);
4530 }
Junda Liu84d15a22014-07-02 11:21:04 -07004531 }
4532
4533 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08004534 * Get the preferred network type.
4535 * Used for device configuration by some CDMA operators.
4536 *
4537 * @return the preferred network type, defined in RILConstants.java.
4538 */
4539 @Override
Stuart Scott54788802015-03-30 13:18:01 -07004540 public int getPreferredNetworkType(int subId) {
Pengquan Menga4009cb2018-12-20 11:00:24 -08004541 TelephonyPermissions
4542 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
4543 mApp, subId, "getPreferredNetworkType");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004544
4545 final long identity = Binder.clearCallingIdentity();
4546 try {
4547 if (DBG) log("getPreferredNetworkType");
4548 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
4549 int networkType = (result != null ? result[0] : -1);
4550 if (DBG) log("getPreferredNetworkType: " + networkType);
4551 return networkType;
4552 } finally {
4553 Binder.restoreCallingIdentity(identity);
4554 }
Jake Hamby7c27be32014-03-03 13:25:59 -08004555 }
4556
4557 /**
4558 * Set the preferred network type.
4559 * Used for device configuration by some CDMA operators.
4560 *
4561 * @param networkType the preferred network type, defined in RILConstants.java.
4562 * @return true on success; false on any failure.
4563 */
4564 @Override
Stuart Scott54788802015-03-30 13:18:01 -07004565 public boolean setPreferredNetworkType(int subId, int networkType) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004566 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4567 mApp, subId, "setPreferredNetworkType");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004568
4569 final long identity = Binder.clearCallingIdentity();
4570 try {
4571 if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
4572 Boolean success = (Boolean) sendRequest(
4573 CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
4574 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
4575 if (success) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004576 Settings.Global.putInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004577 Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
4578 }
4579 return success;
4580 } finally {
4581 Binder.restoreCallingIdentity(identity);
Junda Liu80bc0d12014-07-14 16:36:44 -07004582 }
Jake Hamby7c27be32014-03-03 13:25:59 -08004583 }
Robert Greenwalted86e582014-05-21 20:03:20 -07004584
4585 /**
Miaoa84611c2019-03-15 09:21:10 +08004586 * Check whether DUN APN is required for tethering with subId.
Junda Liu475951f2014-11-07 16:45:03 -08004587 *
Miaoa84611c2019-03-15 09:21:10 +08004588 * @param subId the id of the subscription to require tethering.
Amit Mahajanfe58cdf2017-07-11 12:01:53 -07004589 * @return {@code true} if DUN APN is required for tethering.
Junda Liu475951f2014-11-07 16:45:03 -08004590 * @hide
4591 */
4592 @Override
Miaoa84611c2019-03-15 09:21:10 +08004593 public boolean getTetherApnRequiredForSubscriber(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08004594 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004595 final long identity = Binder.clearCallingIdentity();
Miaoa84611c2019-03-15 09:21:10 +08004596 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004597 try {
Miaoa84611c2019-03-15 09:21:10 +08004598 if (phone != null) {
4599 return phone.hasMatchedTetherApnSetting();
4600 } else {
4601 return false;
4602 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004603 } finally {
4604 Binder.restoreCallingIdentity(identity);
Junda Liu475951f2014-11-07 16:45:03 -08004605 }
Junda Liu475951f2014-11-07 16:45:03 -08004606 }
4607
4608 /**
Robert Greenwalted86e582014-05-21 20:03:20 -07004609 * Set mobile data enabled
4610 * Used by the user through settings etc to turn on/off mobile data
4611 *
4612 * @param enable {@code true} turn turn data on, else {@code false}
4613 */
4614 @Override
Malcolm Chen964682d2017-11-28 16:20:07 -08004615 public void setUserDataEnabled(int subId, boolean enable) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004616 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4617 mApp, subId, "setUserDataEnabled");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004618
4619 final long identity = Binder.clearCallingIdentity();
4620 try {
4621 int phoneId = mSubscriptionController.getPhoneId(subId);
4622 if (DBG) log("setUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
4623 Phone phone = PhoneFactory.getPhone(phoneId);
4624 if (phone != null) {
4625 if (DBG) log("setUserDataEnabled: subId=" + subId + " enable=" + enable);
Jack Yud79fba22018-12-13 11:51:28 -08004626 phone.getDataEnabledSettings().setUserDataEnabled(enable);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004627 } else {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004628 loge("setUserDataEnabled: no phone found. Invalid subId=" + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004629 }
4630 } finally {
4631 Binder.restoreCallingIdentity(identity);
Wink Savillee7353bb2014-12-05 14:21:41 -08004632 }
Robert Greenwalted86e582014-05-21 20:03:20 -07004633 }
4634
4635 /**
Malcolm Chen964682d2017-11-28 16:20:07 -08004636 * Get the user enabled state of Mobile Data.
4637 *
4638 * TODO: remove and use isUserDataEnabled.
4639 * This can't be removed now because some vendor codes
4640 * calls through ITelephony directly while they should
4641 * use TelephonyManager.
4642 *
4643 * @return true on enabled
4644 */
4645 @Override
4646 public boolean getDataEnabled(int subId) {
4647 return isUserDataEnabled(subId);
4648 }
4649
4650 /**
4651 * Get whether mobile data is enabled per user setting.
4652 *
4653 * There are other factors deciding whether mobile data is actually enabled, but they are
4654 * not considered here. See {@link #isDataEnabled(int)} for more details.
Robert Greenwalt646120a2014-05-23 11:54:03 -07004655 *
Jeff Davidsona1920712016-11-18 17:05:56 -08004656 * Accepts either ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE or carrier privileges.
Robert Greenwalted86e582014-05-21 20:03:20 -07004657 *
4658 * @return {@code true} if data is enabled else {@code false}
4659 */
4660 @Override
Malcolm Chen964682d2017-11-28 16:20:07 -08004661 public boolean isUserDataEnabled(int subId) {
Robert Greenwalt646120a2014-05-23 11:54:03 -07004662 try {
4663 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
4664 null);
4665 } catch (Exception e) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004666 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4667 mApp, subId, "isUserDataEnabled");
Robert Greenwalt646120a2014-05-23 11:54:03 -07004668 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004669
4670 final long identity = Binder.clearCallingIdentity();
4671 try {
4672 int phoneId = mSubscriptionController.getPhoneId(subId);
4673 if (DBG) log("isUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
4674 Phone phone = PhoneFactory.getPhone(phoneId);
4675 if (phone != null) {
4676 boolean retVal = phone.isUserDataEnabled();
4677 if (DBG) log("isUserDataEnabled: subId=" + subId + " retVal=" + retVal);
4678 return retVal;
4679 } else {
4680 if (DBG) loge("isUserDataEnabled: no phone subId=" + subId + " retVal=false");
4681 return false;
4682 }
4683 } finally {
4684 Binder.restoreCallingIdentity(identity);
Malcolm Chen964682d2017-11-28 16:20:07 -08004685 }
4686 }
4687
4688 /**
4689 * Get whether mobile data is enabled.
4690 *
4691 * Comparable to {@link #isUserDataEnabled(int)}, this considers all factors deciding
4692 * whether mobile data is actually enabled.
4693 *
4694 * Accepts either ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE or carrier privileges.
4695 *
4696 * @return {@code true} if data is enabled else {@code false}
4697 */
4698 @Override
4699 public boolean isDataEnabled(int subId) {
4700 try {
4701 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
4702 null);
4703 } catch (Exception e) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004704 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4705 mApp, subId, "isDataEnabled");
Malcolm Chen964682d2017-11-28 16:20:07 -08004706 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004707
4708 final long identity = Binder.clearCallingIdentity();
4709 try {
4710 int phoneId = mSubscriptionController.getPhoneId(subId);
4711 if (DBG) log("isDataEnabled: subId=" + subId + " phoneId=" + phoneId);
4712 Phone phone = PhoneFactory.getPhone(phoneId);
4713 if (phone != null) {
Jack Yud79fba22018-12-13 11:51:28 -08004714 boolean retVal = phone.getDataEnabledSettings().isDataEnabled();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004715 if (DBG) log("isDataEnabled: subId=" + subId + " retVal=" + retVal);
4716 return retVal;
4717 } else {
4718 if (DBG) loge("isDataEnabled: no phone subId=" + subId + " retVal=false");
4719 return false;
4720 }
4721 } finally {
4722 Binder.restoreCallingIdentity(identity);
Wink Savillee7353bb2014-12-05 14:21:41 -08004723 }
Robert Greenwalted86e582014-05-21 20:03:20 -07004724 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07004725
4726 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08004727 public int getCarrierPrivilegeStatus(int subId) {
4728 final Phone phone = getPhone(subId);
4729 if (phone == null) {
4730 loge("getCarrierPrivilegeStatus: Invalid subId");
4731 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
4732 }
4733 UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07004734 if (card == null) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08004735 loge("getCarrierPrivilegeStatus: No UICC");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07004736 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
4737 }
4738 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalc04d9752016-02-19 10:41:00 -08004739 phone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07004740 }
Junda Liu29340342014-07-10 15:23:27 -07004741
4742 @Override
Jeff Davidson7e17e312018-02-13 18:17:36 -08004743 public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
4744 final Phone phone = getPhone(subId);
4745 if (phone == null) {
4746 loge("getCarrierPrivilegeStatus: Invalid subId");
4747 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
4748 }
4749 UiccProfile profile =
4750 UiccController.getInstance().getUiccProfileForPhone(phone.getPhoneId());
4751 if (profile == null) {
4752 loge("getCarrierPrivilegeStatus: No UICC");
4753 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
4754 }
4755 return profile.getCarrierPrivilegeStatusForUid(phone.getContext().getPackageManager(), uid);
4756 }
4757
4758 @Override
Zach Johnson50ecba32015-05-19 00:24:21 -07004759 public int checkCarrierPrivilegesForPackage(String pkgName) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004760 final Phone defaultPhone = getDefaultPhone();
Junda Liu317d70b2016-03-08 09:33:53 -08004761 if (TextUtils.isEmpty(pkgName))
4762 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004763 UiccCard card = UiccController.getInstance().getUiccCard(defaultPhone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07004764 if (card == null) {
4765 loge("checkCarrierPrivilegesForPackage: No UICC");
4766 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
4767 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004768 return card.getCarrierPrivilegeStatus(defaultPhone.getContext().getPackageManager(),
4769 pkgName);
Zach Johnson50ecba32015-05-19 00:24:21 -07004770 }
4771
4772 @Override
4773 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08004774 if (TextUtils.isEmpty(pkgName))
4775 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Zach Johnson50ecba32015-05-19 00:24:21 -07004776 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
4777 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
4778 UiccCard card = UiccController.getInstance().getUiccCard(i);
4779 if (card == null) {
Jonathan Basseri7d320df2015-06-16 12:17:08 -07004780 // No UICC in that slot.
Zach Johnson50ecba32015-05-19 00:24:21 -07004781 continue;
4782 }
4783
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004784 result = card.getCarrierPrivilegeStatus(mApp.getPackageManager(), pkgName);
Zach Johnson50ecba32015-05-19 00:24:21 -07004785 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
4786 break;
4787 }
4788 }
4789
4790 return result;
Junda Liu29340342014-07-10 15:23:27 -07004791 }
Derek Tan89e89d42014-07-08 17:00:10 -07004792
4793 @Override
Junda Liue64de782015-04-16 17:19:16 -07004794 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
4795 if (!SubscriptionManager.isValidPhoneId(phoneId)) {
4796 loge("phoneId " + phoneId + " is not valid.");
4797 return null;
4798 }
4799 UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07004800 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07004801 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07004802 return null ;
4803 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004804 return card.getCarrierPackageNamesForIntent(mApp.getPackageManager(), intent);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07004805 }
4806
Amith Yamasani6e118872016-02-19 12:53:51 -08004807 @Override
4808 public List<String> getPackagesWithCarrierPrivileges() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004809 PackageManager pm = mApp.getPackageManager();
Amith Yamasani6e118872016-02-19 12:53:51 -08004810 List<String> privilegedPackages = new ArrayList<>();
4811 List<PackageInfo> packages = null;
4812 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
4813 UiccCard card = UiccController.getInstance().getUiccCard(i);
4814 if (card == null) {
4815 // No UICC in that slot.
4816 continue;
4817 }
4818 if (card.hasCarrierPrivilegeRules()) {
4819 if (packages == null) {
4820 // Only check packages in user 0 for now
4821 packages = pm.getInstalledPackagesAsUser(
4822 PackageManager.MATCH_DISABLED_COMPONENTS
4823 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
4824 | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
4825 }
4826 for (int p = packages.size() - 1; p >= 0; p--) {
4827 PackageInfo pkgInfo = packages.get(p);
4828 if (pkgInfo != null && pkgInfo.packageName != null
4829 && card.getCarrierPrivilegeStatus(pkgInfo)
4830 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
4831 privilegedPackages.add(pkgInfo.packageName);
4832 }
4833 }
4834 }
4835 }
4836 return privilegedPackages;
4837 }
4838
Wink Savilleb564aae2014-10-23 10:18:09 -07004839 private String getIccId(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07004840 final Phone phone = getPhone(subId);
4841 UiccCard card = phone == null ? null : phone.getUiccCard();
Derek Tan97ebb422014-09-05 16:55:38 -07004842 if (card == null) {
4843 loge("getIccId: No UICC");
4844 return null;
4845 }
4846 String iccId = card.getIccId();
4847 if (TextUtils.isEmpty(iccId)) {
4848 loge("getIccId: ICC ID is null or empty.");
4849 return null;
4850 }
4851 return iccId;
4852 }
4853
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07004854 @Override
Jeff Sharkey85190e62014-12-05 09:40:12 -08004855 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
4856 String number) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004857 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
4858 subId, "setLine1NumberForDisplayForSubscriber");
Derek Tan97ebb422014-09-05 16:55:38 -07004859
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004860 final long identity = Binder.clearCallingIdentity();
4861 try {
4862 final String iccId = getIccId(subId);
4863 final Phone phone = getPhone(subId);
4864 if (phone == null) {
4865 return false;
4866 }
4867 final String subscriberId = phone.getSubscriberId();
4868
4869 if (DBG_MERGE) {
4870 Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
4871 + subscriberId + " to " + number);
4872 }
4873
4874 if (TextUtils.isEmpty(iccId)) {
4875 return false;
4876 }
4877
4878 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
4879
4880 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
4881 if (alphaTag == null) {
4882 editor.remove(alphaTagPrefKey);
4883 } else {
4884 editor.putString(alphaTagPrefKey, alphaTag);
4885 }
4886
4887 // Record both the line number and IMSI for this ICCID, since we need to
4888 // track all merged IMSIs based on line number
4889 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
4890 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
4891 if (number == null) {
4892 editor.remove(numberPrefKey);
4893 editor.remove(subscriberPrefKey);
4894 } else {
4895 editor.putString(numberPrefKey, number);
4896 editor.putString(subscriberPrefKey, subscriberId);
4897 }
4898
4899 editor.commit();
4900 return true;
4901 } finally {
4902 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004903 }
Derek Tan7226c842014-07-02 17:42:23 -07004904 }
4905
4906 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07004907 public String getLine1NumberForDisplay(int subId, String callingPackage) {
Makoto Onukifee69342015-06-29 14:44:50 -07004908 // This is open to apps with WRITE_SMS.
Jeff Davidson7e17e312018-02-13 18:17:36 -08004909 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
Jeff Davidson913390f2018-02-23 17:11:49 -08004910 mApp, subId, callingPackage, "getLine1NumberForDisplay")) {
Amit Mahajan9cf11512015-11-09 11:40:48 -08004911 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
Svet Ganovb320e182015-04-16 12:30:10 -07004912 return null;
4913 }
Derek Tan97ebb422014-09-05 16:55:38 -07004914
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004915 final long identity = Binder.clearCallingIdentity();
4916 try {
4917 String iccId = getIccId(subId);
4918 if (iccId != null) {
4919 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
4920 if (DBG_MERGE) {
4921 log("getLine1NumberForDisplay returning "
4922 + mTelephonySharedPreferences.getString(numberPrefKey, null));
4923 }
4924 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Amit Mahajan9cf11512015-11-09 11:40:48 -08004925 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004926 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
4927 return null;
4928 } finally {
4929 Binder.restoreCallingIdentity(identity);
Derek Tan7226c842014-07-02 17:42:23 -07004930 }
Derek Tan7226c842014-07-02 17:42:23 -07004931 }
4932
4933 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07004934 public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004935 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08004936 mApp, subId, callingPackage, "getLine1AlphaTagForDisplay")) {
Svet Ganovb320e182015-04-16 12:30:10 -07004937 return null;
4938 }
Derek Tan97ebb422014-09-05 16:55:38 -07004939
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004940 final long identity = Binder.clearCallingIdentity();
4941 try {
4942 String iccId = getIccId(subId);
4943 if (iccId != null) {
4944 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
4945 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
4946 }
4947 return null;
4948 } finally {
4949 Binder.restoreCallingIdentity(identity);
Derek Tan7226c842014-07-02 17:42:23 -07004950 }
Derek Tan7226c842014-07-02 17:42:23 -07004951 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07004952
4953 @Override
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07004954 public String[] getMergedSubscriberIds(String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004955 // This API isn't public, so no need to provide a valid subscription ID - we're not worried
4956 // about carrier-privileged callers not having access.
Jeff Davidson7e17e312018-02-13 18:17:36 -08004957 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08004958 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
4959 "getMergedSubscriberIds")) {
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07004960 return null;
4961 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08004962
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07004963 final long identity = Binder.clearCallingIdentity();
4964 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004965 final Context context = mApp;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004966 final TelephonyManager tele = TelephonyManager.from(context);
4967 final SubscriptionManager sub = SubscriptionManager.from(context);
4968
4969 // Figure out what subscribers are currently active
4970 final ArraySet<String> activeSubscriberIds = new ArraySet<>();
4971 // Clear calling identity, when calling TelephonyManager, because callerUid must be
4972 // the process, where TelephonyManager was instantiated.
4973 // Otherwise AppOps check will fail.
4974
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07004975 final int[] subIds = sub.getActiveSubscriptionIdList();
4976 for (int subId : subIds) {
4977 activeSubscriberIds.add(tele.getSubscriberId(subId));
4978 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004979
4980 // First pass, find a number override for an active subscriber
4981 String mergeNumber = null;
4982 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
4983 for (String key : prefs.keySet()) {
4984 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
4985 final String subscriberId = (String) prefs.get(key);
4986 if (activeSubscriberIds.contains(subscriberId)) {
4987 final String iccId = key.substring(
4988 PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
4989 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
4990 mergeNumber = (String) prefs.get(numberKey);
4991 if (DBG_MERGE) {
4992 Slog.d(LOG_TAG, "Found line number " + mergeNumber
4993 + " for active subscriber " + subscriberId);
4994 }
4995 if (!TextUtils.isEmpty(mergeNumber)) {
4996 break;
4997 }
4998 }
4999 }
5000 }
5001
5002 // Shortcut when no active merged subscribers
5003 if (TextUtils.isEmpty(mergeNumber)) {
5004 return null;
5005 }
5006
5007 // Second pass, find all subscribers under that line override
5008 final ArraySet<String> result = new ArraySet<>();
5009 for (String key : prefs.keySet()) {
5010 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
5011 final String number = (String) prefs.get(key);
5012 if (mergeNumber.equals(number)) {
5013 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
5014 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
5015 final String subscriberId = (String) prefs.get(subscriberKey);
5016 if (!TextUtils.isEmpty(subscriberId)) {
5017 result.add(subscriberId);
5018 }
5019 }
5020 }
5021 }
5022
5023 final String[] resultArray = result.toArray(new String[result.size()]);
5024 Arrays.sort(resultArray);
5025 if (DBG_MERGE) {
5026 Slog.d(LOG_TAG,
5027 "Found subscribers " + Arrays.toString(resultArray) + " after merge");
5028 }
5029 return resultArray;
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07005030 } finally {
5031 Binder.restoreCallingIdentity(identity);
Jeff Sharkey85190e62014-12-05 09:40:12 -08005032 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08005033 }
5034
5035 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08005036 public boolean setOperatorBrandOverride(int subId, String brand) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08005037 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
5038 subId, "setOperatorBrandOverride");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005039
5040 final long identity = Binder.clearCallingIdentity();
5041 try {
5042 final Phone phone = getPhone(subId);
5043 return phone == null ? false : phone.setOperatorBrandOverride(brand);
5044 } finally {
5045 Binder.restoreCallingIdentity(identity);
5046 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07005047 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05005048
5049 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08005050 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08005051 List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
5052 List<String> cdmaNonRoamingList) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08005053 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, "setRoamingOverride");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005054
5055 final long identity = Binder.clearCallingIdentity();
5056 try {
5057 final Phone phone = getPhone(subId);
5058 if (phone == null) {
5059 return false;
5060 }
5061 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
5062 cdmaNonRoamingList);
5063 } finally {
5064 Binder.restoreCallingIdentity(identity);
Shishir Agrawalc04d9752016-02-19 10:41:00 -08005065 }
Shishir Agrawal621a47c2014-12-01 10:25:09 -08005066 }
5067
5068 @Override
Shuo Qian850e4d6a2018-04-25 21:02:08 +00005069 @Deprecated
5070 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
5071 enforceModifyPermission();
5072
5073 int returnValue = 0;
5074 try {
vagdeviaf9a5b92018-08-15 16:01:53 -07005075 AsyncResult result = (AsyncResult) sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00005076 if(result.exception == null) {
5077 if (result.result != null) {
5078 byte[] responseData = (byte[])(result.result);
5079 if(responseData.length > oemResp.length) {
5080 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
5081 responseData.length + "bytes. Buffer Size is " +
5082 oemResp.length + "bytes.");
5083 }
5084 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
5085 returnValue = responseData.length;
5086 }
5087 } else {
5088 CommandException ex = (CommandException) result.exception;
5089 returnValue = ex.getCommandError().ordinal();
5090 if(returnValue > 0) returnValue *= -1;
5091 }
5092 } catch (RuntimeException e) {
5093 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
5094 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
5095 if(returnValue > 0) returnValue *= -1;
5096 }
5097
5098 return returnValue;
5099 }
5100
5101 @Override
Wink Saville5d475dd2014-10-17 15:00:58 -07005102 public void setRadioCapability(RadioAccessFamily[] rafs) {
5103 try {
5104 ProxyController.getInstance().setRadioCapability(rafs);
5105 } catch (RuntimeException e) {
5106 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
5107 }
5108 }
5109
5110 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07005111 public int getRadioAccessFamily(int phoneId, String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08005112 Phone phone = PhoneFactory.getPhone(phoneId);
chen xub97461a2018-10-26 14:17:57 -07005113 int raf = RadioAccessFamily.RAF_UNKNOWN;
Jeff Davidson913390f2018-02-23 17:11:49 -08005114 if (phone == null) {
chen xub97461a2018-10-26 14:17:57 -07005115 return raf;
Jeff Davidson913390f2018-02-23 17:11:49 -08005116 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005117 final long identity = Binder.clearCallingIdentity();
5118 try {
chen xub97461a2018-10-26 14:17:57 -07005119 TelephonyPermissions
5120 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
5121 mApp, phone.getSubId(), "getRadioAccessFamily");
5122 raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005123 } finally {
5124 Binder.restoreCallingIdentity(identity);
5125 }
chen xub97461a2018-10-26 14:17:57 -07005126 return raf;
Wink Saville5d475dd2014-10-17 15:00:58 -07005127 }
Andrew Leedf14ead2014-10-17 14:22:52 -07005128
5129 @Override
5130 public void enableVideoCalling(boolean enable) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005131 final Phone defaultPhone = getDefaultPhone();
Andrew Leedf14ead2014-10-17 14:22:52 -07005132 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005133
5134 final long identity = Binder.clearCallingIdentity();
5135 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005136 ImsManager.getInstance(defaultPhone.getContext(),
5137 defaultPhone.getPhoneId()).setVtSetting(enable);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005138 } finally {
5139 Binder.restoreCallingIdentity(identity);
5140 }
Andrew Leedf14ead2014-10-17 14:22:52 -07005141 }
5142
5143 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07005144 public boolean isVideoCallingEnabled(String callingPackage) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005145 final Phone defaultPhone = getDefaultPhone();
Amit Mahajan578e53d2018-03-20 16:18:38 +00005146 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005147 mApp, defaultPhone.getSubId(), callingPackage, "isVideoCallingEnabled")) {
Amit Mahajan578e53d2018-03-20 16:18:38 +00005148 return false;
5149 }
Svet Ganovb320e182015-04-16 12:30:10 -07005150
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005151 final long identity = Binder.clearCallingIdentity();
5152 try {
5153 // Check the user preference and the system-level IMS setting. Even if the user has
5154 // enabled video calling, if IMS is disabled we aren't able to support video calling.
5155 // In the long run, we may instead need to check if there exists a connection service
5156 // which can support video calling.
5157 ImsManager imsManager =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005158 ImsManager.getInstance(defaultPhone.getContext(), defaultPhone.getPhoneId());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005159 return imsManager.isVtEnabledByPlatform()
5160 && imsManager.isEnhanced4gLteModeSettingEnabledByUser()
5161 && imsManager.isVtEnabledByUser();
5162 } finally {
5163 Binder.restoreCallingIdentity(identity);
5164 }
Andrew Leedf14ead2014-10-17 14:22:52 -07005165 }
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06005166
Andrew Leea1239f22015-03-02 17:44:07 -08005167 @Override
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005168 public boolean canChangeDtmfToneLength(int subId, String callingPackage) {
5169 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
5170 mApp, subId, callingPackage, "isVideoCallingEnabled")) {
5171 return false;
5172 }
5173
5174 final long identity = Binder.clearCallingIdentity();
5175 try {
5176 CarrierConfigManager configManager =
5177 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005178 return configManager.getConfigForSubId(subId)
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005179 .getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
5180 } finally {
5181 Binder.restoreCallingIdentity(identity);
5182 }
Andrew Leea1239f22015-03-02 17:44:07 -08005183 }
5184
5185 @Override
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005186 public boolean isWorldPhone(int subId, String callingPackage) {
5187 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
5188 mApp, subId, callingPackage, "isVideoCallingEnabled")) {
5189 return false;
5190 }
5191
5192 final long identity = Binder.clearCallingIdentity();
5193 try {
5194 CarrierConfigManager configManager =
5195 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005196 return configManager.getConfigForSubId(subId)
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005197 .getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
5198 } finally {
5199 Binder.restoreCallingIdentity(identity);
5200 }
Andrew Leea1239f22015-03-02 17:44:07 -08005201 }
5202
Andrew Lee9431b832015-03-09 18:46:45 -07005203 @Override
5204 public boolean isTtyModeSupported() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005205 TelecomManager telecomManager = TelecomManager.from(mApp);
Wooki Wu1f82f7a2016-02-15 15:59:58 +08005206 return telecomManager.isTtySupported();
Andrew Lee9431b832015-03-09 18:46:45 -07005207 }
5208
5209 @Override
5210 public boolean isHearingAidCompatibilitySupported() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005211 final long identity = Binder.clearCallingIdentity();
5212 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005213 return mApp.getResources().getBoolean(R.bool.hac_enabled);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005214 } finally {
5215 Binder.restoreCallingIdentity(identity);
5216 }
Andrew Lee9431b832015-03-09 18:46:45 -07005217 }
5218
Hall Liuf6668912018-10-31 17:05:23 -07005219 /**
5220 * Determines whether the device currently supports RTT (Real-time text). Based both on carrier
5221 * support for the feature and device firmware support.
5222 *
5223 * @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
5224 */
5225 @Override
5226 public boolean isRttSupported(int subscriptionId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005227 final long identity = Binder.clearCallingIdentity();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005228 final Phone phone = getPhone(subscriptionId);
5229 if (phone == null) {
5230 loge("isRttSupported: no Phone found. Invalid subId:" + subscriptionId);
5231 return false;
5232 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005233 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005234 boolean isCarrierSupported = mApp.getCarrierConfigForSubId(subscriptionId).getBoolean(
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005235 CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
5236 boolean isDeviceSupported =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005237 phone.getContext().getResources().getBoolean(R.bool.config_support_rtt);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005238 return isCarrierSupported && isDeviceSupported;
5239 } finally {
5240 Binder.restoreCallingIdentity(identity);
5241 }
Hall Liu98187582018-01-22 19:15:32 -08005242 }
5243
Hall Liuf6668912018-10-31 17:05:23 -07005244 /**
5245 * Determines whether the user has turned on RTT. Only returns true if the device and carrier
5246 * both also support RTT.
5247 */
5248 public boolean isRttEnabled(int subscriptionId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005249 final long identity = Binder.clearCallingIdentity();
5250 try {
Hall Liuf6668912018-10-31 17:05:23 -07005251 return isRttSupported(subscriptionId) && Settings.Secure.getInt(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005252 mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005253 } finally {
5254 Binder.restoreCallingIdentity(identity);
5255 }
Hall Liu3ad5f012018-04-06 16:23:39 -07005256 }
5257
Sanket Padawe7310cc72015-01-14 09:53:20 -08005258 /**
5259 * Returns the unique device ID of phone, for example, the IMEI for
5260 * GSM and the MEID for CDMA phones. Return null if device ID is not available.
5261 *
5262 * <p>Requires Permission:
5263 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
5264 */
5265 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07005266 public String getDeviceId(String callingPackage) {
Sanket Padawe7310cc72015-01-14 09:53:20 -08005267 final Phone phone = PhoneFactory.getPhone(0);
Jeff Davidson913390f2018-02-23 17:11:49 -08005268 if (phone == null) {
Sanket Padawe7310cc72015-01-14 09:53:20 -08005269 return null;
5270 }
Jeff Davidson913390f2018-02-23 17:11:49 -08005271 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07005272 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
5273 callingPackage, "getDeviceId")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08005274 return null;
5275 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005276
5277 final long identity = Binder.clearCallingIdentity();
5278 try {
5279 return phone.getDeviceId();
5280 } finally {
5281 Binder.restoreCallingIdentity(identity);
5282 }
Sanket Padawe7310cc72015-01-14 09:53:20 -08005283 }
5284
Ping Sunc67b7c22016-03-02 19:16:45 +08005285 /**
5286 * {@hide}
5287 * Returns the IMS Registration Status on a particular subid
5288 *
5289 * @param subId
5290 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005291 public boolean isImsRegistered(int subId) {
Ping Sunc67b7c22016-03-02 19:16:45 +08005292 Phone phone = getPhone(subId);
5293 if (phone != null) {
5294 return phone.isImsRegistered();
5295 } else {
5296 return false;
5297 }
5298 }
5299
Santos Cordon7a1885b2015-02-03 11:15:19 -08005300 @Override
5301 public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005302 final long identity = Binder.clearCallingIdentity();
5303 try {
5304 return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
5305 } finally {
5306 Binder.restoreCallingIdentity(identity);
5307 }
Santos Cordon7a1885b2015-02-03 11:15:19 -08005308 }
Nathan Harolddcfc7932015-03-18 10:01:20 -07005309
Tyler Gunnf70ed162019-04-03 15:28:53 -07005310 @Override
5311 public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
5312 final long identity = Binder.clearCallingIdentity();
5313 try {
5314 Phone phone = getPhone(subscriptionId);
5315 if (phone == null) {
5316 return null;
5317 }
5318 return PhoneUtils.makePstnPhoneAccountHandle(phone);
5319 } finally {
5320 Binder.restoreCallingIdentity(identity);
5321 }
5322 }
5323
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005324 /**
5325 * @return the VoWiFi calling availability.
Nathan Haroldc55097a2015-03-11 18:14:50 -07005326 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005327 public boolean isWifiCallingAvailable(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005328 final long identity = Binder.clearCallingIdentity();
5329 try {
5330 Phone phone = getPhone(subId);
5331 if (phone != null) {
5332 return phone.isWifiCallingEnabled();
5333 } else {
5334 return false;
5335 }
5336 } finally {
5337 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005338 }
Nathan Haroldc55097a2015-03-11 18:14:50 -07005339 }
5340
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005341 /**
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005342 * @return the VT calling availability.
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07005343 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005344 public boolean isVideoTelephonyAvailable(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005345 final long identity = Binder.clearCallingIdentity();
5346 try {
5347 Phone phone = getPhone(subId);
5348 if (phone != null) {
5349 return phone.isVideoEnabled();
5350 } else {
5351 return false;
5352 }
5353 } finally {
5354 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005355 }
5356 }
5357
5358 /**
5359 * @return the IMS registration technology for the MMTEL feature. Valid return values are
5360 * defined in {@link ImsRegistrationImplBase}.
5361 */
5362 public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005363 final long identity = Binder.clearCallingIdentity();
5364 try {
5365 Phone phone = getPhone(subId);
5366 if (phone != null) {
5367 return phone.getImsRegistrationTech();
5368 } else {
5369 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
5370 }
5371 } finally {
5372 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08005373 }
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07005374 }
5375
Stuart Scott8eef64f2015-04-08 15:13:54 -07005376 @Override
5377 public void factoryReset(int subId) {
5378 enforceConnectivityInternalPermission();
Stuart Scott981d8582015-04-21 14:09:50 -07005379 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
5380 return;
5381 }
5382
Svet Ganovcc087f82015-05-12 20:35:54 -07005383 final long identity = Binder.clearCallingIdentity();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005384
Svet Ganovcc087f82015-05-12 20:35:54 -07005385 try {
Stuart Scott981d8582015-04-21 14:09:50 -07005386 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
5387 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Pengquan Meng85728fb2018-03-12 16:31:21 -07005388 setUserDataEnabled(subId, getDefaultDataEnabled());
Svet Ganovcc087f82015-05-12 20:35:54 -07005389 setNetworkSelectionModeAutomatic(subId);
Pengquan Meng85728fb2018-03-12 16:31:21 -07005390 setPreferredNetworkType(subId, getDefaultNetworkType(subId));
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005391 setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
5392 CarrierInfoManager.deleteAllCarrierKeysForImsiEncryption(mApp);
Svet Ganovcc087f82015-05-12 20:35:54 -07005393 }
Amit Mahajan7dbbd822019-03-13 17:33:47 -07005394 // There has been issues when Sms raw table somehow stores orphan
5395 // fragments. They lead to garbled message when new fragments come
5396 // in and combined with those stale ones. In case this happens again,
5397 // user can reset all network settings which will clean up this table.
5398 cleanUpSmsRawTable(getDefaultPhone().getContext());
Svet Ganovcc087f82015-05-12 20:35:54 -07005399 } finally {
5400 Binder.restoreCallingIdentity(identity);
Stuart Scott8eef64f2015-04-08 15:13:54 -07005401 }
5402 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01005403
Amit Mahajan7dbbd822019-03-13 17:33:47 -07005404 private void cleanUpSmsRawTable(Context context) {
5405 ContentResolver resolver = context.getContentResolver();
5406 Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
5407 resolver.delete(uri, null, null);
5408 }
5409
Narayan Kamath1c496c22015-04-16 14:40:19 +01005410 @Override
chen xu5d3637b2019-01-21 23:31:38 -08005411 public String getSimLocaleForSubscriber(int subId) {
5412 enforceReadPrivilegedPermission("getSimLocaleForSubscriber, subId: " + subId);
5413 final Phone phone = getPhone(subId);
5414 if (phone == null) {
5415 log("getSimLocaleForSubscriber, invalid subId");
chen xu2bb91e42019-01-24 14:35:54 -08005416 return null;
chen xu5d3637b2019-01-21 23:31:38 -08005417 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005418 final long identity = Binder.clearCallingIdentity();
5419 try {
chen xu5d3637b2019-01-21 23:31:38 -08005420 final SubscriptionInfo info = mSubscriptionController.getActiveSubscriptionInfo(subId,
5421 phone.getContext().getOpPackageName());
chen xu6291c472019-02-04 12:55:53 -08005422 if (info == null) {
5423 log("getSimLocaleForSubscriber, inactive subId: " + subId);
5424 return null;
5425 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005426 // Try and fetch the locale from the carrier properties or from the SIM language
5427 // preferences (EF-PL and EF-LI)...
5428 final int mcc = info.getMcc();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005429 String simLanguage = null;
chen xu5d3637b2019-01-21 23:31:38 -08005430 final Locale localeFromDefaultSim = phone.getLocaleFromSimAndCarrierPrefs();
5431 if (localeFromDefaultSim != null) {
5432 if (!localeFromDefaultSim.getCountry().isEmpty()) {
5433 if (DBG) log("Using locale from subId: " + subId + " locale: "
5434 + localeFromDefaultSim);
5435 return localeFromDefaultSim.toLanguageTag();
5436 } else {
5437 simLanguage = localeFromDefaultSim.getLanguage();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005438 }
5439 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01005440
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005441 // The SIM language preferences only store a language (e.g. fr = French), not an
5442 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
5443 // the SIM and carrier preferences does not include a country we add the country
5444 // determined from the SIM MCC to provide an exact locale.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005445 final Locale mccLocale = MccTable.getLocaleFromMcc(mApp, mcc, simLanguage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005446 if (mccLocale != null) {
chen xu5d3637b2019-01-21 23:31:38 -08005447 if (DBG) log("No locale from SIM, using mcc locale:" + mccLocale);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005448 return mccLocale.toLanguageTag();
5449 }
5450
5451 if (DBG) log("No locale found - returning null");
5452 return null;
5453 } finally {
5454 Binder.restoreCallingIdentity(identity);
5455 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01005456 }
5457
5458 private List<SubscriptionInfo> getAllSubscriptionInfoList() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005459 return mSubscriptionController.getAllSubInfoList(mApp.getOpPackageName());
Narayan Kamath1c496c22015-04-16 14:40:19 +01005460 }
5461
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005462 /**
5463 * NOTE: this method assumes permission checks are done and caller identity has been cleared.
5464 */
5465 private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005466 return mSubscriptionController.getActiveSubscriptionInfoList(mApp.getOpPackageName());
Narayan Kamath1c496c22015-04-16 14:40:19 +01005467 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07005468
Chenjie Yu1ba97252018-01-11 18:16:20 -08005469 private final ModemActivityInfo mLastModemActivityInfo =
5470 new ModemActivityInfo(0, 0, 0, new int[0], 0, 0);
5471
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07005472 /**
Adam Lesinski903a54c2016-04-11 14:49:52 -07005473 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
5474 * representing the state of the modem.
5475 *
Chenjie Yu1ba97252018-01-11 18:16:20 -08005476 * NOTE: The underlying implementation clears the modem state, so there should only ever be one
5477 * caller to it. Everyone should call this class to get cumulative data.
Adam Lesinski903a54c2016-04-11 14:49:52 -07005478 * @hide
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07005479 */
5480 @Override
Adam Lesinski903a54c2016-04-11 14:49:52 -07005481 public void requestModemActivityInfo(ResultReceiver result) {
5482 enforceModifyPermission();
vagdeviaf9a5b92018-08-15 16:01:53 -07005483 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005484
5485 final long identity = Binder.clearCallingIdentity();
5486 try {
5487 ModemActivityInfo ret = null;
5488 synchronized (mLastModemActivityInfo) {
5489 ModemActivityInfo info = (ModemActivityInfo) sendRequest(
5490 CMD_GET_MODEM_ACTIVITY_INFO,
vagdeviaf9a5b92018-08-15 16:01:53 -07005491 null, workSource);
Siddharth Rayb8114062018-06-17 15:02:38 -07005492 if (isModemActivityInfoValid(info)) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005493 int[] mergedTxTimeMs = new int[ModemActivityInfo.TX_POWER_LEVELS];
5494 for (int i = 0; i < mergedTxTimeMs.length; i++) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005495 mergedTxTimeMs[i] = info.getTxTimeMillis()[i]
5496 + mLastModemActivityInfo.getTxTimeMillis()[i];
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005497 }
5498 mLastModemActivityInfo.setTimestamp(info.getTimestamp());
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005499 mLastModemActivityInfo.setSleepTimeMillis(info.getSleepTimeMillis()
5500 + mLastModemActivityInfo.getSleepTimeMillis());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005501 mLastModemActivityInfo.setIdleTimeMillis(
5502 info.getIdleTimeMillis() + mLastModemActivityInfo.getIdleTimeMillis());
5503 mLastModemActivityInfo.setTxTimeMillis(mergedTxTimeMs);
5504 mLastModemActivityInfo.setRxTimeMillis(
5505 info.getRxTimeMillis() + mLastModemActivityInfo.getRxTimeMillis());
5506 mLastModemActivityInfo.setEnergyUsed(
5507 info.getEnergyUsed() + mLastModemActivityInfo.getEnergyUsed());
Chenjie Yu1ba97252018-01-11 18:16:20 -08005508 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005509 ret = new ModemActivityInfo(mLastModemActivityInfo.getTimestamp(),
5510 mLastModemActivityInfo.getSleepTimeMillis(),
5511 mLastModemActivityInfo.getIdleTimeMillis(),
5512 mLastModemActivityInfo.getTxTimeMillis(),
5513 mLastModemActivityInfo.getRxTimeMillis(),
5514 mLastModemActivityInfo.getEnergyUsed());
Chenjie Yu1ba97252018-01-11 18:16:20 -08005515 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005516 Bundle bundle = new Bundle();
5517 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, ret);
5518 result.send(0, bundle);
5519 } finally {
5520 Binder.restoreCallingIdentity(identity);
Chenjie Yu1ba97252018-01-11 18:16:20 -08005521 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07005522 }
Jack Yu85bd38a2015-11-09 11:34:32 -08005523
Siddharth Rayb8114062018-06-17 15:02:38 -07005524 // Checks that ModemActivityInfo is valid. Sleep time, Idle time, Rx time and Tx time should be
5525 // less than total activity duration.
5526 private boolean isModemActivityInfoValid(ModemActivityInfo info) {
5527 if (info == null) {
5528 return false;
5529 }
5530 int activityDurationMs =
5531 (int) (info.getTimestamp() - mLastModemActivityInfo.getTimestamp());
5532 int totalTxTimeMs = 0;
5533 for (int i = 0; i < info.getTxTimeMillis().length; i++) {
5534 totalTxTimeMs += info.getTxTimeMillis()[i];
5535 }
5536 return (info.isValid()
5537 && (info.getSleepTimeMillis() <= activityDurationMs)
5538 && (info.getIdleTimeMillis() <= activityDurationMs)
5539 && (info.getRxTimeMillis() <= activityDurationMs)
5540 && (totalTxTimeMs <= activityDurationMs));
5541 }
5542
Jack Yu85bd38a2015-11-09 11:34:32 -08005543 /**
5544 * {@hide}
5545 * Returns the service state information on specified subscription.
5546 */
5547 @Override
5548 public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08005549 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08005550 mApp, subId, callingPackage, "getServiceStateForSubscriber")) {
Jack Yu85bd38a2015-11-09 11:34:32 -08005551 return null;
5552 }
5553
Hall Liuf19c44f2018-11-27 14:38:17 -08005554 LocationAccessPolicy.LocationPermissionResult fineLocationResult =
5555 LocationAccessPolicy.checkLocationPermission(mApp,
5556 new LocationAccessPolicy.LocationPermissionQuery.Builder()
5557 .setCallingPackage(callingPackage)
5558 .setCallingPid(Binder.getCallingPid())
5559 .setCallingUid(Binder.getCallingUid())
5560 .setMethod("getServiceStateForSubscriber")
5561 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
5562 .build());
5563
5564 LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
5565 LocationAccessPolicy.checkLocationPermission(mApp,
5566 new LocationAccessPolicy.LocationPermissionQuery.Builder()
5567 .setCallingPackage(callingPackage)
5568 .setCallingPid(Binder.getCallingPid())
5569 .setCallingUid(Binder.getCallingUid())
5570 .setMethod("getServiceStateForSubscriber")
5571 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
5572 .build());
5573 // We don't care about hard or soft here -- all we need to know is how much info to scrub.
5574 boolean hasFinePermission =
5575 fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
5576 boolean hasCoarsePermission =
5577 coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
5578
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005579 final long identity = Binder.clearCallingIdentity();
5580 try {
5581 final Phone phone = getPhone(subId);
5582 if (phone == null) {
5583 return null;
5584 }
Jack Yu85bd38a2015-11-09 11:34:32 -08005585
Hall Liuf19c44f2018-11-27 14:38:17 -08005586 ServiceState ss = phone.getServiceState();
5587
5588 // Scrub out the location info in ServiceState depending on what level of access
5589 // the caller has.
5590 if (hasFinePermission) return ss;
5591 if (hasCoarsePermission) return ss.sanitizeLocationInfo(false);
5592 return ss.sanitizeLocationInfo(true);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005593 } finally {
5594 Binder.restoreCallingIdentity(identity);
5595 }
Jack Yu85bd38a2015-11-09 11:34:32 -08005596 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08005597
5598 /**
5599 * Returns the URI for the per-account voicemail ringtone set in Phone settings.
5600 *
5601 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
5602 * voicemail ringtone.
5603 * @return The URI for the ringtone to play when receiving a voicemail from a specific
5604 * PhoneAccount.
5605 */
5606 @Override
5607 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005608 final long identity = Binder.clearCallingIdentity();
5609 try {
5610 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
5611 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005612 phone = getDefaultPhone();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005613 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08005614
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005615 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone.getContext());
5616 } finally {
5617 Binder.restoreCallingIdentity(identity);
5618 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08005619 }
5620
5621 /**
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005622 * Sets the per-account voicemail ringtone.
5623 *
5624 * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
5625 * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
5626 *
5627 * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
5628 * voicemail ringtone.
5629 * @param uri The URI for the ringtone to play when receiving a voicemail from a specific
5630 * PhoneAccount.
5631 */
5632 @Override
5633 public void setVoicemailRingtoneUri(String callingPackage,
5634 PhoneAccountHandle phoneAccountHandle, Uri uri) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005635 final Phone defaultPhone = getDefaultPhone();
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005636 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
5637 if (!TextUtils.equals(callingPackage,
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005638 TelecomManager.from(defaultPhone.getContext()).getDefaultDialerPackage())) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08005639 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5640 mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
5641 "setVoicemailRingtoneUri");
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005642 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005643
5644 final long identity = Binder.clearCallingIdentity();
5645 try {
5646 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
5647 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005648 phone = defaultPhone;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005649 }
5650 VoicemailNotificationSettingsUtil.setRingtoneUri(phone.getContext(), uri);
5651 } finally {
5652 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005653 }
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005654 }
5655
5656 /**
Nancy Chen31f9ba12016-01-06 11:42:12 -08005657 * Returns whether vibration is set for voicemail notification in Phone settings.
5658 *
5659 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
5660 * voicemail vibration setting.
5661 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
5662 */
5663 @Override
5664 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005665 final long identity = Binder.clearCallingIdentity();
5666 try {
5667 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
5668 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005669 phone = getDefaultPhone();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005670 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08005671
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005672 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone.getContext());
5673 } finally {
5674 Binder.restoreCallingIdentity(identity);
5675 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08005676 }
5677
Youhan Wange64578a2016-05-02 15:32:42 -07005678 /**
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005679 * Sets the per-account voicemail vibration.
5680 *
5681 * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
5682 * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
5683 *
5684 * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
5685 * voicemail vibration setting.
5686 * @param enabled Whether to enable or disable vibration for voicemail notifications from a
5687 * specific PhoneAccount.
5688 */
5689 @Override
5690 public void setVoicemailVibrationEnabled(String callingPackage,
5691 PhoneAccountHandle phoneAccountHandle, boolean enabled) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005692 final Phone defaultPhone = getDefaultPhone();
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005693 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
5694 if (!TextUtils.equals(callingPackage,
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005695 TelecomManager.from(defaultPhone.getContext()).getDefaultDialerPackage())) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08005696 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5697 mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
5698 "setVoicemailVibrationEnabled");
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005699 }
5700
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005701 final long identity = Binder.clearCallingIdentity();
5702 try {
5703 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
5704 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005705 phone = defaultPhone;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005706 }
5707 VoicemailNotificationSettingsUtil.setVibrationEnabled(phone.getContext(), enabled);
5708 } finally {
5709 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005710 }
Ta-wei Yenc33877d2017-01-23 18:11:21 -08005711 }
5712
5713 /**
Youhan Wange64578a2016-05-02 15:32:42 -07005714 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
5715 *
5716 * @throws SecurityException if the caller does not have the required permission
5717 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005718 private void enforceReadPrivilegedPermission(String message) {
Youhan Wange64578a2016-05-02 15:32:42 -07005719 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Brad Ebinger35c841c2018-10-01 10:40:55 -07005720 message);
Youhan Wange64578a2016-05-02 15:32:42 -07005721 }
5722
5723 /**
Ta-wei Yen30a69c82016-12-27 14:52:32 -08005724 * Make sure either called from same process as self (phone) or IPC caller has send SMS
5725 * permission.
5726 *
5727 * @throws SecurityException if the caller does not have the required permission
5728 */
5729 private void enforceSendSmsPermission() {
5730 mApp.enforceCallingOrSelfPermission(permission.SEND_SMS, null);
5731 }
5732
5733 /**
Ta-wei Yen527a9c02017-01-06 15:29:25 -08005734 * Make sure called from the package in charge of visual voicemail.
Ta-wei Yen30a69c82016-12-27 14:52:32 -08005735 *
Ta-wei Yen527a9c02017-01-06 15:29:25 -08005736 * @throws SecurityException if the caller is not the visual voicemail package.
Ta-wei Yen30a69c82016-12-27 14:52:32 -08005737 */
Ta-wei Yen527a9c02017-01-06 15:29:25 -08005738 private void enforceVisualVoicemailPackage(String callingPackage, int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005739 final long identity = Binder.clearCallingIdentity();
5740 try {
5741 ComponentName componentName =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08005742 RemoteVvmTaskManager.getRemotePackage(mApp, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005743 if (componentName == null) {
5744 throw new SecurityException(
5745 "Caller not current active visual voicemail package[null]");
5746 }
5747 String vvmPackage = componentName.getPackageName();
5748 if (!callingPackage.equals(vvmPackage)) {
5749 throw new SecurityException("Caller not current active visual voicemail package["
5750 + vvmPackage + "]");
5751 }
5752 } finally {
5753 Binder.restoreCallingIdentity(identity);
Ta-wei Yen30a69c82016-12-27 14:52:32 -08005754 }
5755 }
5756
5757 /**
Youhan Wange64578a2016-05-02 15:32:42 -07005758 * Return the application ID for the app type.
5759 *
5760 * @param subId the subscription ID that this request applies to.
5761 * @param appType the uicc app type.
5762 * @return Application ID for specificied app type, or null if no uicc.
5763 */
5764 @Override
5765 public String getAidForAppType(int subId, int appType) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005766 enforceReadPrivilegedPermission("getAidForAppType");
Youhan Wange64578a2016-05-02 15:32:42 -07005767 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005768
5769 final long identity = Binder.clearCallingIdentity();
Youhan Wange64578a2016-05-02 15:32:42 -07005770 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005771 if (phone == null) {
5772 return null;
5773 }
5774 String aid = null;
5775 try {
5776 aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
5777 .getApplicationByType(appType).getAid();
5778 } catch (Exception e) {
5779 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
5780 }
5781 return aid;
5782 } finally {
5783 Binder.restoreCallingIdentity(identity);
Youhan Wange64578a2016-05-02 15:32:42 -07005784 }
Youhan Wange64578a2016-05-02 15:32:42 -07005785 }
5786
Youhan Wang4001d252016-05-11 10:29:41 -07005787 /**
5788 * Return the Electronic Serial Number.
5789 *
5790 * @param subId the subscription ID that this request applies to.
5791 * @return ESN or null if error.
5792 */
5793 @Override
5794 public String getEsn(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005795 enforceReadPrivilegedPermission("getEsn");
Youhan Wang4001d252016-05-11 10:29:41 -07005796 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005797
5798 final long identity = Binder.clearCallingIdentity();
Youhan Wang4001d252016-05-11 10:29:41 -07005799 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005800 if (phone == null) {
5801 return null;
5802 }
5803 String esn = null;
5804 try {
5805 esn = phone.getEsn();
5806 } catch (Exception e) {
5807 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
5808 }
5809 return esn;
5810 } finally {
5811 Binder.restoreCallingIdentity(identity);
Youhan Wang4001d252016-05-11 10:29:41 -07005812 }
Youhan Wang4001d252016-05-11 10:29:41 -07005813 }
5814
Sanket Padawe99ef1e32016-05-18 16:12:33 -07005815 /**
Youhan Wang66ad5d72016-07-18 17:56:58 -07005816 * Return the Preferred Roaming List Version.
5817 *
5818 * @param subId the subscription ID that this request applies to.
5819 * @return PRLVersion or null if error.
5820 */
5821 @Override
5822 public String getCdmaPrlVersion(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005823 enforceReadPrivilegedPermission("getCdmaPrlVersion");
Youhan Wang66ad5d72016-07-18 17:56:58 -07005824 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005825
5826 final long identity = Binder.clearCallingIdentity();
Youhan Wang66ad5d72016-07-18 17:56:58 -07005827 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005828 if (phone == null) {
5829 return null;
5830 }
5831 String cdmaPrlVersion = null;
5832 try {
5833 cdmaPrlVersion = phone.getCdmaPrlVersion();
5834 } catch (Exception e) {
5835 Log.e(LOG_TAG, "Not getting PRLVersion", e);
5836 }
5837 return cdmaPrlVersion;
5838 } finally {
5839 Binder.restoreCallingIdentity(identity);
Youhan Wang66ad5d72016-07-18 17:56:58 -07005840 }
Youhan Wang66ad5d72016-07-18 17:56:58 -07005841 }
5842
5843 /**
Sanket Padawe99ef1e32016-05-18 16:12:33 -07005844 * Get snapshot of Telephony histograms
5845 * @return List of Telephony histograms
5846 * @hide
5847 */
5848 @Override
5849 public List<TelephonyHistogram> getTelephonyHistograms() {
Jeff Davidson7e17e312018-02-13 18:17:36 -08005850 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
5851 mApp, getDefaultSubscription(), "getTelephonyHistograms");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005852
5853 final long identity = Binder.clearCallingIdentity();
5854 try {
5855 return RIL.getTelephonyRILTimingHistograms();
5856 } finally {
5857 Binder.restoreCallingIdentity(identity);
5858 }
Sanket Padawe99ef1e32016-05-18 16:12:33 -07005859 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07005860
5861 /**
5862 * {@hide}
Michele Berionne482f8202018-11-27 18:57:59 -08005863 * Set the allowed carrier list and the excluded carrier list, indicating the priority between
5864 * the two lists.
Meng Wang1a7c35a2016-05-05 20:56:15 -07005865 * Require system privileges. In the future we may add this to carrier APIs.
5866 *
Michele Berionne482f8202018-11-27 18:57:59 -08005867 * @return Integer with the result of the operation, as defined in {@link TelephonyManager}.
Meng Wang1a7c35a2016-05-05 20:56:15 -07005868 */
5869 @Override
Michele Berionne482f8202018-11-27 18:57:59 -08005870 @TelephonyManager.SetCarrierRestrictionResult
5871 public int setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules) {
Meng Wang1a7c35a2016-05-05 20:56:15 -07005872 enforceModifyPermission();
vagdeviaf9a5b92018-08-15 16:01:53 -07005873 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Sanket Padawe13bac7b2017-03-20 15:04:47 -07005874
Michele Berionne482f8202018-11-27 18:57:59 -08005875 if (carrierRestrictionRules == null) {
5876 throw new NullPointerException("carrier restriction cannot be null");
Meng Wang9b7c4e92017-02-17 11:41:27 -08005877 }
Sanket Padawe13bac7b2017-03-20 15:04:47 -07005878
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005879 final long identity = Binder.clearCallingIdentity();
5880 try {
Michele Berionne482f8202018-11-27 18:57:59 -08005881 return (int) sendRequest(CMD_SET_ALLOWED_CARRIERS, carrierRestrictionRules,
vagdeviaf9a5b92018-08-15 16:01:53 -07005882 workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005883 } finally {
5884 Binder.restoreCallingIdentity(identity);
5885 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07005886 }
5887
5888 /**
5889 * {@hide}
Michele Berionne482f8202018-11-27 18:57:59 -08005890 * Get the allowed carrier list and the excluded carrier list, including the priority between
5891 * the two lists.
Meng Wang1a7c35a2016-05-05 20:56:15 -07005892 * Require system privileges. In the future we may add this to carrier APIs.
5893 *
Michele Berionne482f8202018-11-27 18:57:59 -08005894 * @return {@link android.telephony.CarrierRestrictionRules}
Meng Wang1a7c35a2016-05-05 20:56:15 -07005895 */
5896 @Override
Michele Berionne482f8202018-11-27 18:57:59 -08005897 public CarrierRestrictionRules getAllowedCarriers() {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005898 enforceReadPrivilegedPermission("getAllowedCarriers");
vagdeviaf9a5b92018-08-15 16:01:53 -07005899 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005900
5901 final long identity = Binder.clearCallingIdentity();
5902 try {
Michele Berionne482f8202018-11-27 18:57:59 -08005903 Object response = sendRequest(CMD_GET_ALLOWED_CARRIERS, null, workSource);
5904 if (response instanceof CarrierRestrictionRules) {
5905 return (CarrierRestrictionRules) response;
5906 }
5907 // Response is an Exception of some kind,
5908 // which is signalled to the user as a NULL retval
5909 return null;
5910 } catch (Exception e) {
5911 Log.e(LOG_TAG, "getAllowedCarriers. Exception ex=" + e);
5912 return null;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005913 } finally {
5914 Binder.restoreCallingIdentity(identity);
5915 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07005916 }
5917
fionaxu59545b42016-05-25 15:53:37 -07005918 /**
5919 * Action set from carrier signalling broadcast receivers to enable/disable metered apns
5920 * @param subId the subscription ID that this action applies to.
5921 * @param enabled control enable or disable metered apns.
5922 * {@hide}
5923 */
5924 @Override
5925 public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
5926 enforceModifyPermission();
5927 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005928
5929 final long identity = Binder.clearCallingIdentity();
fionaxu59545b42016-05-25 15:53:37 -07005930 if (phone == null) {
5931 loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
5932 return;
5933 }
5934 try {
5935 phone.carrierActionSetMeteredApnsEnabled(enabled);
5936 } catch (Exception e) {
5937 Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005938 } finally {
5939 Binder.restoreCallingIdentity(identity);
fionaxu59545b42016-05-25 15:53:37 -07005940 }
5941 }
5942
5943 /**
5944 * Action set from carrier signalling broadcast receivers to enable/disable radio
5945 * @param subId the subscription ID that this action applies to.
5946 * @param enabled control enable or disable radio.
5947 * {@hide}
5948 */
5949 @Override
5950 public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
5951 enforceModifyPermission();
5952 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005953
5954 final long identity = Binder.clearCallingIdentity();
fionaxu59545b42016-05-25 15:53:37 -07005955 if (phone == null) {
5956 loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
5957 return;
5958 }
5959 try {
5960 phone.carrierActionSetRadioEnabled(enabled);
5961 } catch (Exception e) {
5962 Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005963 } finally {
5964 Binder.restoreCallingIdentity(identity);
fionaxu59545b42016-05-25 15:53:37 -07005965 }
5966 }
5967
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07005968 /**
fionaxu8da9cb12017-05-23 15:02:46 -07005969 * Action set from carrier signalling broadcast receivers to start/stop reporting the default
5970 * network status based on which carrier apps could apply actions accordingly,
5971 * enable/disable default url handler for example.
5972 *
5973 * @param subId the subscription ID that this action applies to.
5974 * @param report control start/stop reporting the default network status.
5975 * {@hide}
5976 */
5977 @Override
5978 public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
5979 enforceModifyPermission();
5980 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005981
5982 final long identity = Binder.clearCallingIdentity();
fionaxu8da9cb12017-05-23 15:02:46 -07005983 if (phone == null) {
5984 loge("carrierAction: ReportDefaultNetworkStatus fails with invalid sibId: " + subId);
5985 return;
5986 }
5987 try {
5988 phone.carrierActionReportDefaultNetworkStatus(report);
5989 } catch (Exception e) {
5990 Log.e(LOG_TAG, "carrierAction: ReportDefaultNetworkStatus fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08005991 } finally {
5992 Binder.restoreCallingIdentity(identity);
fionaxu8da9cb12017-05-23 15:02:46 -07005993 }
5994 }
5995
5996 /**
fionaxud9622282017-07-17 17:51:30 -07005997 * Action set from carrier signalling broadcast receivers to reset all carrier actions
5998 * @param subId the subscription ID that this action applies to.
5999 * {@hide}
6000 */
6001 @Override
6002 public void carrierActionResetAll(int subId) {
6003 enforceModifyPermission();
6004 final Phone phone = getPhone(subId);
6005 if (phone == null) {
6006 loge("carrierAction: ResetAll fails with invalid sibId: " + subId);
6007 return;
6008 }
6009 try {
6010 phone.carrierActionResetAll();
6011 } catch (Exception e) {
6012 Log.e(LOG_TAG, "carrierAction: ResetAll fails. Exception ex=" + e);
6013 }
6014 }
6015
6016 /**
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07006017 * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
6018 * bug report is being generated.
6019 */
6020 @Override
Ta-wei Yen99282e02016-06-21 18:19:35 -07006021 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006022 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
6023 != PackageManager.PERMISSION_GRANTED) {
dcashman22b950d2016-06-27 11:39:02 -07006024 writer.println("Permission Denial: can't dump Phone from pid="
6025 + Binder.getCallingPid()
6026 + ", uid=" + Binder.getCallingUid()
6027 + "without permission "
6028 + android.Manifest.permission.DUMP);
6029 return;
6030 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006031 DumpsysHandler.dump(mApp, fd, writer, args);
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07006032 }
Jack Yueb89b242016-06-22 13:27:47 -07006033
Brad Ebingerdac2f002018-04-03 15:17:52 -07006034 @Override
6035 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
6036 String[] args, ShellCallback callback, ResultReceiver resultReceiver)
6037 throws RemoteException {
6038 (new TelephonyShellCommand(this)).exec(this, in, out, err, args, callback, resultReceiver);
6039 }
6040
Jack Yueb89b242016-06-22 13:27:47 -07006041 /**
Jack Yu84291ec2017-05-26 16:07:50 -07006042 * Get aggregated video call data usage since boot.
6043 *
6044 * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
6045 * @return Snapshot of video call data usage
Jack Yueb89b242016-06-22 13:27:47 -07006046 * {@hide}
6047 */
6048 @Override
Jack Yu84291ec2017-05-26 16:07:50 -07006049 public NetworkStats getVtDataUsage(int subId, boolean perUidStats) {
Jack Yueb89b242016-06-22 13:27:47 -07006050 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
6051 null);
6052
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006053 final long identity = Binder.clearCallingIdentity();
6054 try {
6055 // NetworkStatsService keeps tracking the active network interface and identity. It
6056 // records the delta with the corresponding network identity.
6057 // We just return the total video call data usage snapshot since boot.
6058 Phone phone = getPhone(subId);
6059 if (phone != null) {
6060 return phone.getVtDataUsage(perUidStats);
6061 }
6062 return null;
6063 } finally {
6064 Binder.restoreCallingIdentity(identity);
Jack Yueb89b242016-06-22 13:27:47 -07006065 }
Jack Yueb89b242016-06-22 13:27:47 -07006066 }
Jack Yu75ab2952016-07-08 14:29:33 -07006067
6068 /**
6069 * Policy control of data connection. Usually used when data limit is passed.
6070 * @param enabled True if enabling the data, otherwise disabling.
6071 * @param subId Subscription index
6072 * {@hide}
6073 */
6074 @Override
6075 public void setPolicyDataEnabled(boolean enabled, int subId) {
6076 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006077
6078 final long identity = Binder.clearCallingIdentity();
6079 try {
6080 Phone phone = getPhone(subId);
6081 if (phone != null) {
Jack Yud79fba22018-12-13 11:51:28 -08006082 phone.getDataEnabledSettings().setPolicyDataEnabled(enabled);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006083 }
6084 } finally {
6085 Binder.restoreCallingIdentity(identity);
Jack Yu75ab2952016-07-08 14:29:33 -07006086 }
6087 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07006088
6089 /**
6090 * Get Client request stats
6091 * @return List of Client Request Stats
6092 * @hide
6093 */
6094 @Override
6095 public List<ClientRequestStats> getClientRequestStats(String callingPackage, int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006096 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08006097 mApp, subId, callingPackage, "getClientRequestStats")) {
Sooraj Sasindran9a909312016-07-18 11:57:25 -07006098 return null;
6099 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07006100 Phone phone = getPhone(subId);
Sooraj Sasindran9a909312016-07-18 11:57:25 -07006101
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006102 final long identity = Binder.clearCallingIdentity();
6103 try {
6104 if (phone != null) {
6105 return phone.getClientRequestStats();
6106 }
6107
6108 return null;
6109 } finally {
6110 Binder.restoreCallingIdentity(identity);
6111 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07006112 }
6113
Narayan Kamathf04b5a12018-01-09 11:47:15 +00006114 private WorkSource getWorkSource(int uid) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006115 String packageName = mApp.getPackageManager().getNameForUid(uid);
Narayan Kamathf04b5a12018-01-09 11:47:15 +00006116 return new WorkSource(uid, packageName);
Sooraj Sasindran9a909312016-07-18 11:57:25 -07006117 }
Jack Yueb4124c2017-02-16 15:32:43 -08006118
6119 /**
Grace Chen70990072017-03-24 17:21:30 -07006120 * Set SIM card power state.
Jack Yueb4124c2017-02-16 15:32:43 -08006121 *
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006122 * @param slotIndex SIM slot id.
Grace Chen70990072017-03-24 17:21:30 -07006123 * @param state State of SIM (power down, power up, pass through)
6124 * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
6125 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
6126 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
Jack Yueb4124c2017-02-16 15:32:43 -08006127 *
6128 **/
6129 @Override
Grace Chen70990072017-03-24 17:21:30 -07006130 public void setSimPowerStateForSlot(int slotIndex, int state) {
Jack Yueb4124c2017-02-16 15:32:43 -08006131 enforceModifyPermission();
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006132 Phone phone = PhoneFactory.getPhone(slotIndex);
6133
vagdeviaf9a5b92018-08-15 16:01:53 -07006134 WorkSource workSource = getWorkSource(Binder.getCallingUid());
6135
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006136 final long identity = Binder.clearCallingIdentity();
6137 try {
6138 if (phone != null) {
vagdeviaf9a5b92018-08-15 16:01:53 -07006139 phone.setSimPowerState(state, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006140 }
6141 } finally {
6142 Binder.restoreCallingIdentity(identity);
Jack Yueb4124c2017-02-16 15:32:43 -08006143 }
6144 }
Shuo Qiandd210312017-04-12 22:11:33 +00006145
Tyler Gunn65d45c22017-06-05 11:22:26 -07006146 private boolean isUssdApiAllowed(int subId) {
6147 CarrierConfigManager configManager =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006148 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Tyler Gunn65d45c22017-06-05 11:22:26 -07006149 if (configManager == null) {
6150 return false;
6151 }
6152 PersistableBundle pb = configManager.getConfigForSubId(subId);
6153 if (pb == null) {
6154 return false;
6155 }
6156 return pb.getBoolean(
6157 CarrierConfigManager.KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL);
6158 }
6159
Shuo Qiandd210312017-04-12 22:11:33 +00006160 /**
6161 * Check if phone is in emergency callback mode
6162 * @return true if phone is in emergency callback mode
6163 * @param subId sub id
6164 */
goneil9c5f4872017-12-05 14:07:56 -08006165 @Override
Shuo Qiandd210312017-04-12 22:11:33 +00006166 public boolean getEmergencyCallbackMode(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07006167 enforceReadPrivilegedPermission("getEmergencyCallbackMode");
Shuo Qiandd210312017-04-12 22:11:33 +00006168 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006169
6170 final long identity = Binder.clearCallingIdentity();
6171 try {
6172 if (phone != null) {
6173 return phone.isInEcm();
6174 } else {
6175 return false;
6176 }
6177 } finally {
6178 Binder.restoreCallingIdentity(identity);
Shuo Qiandd210312017-04-12 22:11:33 +00006179 }
6180 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08006181
6182 /**
6183 * Get the current signal strength information for the given subscription.
6184 * Because this information is not updated when the device is in a low power state
6185 * it should not be relied-upon to be current.
6186 * @param subId Subscription index
6187 * @return the most recent cached signal strength info from the modem
6188 */
6189 @Override
6190 public SignalStrength getSignalStrength(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006191 final long identity = Binder.clearCallingIdentity();
6192 try {
6193 Phone p = getPhone(subId);
6194 if (p == null) {
6195 return null;
6196 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08006197
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006198 return p.getSignalStrength();
6199 } finally {
6200 Binder.restoreCallingIdentity(identity);
6201 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08006202 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00006203
Pengquan Meng77b7f132018-08-22 14:49:57 -07006204 /**
Chen Xuf792fd62018-10-17 17:54:36 +00006205 * Get the current modem radio state for the given slot.
6206 * @param slotIndex slot index.
6207 * @param callingPackage the name of the package making the call.
6208 * @return the current radio power state from the modem
6209 */
6210 @Override
6211 public int getRadioPowerState(int slotIndex, String callingPackage) {
6212 Phone phone = PhoneFactory.getPhone(slotIndex);
6213 if (phone != null) {
6214 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6215 mApp, phone.getSubId(), callingPackage, "getRadioPowerState")) {
6216 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
6217 }
6218
6219 final long identity = Binder.clearCallingIdentity();
6220 try {
6221 return phone.getRadioPowerState();
6222 } finally {
6223 Binder.restoreCallingIdentity(identity);
6224 }
6225 }
6226 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
6227 }
6228
6229 /**
Pengquan Meng77b7f132018-08-22 14:49:57 -07006230 * Checks if data roaming is enabled on the subscription with id {@code subId}.
6231 *
6232 * <p>Requires one of the following permissions:
6233 * {@link android.Manifest.permission#ACCESS_NETWORK_STATE},
6234 * {@link android.Manifest.permission#READ_PHONE_STATE} or that the calling app has carrier
6235 * privileges.
6236 *
6237 * @param subId subscription id
6238 * @return {@code true} if data roaming is enabled on this subscription, otherwise return
6239 * {@code false}.
6240 */
6241 @Override
6242 public boolean isDataRoamingEnabled(int subId) {
Pengquan Meng44e66f12019-04-01 10:48:20 -07006243 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
6244 null /* message */);
6245
Pengquan Menga1bb6272018-09-06 09:59:22 -07006246 boolean isEnabled = false;
6247 final long identity = Binder.clearCallingIdentity();
Pengquan Meng77b7f132018-08-22 14:49:57 -07006248 try {
Pengquan Menga1bb6272018-09-06 09:59:22 -07006249 Phone phone = getPhone(subId);
6250 isEnabled = phone != null ? phone.getDataRoamingEnabled() : false;
Pengquan Meng77b7f132018-08-22 14:49:57 -07006251 } catch (Exception e) {
6252 TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
6253 mApp, subId, "isDataRoamingEnabled");
Pengquan Menga1bb6272018-09-06 09:59:22 -07006254 } finally {
6255 Binder.restoreCallingIdentity(identity);
Pengquan Meng77b7f132018-08-22 14:49:57 -07006256 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07006257 return isEnabled;
Pengquan Meng77b7f132018-08-22 14:49:57 -07006258 }
6259
6260
6261 /**
6262 * Enables/Disables the data roaming on the subscription with id {@code subId}.
6263 *
6264 * <p> Requires permission:
6265 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the calling app has carrier
6266 * privileges.
6267 *
6268 * @param subId subscription id
6269 * @param isEnabled {@code true} means enable, {@code false} means disable.
6270 */
6271 @Override
6272 public void setDataRoamingEnabled(int subId, boolean isEnabled) {
Pengquan Meng44e66f12019-04-01 10:48:20 -07006273 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6274 mApp, subId, "setDataRoamingEnabled");
6275
Pengquan Menga1bb6272018-09-06 09:59:22 -07006276 final long identity = Binder.clearCallingIdentity();
6277 try {
Pengquan Menga1bb6272018-09-06 09:59:22 -07006278 Phone phone = getPhone(subId);
6279 if (phone != null) {
6280 phone.setDataRoamingEnabled(isEnabled);
6281 }
6282 } finally {
6283 Binder.restoreCallingIdentity(identity);
Pengquan Meng77b7f132018-08-22 14:49:57 -07006284 }
6285 }
6286
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00006287 @Override
Pengquan Meng6884a2c2018-10-03 12:19:13 -07006288 public boolean isManualNetworkSelectionAllowed(int subId) {
Pengquan Meng44e66f12019-04-01 10:48:20 -07006289 TelephonyPermissions.enforeceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
6290 mApp, subId, "isManualNetworkSelectionAllowed");
6291
Pengquan Meng6884a2c2018-10-03 12:19:13 -07006292 boolean isAllowed = true;
6293 final long identity = Binder.clearCallingIdentity();
6294 try {
Pengquan Meng6884a2c2018-10-03 12:19:13 -07006295 Phone phone = getPhone(subId);
6296 if (phone != null) {
6297 isAllowed = phone.isCspPlmnEnabled();
6298 }
6299 } finally {
6300 Binder.restoreCallingIdentity(identity);
6301 }
6302 return isAllowed;
6303 }
6304
6305 @Override
Jordan Liu75f43ea2019-01-17 16:56:37 -08006306 public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
Jordan Liuc65bc952019-02-12 17:54:02 -08006307 try {
6308 enforceReadPrivilegedPermission("getUiccCardsInfo");
6309 } catch (SecurityException e) {
6310 // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
6311 // has carrier privileges on an active UICC
6312 if (checkCarrierPrivilegesForPackageAnyPhone(callingPackage)
6313 != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
6314 throw new SecurityException("Caller does not have carrier privileges on any UICC");
6315 }
Jordan Liu75f43ea2019-01-17 16:56:37 -08006316 }
Jordan Liu5aa07002018-12-18 15:44:48 -08006317
6318 final long identity = Binder.clearCallingIdentity();
6319 try {
Jordan Liu75f43ea2019-01-17 16:56:37 -08006320 UiccController uiccController = UiccController.getInstance();
6321 ArrayList<UiccCardInfo> cardInfos = uiccController.getAllUiccCardInfos();
6322
6323 ApplicationInfo ai = mApp.getPackageManager().getApplicationInfo(callingPackage, 0);
6324 if ((ai.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
6325 // Remove private info if the caller doesn't have access
6326 ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
6327 for (UiccCardInfo cardInfo : cardInfos) {
6328 UiccCard card = uiccController.getUiccCard(cardInfo.getSlotIndex());
6329 UiccProfile profile = card.getUiccProfile();
6330 if (profile.getCarrierPrivilegeStatus(mApp.getPackageManager(), callingPackage)
6331 != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
6332 filteredInfos.add(cardInfo.getUnprivileged());
6333 } else {
6334 filteredInfos.add(cardInfo);
6335 }
6336 }
6337 return filteredInfos;
6338 }
6339 return cardInfos;
6340 } catch (PackageManager.NameNotFoundException e) {
6341 // This should not happen since we pass the package info in from TelephonyManager
6342 throw new SecurityException("Invalid calling package.");
Jordan Liu5aa07002018-12-18 15:44:48 -08006343 } finally {
6344 Binder.restoreCallingIdentity(identity);
6345 }
6346 }
6347
6348 @Override
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00006349 public UiccSlotInfo[] getUiccSlotsInfo() {
Brad Ebinger35c841c2018-10-01 10:40:55 -07006350 enforceReadPrivilegedPermission("getUiccSlotsInfo");
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00006351
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006352 final long identity = Binder.clearCallingIdentity();
6353 try {
6354 UiccSlot[] slots = UiccController.getInstance().getUiccSlots();
6355 if (slots == null) {
6356 Rlog.i(LOG_TAG, "slots is null.");
6357 return null;
6358 }
6359
6360 UiccSlotInfo[] infos = new UiccSlotInfo[slots.length];
6361 for (int i = 0; i < slots.length; i++) {
6362 UiccSlot slot = slots[i];
6363 if (slot == null) {
6364 continue;
6365 }
6366
6367 String cardId;
6368 UiccCard card = slot.getUiccCard();
6369 if (card != null) {
6370 cardId = card.getCardId();
6371 } else {
6372 cardId = slot.getIccId();
6373 }
6374
6375 int cardState = 0;
6376 switch (slot.getCardState()) {
6377 case CARDSTATE_ABSENT:
6378 cardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT;
6379 break;
6380 case CARDSTATE_PRESENT:
6381 cardState = UiccSlotInfo.CARD_STATE_INFO_PRESENT;
6382 break;
6383 case CARDSTATE_ERROR:
6384 cardState = UiccSlotInfo.CARD_STATE_INFO_ERROR;
6385 break;
6386 case CARDSTATE_RESTRICTED:
6387 cardState = UiccSlotInfo.CARD_STATE_INFO_RESTRICTED;
6388 break;
6389 default:
6390 break;
6391
6392 }
6393
6394 infos[i] = new UiccSlotInfo(
6395 slot.isActive(),
6396 slot.isEuicc(),
6397 cardId,
6398 cardState,
6399 slot.getPhoneId(),
Jordan Liua2619582019-02-14 12:56:40 -08006400 slot.isExtendedApduSupported(),
6401 slot.isRemovable());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006402 }
6403 return infos;
6404 } finally {
6405 Binder.restoreCallingIdentity(identity);
Holly Jiuyu Sun1d957c52018-04-04 13:52:42 -07006406 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00006407 }
6408
6409 @Override
6410 public boolean switchSlots(int[] physicalSlots) {
6411 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006412
6413 final long identity = Binder.clearCallingIdentity();
6414 try {
6415 return (Boolean) sendRequest(CMD_SWITCH_SLOTS, physicalSlots);
6416 } finally {
6417 Binder.restoreCallingIdentity(identity);
6418 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00006419 }
Jack Yu4c988042018-02-27 15:30:01 -08006420
6421 @Override
Jordan Liu7de49fa2018-12-06 14:48:49 -08006422 public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
Jordan Liu7de49fa2018-12-06 14:48:49 -08006423 final long identity = Binder.clearCallingIdentity();
6424 try {
6425 return UiccController.getInstance().getCardIdForDefaultEuicc();
6426 } finally {
6427 Binder.restoreCallingIdentity(identity);
6428 }
6429 }
6430
6431 @Override
Jack Yu4c988042018-02-27 15:30:01 -08006432 public void setRadioIndicationUpdateMode(int subId, int filters, int mode) {
6433 enforceModifyPermission();
6434 final Phone phone = getPhone(subId);
6435 if (phone == null) {
6436 loge("setRadioIndicationUpdateMode fails with invalid subId: " + subId);
6437 return;
6438 }
6439
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006440 final long identity = Binder.clearCallingIdentity();
6441 try {
6442 phone.setRadioIndicationUpdateMode(filters, mode);
6443 } finally {
6444 Binder.restoreCallingIdentity(identity);
6445 }
Jack Yu4c988042018-02-27 15:30:01 -08006446 }
Pengquan Meng85728fb2018-03-12 16:31:21 -07006447
6448 /**
goneil47ffb6e2018-04-06 15:40:58 -07006449 * A test API to reload the UICC profile.
6450 *
6451 * <p>Requires that the calling app has permission
6452 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
6453 * @hide
6454 */
6455 @Override
6456 public void refreshUiccProfile(int subId) {
6457 enforceModifyPermission();
6458
6459 final long identity = Binder.clearCallingIdentity();
6460 try {
6461 Phone phone = getPhone(subId);
6462 if (phone == null) {
6463 return;
6464 }
6465 UiccCard uiccCard = phone.getUiccCard();
6466 if (uiccCard == null) {
6467 return;
6468 }
6469 UiccProfile uiccProfile = uiccCard.getUiccProfile();
6470 if (uiccProfile == null) {
6471 return;
6472 }
6473 uiccProfile.refresh();
6474 } finally {
6475 Binder.restoreCallingIdentity(identity);
6476 }
6477 }
6478
6479 /**
Pengquan Meng85728fb2018-03-12 16:31:21 -07006480 * Returns false if the mobile data is disabled by default, otherwise return true.
6481 */
6482 private boolean getDefaultDataEnabled() {
6483 return "true".equalsIgnoreCase(
6484 SystemProperties.get(DEFAULT_MOBILE_DATA_PROPERTY_NAME, "true"));
6485 }
6486
6487 /**
6488 * Returns true if the data roaming is enabled by default, i.e the system property
6489 * of {@link #DEFAULT_DATA_ROAMING_PROPERTY_NAME} is true or the config of
6490 * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} is true.
6491 */
6492 private boolean getDefaultDataRoamingEnabled(int subId) {
6493 final CarrierConfigManager configMgr = (CarrierConfigManager)
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006494 mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Pengquan Meng85728fb2018-03-12 16:31:21 -07006495 boolean isDataRoamingEnabled = "true".equalsIgnoreCase(
6496 SystemProperties.get(DEFAULT_DATA_ROAMING_PROPERTY_NAME, "false"));
6497 isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
6498 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
6499 return isDataRoamingEnabled;
6500 }
6501
6502 /**
6503 * Returns the default network type for the given {@code subId}, if the default network type is
6504 * not set, return {@link Phone#PREFERRED_NT_MODE}.
6505 */
6506 private int getDefaultNetworkType(int subId) {
6507 return Integer.parseInt(
6508 TelephonyManager.getTelephonyProperty(
6509 mSubscriptionController.getPhoneId(subId),
6510 DEFAULT_NETWORK_MODE_PROPERTY_NAME,
6511 String.valueOf(Phone.PREFERRED_NT_MODE)));
6512 }
fionaxua13278b2018-03-21 00:08:13 -07006513
6514 @Override
6515 public void setCarrierTestOverride(int subId, String mccmnc, String imsi, String iccid, String
chen xueaba88a2019-03-15 13:15:10 -07006516 gid1, String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn) {
fionaxua13278b2018-03-21 00:08:13 -07006517 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006518
6519 final long identity = Binder.clearCallingIdentity();
6520 try {
6521 final Phone phone = getPhone(subId);
6522 if (phone == null) {
6523 loge("setCarrierTestOverride fails with invalid subId: " + subId);
6524 return;
6525 }
chen xueaba88a2019-03-15 13:15:10 -07006526 phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
6527 carrierPrivilegeRules, apn);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006528 } finally {
6529 Binder.restoreCallingIdentity(identity);
fionaxua13278b2018-03-21 00:08:13 -07006530 }
fionaxua13278b2018-03-21 00:08:13 -07006531 }
6532
6533 @Override
6534 public int getCarrierIdListVersion(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07006535 enforceReadPrivilegedPermission("getCarrierIdListVersion");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006536
6537 final long identity = Binder.clearCallingIdentity();
6538 try {
6539 final Phone phone = getPhone(subId);
6540 if (phone == null) {
6541 loge("getCarrierIdListVersion fails with invalid subId: " + subId);
6542 return TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION;
6543 }
6544 return phone.getCarrierIdListVersion();
6545 } finally {
6546 Binder.restoreCallingIdentity(identity);
fionaxua13278b2018-03-21 00:08:13 -07006547 }
fionaxua13278b2018-03-21 00:08:13 -07006548 }
Malcolm Chen2c63d402018-08-14 16:00:53 -07006549
6550 @Override
6551 public int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage) {
6552 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6553 mApp, subId, callingPackage, "getNumberOfModemsWithSimultaneousDataConnections")) {
6554 return -1;
6555 }
6556
6557 final long identity = Binder.clearCallingIdentity();
6558 try {
6559 return mPhoneConfigurationManager.getNumberOfModemsWithSimultaneousDataConnections();
6560 } finally {
6561 Binder.restoreCallingIdentity(identity);
6562 }
6563 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07006564
6565 @Override
6566 public int getCdmaRoamingMode(int subId) {
6567 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6568 mApp, subId, "getCdmaRoamingMode");
6569
6570 final long identity = Binder.clearCallingIdentity();
6571 try {
6572 return (int) sendRequest(CMD_GET_CDMA_ROAMING_MODE, null /* argument */, subId);
6573 } finally {
6574 Binder.restoreCallingIdentity(identity);
6575 }
6576 }
6577
6578 @Override
6579 public boolean setCdmaRoamingMode(int subId, int mode) {
6580 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6581 mApp, subId, "setCdmaRoamingMode");
6582
6583 final long identity = Binder.clearCallingIdentity();
6584 try {
6585 return (boolean) sendRequest(CMD_SET_CDMA_ROAMING_MODE, mode, subId);
6586 } finally {
6587 Binder.restoreCallingIdentity(identity);
6588 }
6589 }
6590
6591 @Override
6592 public boolean setCdmaSubscriptionMode(int subId, int mode) {
6593 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6594 mApp, subId, "setCdmaSubscriptionMode");
6595
6596 final long identity = Binder.clearCallingIdentity();
6597 try {
6598 return (boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION_MODE, mode, subId);
6599 } finally {
6600 Binder.restoreCallingIdentity(identity);
6601 }
6602 }
Makoto Onukida3bf792018-09-18 16:06:29 -07006603
6604 private void ensureUserRunning(int userId) {
6605 if (!mUserManager.isUserRunning(userId)) {
6606 throw new IllegalStateException("User " + userId + " does not exist or not running");
6607 }
6608 }
6609
6610 /**
6611 * Returns a list of SMS apps on a given user.
6612 *
6613 * Only the shell user (UID 2000 or 0) can call it.
6614 * Target user must be running.
6615 */
6616 @Override
6617 public String[] getSmsApps(int userId) {
6618 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getSmsApps");
6619 ensureUserRunning(userId);
6620
6621 final Collection<SmsApplicationData> apps =
6622 SmsApplication.getApplicationCollectionAsUser(mApp, userId);
6623
6624 String[] ret = new String[apps.size()];
6625 int i = 0;
6626 for (SmsApplicationData app : apps) {
6627 ret[i++] = app.mPackageName;
6628 }
6629 return ret;
6630 }
6631
6632 /**
6633 * Returns the default SMS app package name on a given user.
6634 *
6635 * Only the shell user (UID 2000 or 0) can call it.
6636 * Target user must be running.
6637 */
6638 @Override
6639 public String getDefaultSmsApp(int userId) {
6640 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getDefaultSmsApp");
6641 ensureUserRunning(userId);
6642
6643 final ComponentName cn = SmsApplication.getDefaultSmsApplicationAsUser(mApp,
6644 /* updateIfNeeded= */ true, userId);
6645 return cn == null ? null : cn.getPackageName();
6646 }
6647
6648 /**
6649 * Set a package as the default SMS app on a given user.
6650 *
6651 * Only the shell user (UID 2000 or 0) can call it.
6652 * Target user must be running.
6653 */
6654 @Override
6655 public void setDefaultSmsApp(int userId, String packageName) {
6656 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setDefaultSmsApp");
6657 ensureUserRunning(userId);
6658
6659 boolean found = false;
6660 for (String pkg : getSmsApps(userId)) {
6661 if (TextUtils.equals(packageName, pkg)) {
6662 found = true;
6663 break;
6664 }
6665 }
6666 if (!found) {
6667 throw new IllegalArgumentException("Package " + packageName + " is not an SMS app");
6668 }
6669
6670 SmsApplication.setDefaultApplicationAsUser(packageName, mApp, userId);
6671 }
sqianc5eccab2018-10-19 18:46:41 -07006672
6673 @Override
sqian8c685422019-02-22 15:55:18 -08006674 public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
sqianc5eccab2018-10-19 18:46:41 -07006675 String callingPackage) {
sqian11b7a0e2018-12-05 18:48:28 -08006676 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
sqian8c685422019-02-22 15:55:18 -08006677 mApp, getDefaultSubscription(), callingPackage, "getEmergencyNumberList")) {
sqian11b7a0e2018-12-05 18:48:28 -08006678 throw new SecurityException("Requires READ_PHONE_STATE permission.");
6679 }
6680 final long identity = Binder.clearCallingIdentity();
6681 try {
sqian854d44b2018-12-12 16:48:18 -08006682 Map<Integer, List<EmergencyNumber>> emergencyNumberListInternal = new HashMap<>();
6683 for (Phone phone: PhoneFactory.getPhones()) {
6684 if (phone.getEmergencyNumberTracker() != null
6685 && phone.getEmergencyNumberTracker().getEmergencyNumberList() != null) {
6686 emergencyNumberListInternal.put(
6687 phone.getSubId(),
6688 phone.getEmergencyNumberTracker().getEmergencyNumberList());
6689 }
sqian11b7a0e2018-12-05 18:48:28 -08006690 }
sqian854d44b2018-12-12 16:48:18 -08006691 return emergencyNumberListInternal;
sqian11b7a0e2018-12-05 18:48:28 -08006692 } finally {
6693 Binder.restoreCallingIdentity(identity);
6694 }
sqianc5eccab2018-10-19 18:46:41 -07006695 }
6696
6697 @Override
sqian8c685422019-02-22 15:55:18 -08006698 public boolean isEmergencyNumber(String number, boolean exactMatch) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006699 final Phone defaultPhone = getDefaultPhone();
sqian11b7a0e2018-12-05 18:48:28 -08006700 if (!exactMatch) {
6701 TelephonyPermissions
6702 .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
sqian8c685422019-02-22 15:55:18 -08006703 mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
sqian11b7a0e2018-12-05 18:48:28 -08006704 }
6705 final long identity = Binder.clearCallingIdentity();
6706 try {
sqian854d44b2018-12-12 16:48:18 -08006707 for (Phone phone: PhoneFactory.getPhones()) {
6708 if (phone.getEmergencyNumberTracker() != null
6709 && phone.getEmergencyNumberTracker() != null) {
6710 if (phone.getEmergencyNumberTracker().isEmergencyNumber(
6711 number, exactMatch)) {
6712 return true;
sqian11b7a0e2018-12-05 18:48:28 -08006713 }
6714 }
sqian11b7a0e2018-12-05 18:48:28 -08006715 }
6716 return false;
6717 } finally {
6718 Binder.restoreCallingIdentity(identity);
6719 }
6720 }
6721
sqianf4ca7ed2019-01-15 18:32:07 -08006722 /**
6723 * Update emergency number list for test mode.
6724 */
6725 @Override
6726 public void updateEmergencyNumberListTestMode(int action, EmergencyNumber num) {
6727 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
6728 "updateEmergencyNumberListTestMode");
6729
6730 final long identity = Binder.clearCallingIdentity();
6731 try {
6732 for (Phone phone: PhoneFactory.getPhones()) {
6733 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
6734 if (tracker != null) {
6735 tracker.executeEmergencyNumberTestModeCommand(action, num);
6736 }
6737 }
6738 } finally {
6739 Binder.restoreCallingIdentity(identity);
6740 }
6741 }
6742
6743 /**
6744 * Get the full emergency number list for test mode.
6745 */
6746 @Override
6747 public List<String> getEmergencyNumberListTestMode() {
6748 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
6749 "getEmergencyNumberListTestMode");
6750
6751 final long identity = Binder.clearCallingIdentity();
6752 try {
6753 Set<String> emergencyNumbers = new HashSet<>();
6754 for (Phone phone: PhoneFactory.getPhones()) {
6755 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
6756 if (tracker != null) {
6757 for (EmergencyNumber num : tracker.getEmergencyNumberList()) {
6758 emergencyNumbers.add(num.getNumber());
6759 }
6760 }
6761 }
6762 return new ArrayList<>(emergencyNumbers);
6763 } finally {
6764 Binder.restoreCallingIdentity(identity);
6765 }
6766 }
6767
chen xud6b45bd2018-10-30 22:27:10 -07006768 @Override
6769 public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
6770 enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
6771 Phone phone = getPhone(subId);
6772 if (phone == null) {
6773 return null;
6774 }
6775 final long identity = Binder.clearCallingIdentity();
6776 try {
6777 UiccProfile profile = UiccController.getInstance()
6778 .getUiccProfileForPhone(phone.getPhoneId());
6779 if (profile != null) {
6780 return profile.getCertsFromCarrierPrivilegeAccessRules();
6781 }
6782 } finally {
6783 Binder.restoreCallingIdentity(identity);
6784 }
6785 return null;
6786 }
Malcolm Chen8e4ed912019-01-15 20:22:16 -08006787
6788 /**
6789 * Enable or disable a modem stack.
6790 */
6791 @Override
6792 public boolean enableModemForSlot(int slotIndex, boolean enable) {
6793 enforceModifyPermission();
6794
6795 final long identity = Binder.clearCallingIdentity();
6796 try {
6797 Phone phone = PhoneFactory.getPhone(slotIndex);
6798 if (phone == null) {
6799 return false;
6800 } else {
6801 return (Boolean) sendRequest(CMD_REQUEST_ENABLE_MODEM, enable, phone, null);
6802 }
6803 } finally {
6804 Binder.restoreCallingIdentity(identity);
6805 }
6806 }
Michelecea4cf22018-12-21 15:00:11 -08006807
Malcolm Chen4bcd9822019-03-27 18:34:05 -07006808 /**
6809 * Whether a modem stack is enabled or not.
6810 */
6811 @Override
6812 public boolean isModemEnabledForSlot(int slotIndex, String callingPackage) {
6813 Phone phone = PhoneFactory.getPhone(slotIndex);
6814 if (phone == null) return false;
6815
6816 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6817 mApp, phone.getSubId(), callingPackage, "isModemEnabledForSlot")) {
6818 throw new SecurityException("Requires READ_PHONE_STATE permission.");
6819 }
6820
6821 final long identity = Binder.clearCallingIdentity();
6822 try {
6823 return PhoneConfigurationManager.getInstance().getPhoneStatus(phone);
6824 } finally {
6825 Binder.restoreCallingIdentity(identity);
6826 }
6827 }
6828
Michelecea4cf22018-12-21 15:00:11 -08006829 @Override
Michele0ea7d782019-03-19 14:58:42 -07006830 public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
Michelecea4cf22018-12-21 15:00:11 -08006831 enforceModifyPermission();
6832
6833 final long identity = Binder.clearCallingIdentity();
6834 try {
6835 mTelephonySharedPreferences.edit()
Michele0ea7d782019-03-19 14:58:42 -07006836 .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultiSimCarrierRestricted)
Michelecea4cf22018-12-21 15:00:11 -08006837 .commit();
6838 } finally {
6839 Binder.restoreCallingIdentity(identity);
6840 }
6841 }
6842
6843 @Override
Michele0ea7d782019-03-19 14:58:42 -07006844 @TelephonyManager.IsMultiSimSupportedResult
6845 public int isMultiSimSupported(String callingPackage) {
Michele4245e952019-02-04 11:36:23 -08006846 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp,
Michele0ea7d782019-03-19 14:58:42 -07006847 getDefaultPhone().getSubId(), callingPackage, "isMultiSimSupported")) {
6848 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele4245e952019-02-04 11:36:23 -08006849 }
Michelecea4cf22018-12-21 15:00:11 -08006850
6851 final long identity = Binder.clearCallingIdentity();
6852 try {
Michele0ea7d782019-03-19 14:58:42 -07006853 return isMultiSimSupportedInternal();
Michelecea4cf22018-12-21 15:00:11 -08006854 } finally {
6855 Binder.restoreCallingIdentity(identity);
6856 }
6857 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -08006858
Michele0ea7d782019-03-19 14:58:42 -07006859 @TelephonyManager.IsMultiSimSupportedResult
6860 private int isMultiSimSupportedInternal() {
Michele30b57b22019-03-01 12:01:14 -08006861 // If the device has less than 2 SIM cards, indicate that multisim is restricted.
6862 int numPhysicalSlots = UiccController.getInstance().getUiccSlots().length;
6863 if (numPhysicalSlots < 2) {
Michele0ea7d782019-03-19 14:58:42 -07006864 loge("isMultiSimSupportedInternal: requires at least 2 cards");
6865 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -08006866 }
6867 // Check if the hardware supports multisim functionality. If usage of multisim is not
6868 // supported by the modem, indicate that it is restricted.
6869 PhoneCapability staticCapability =
6870 mPhoneConfigurationManager.getStaticPhoneCapability();
6871 if (staticCapability == null) {
Michele0ea7d782019-03-19 14:58:42 -07006872 loge("isMultiSimSupportedInternal: no static configuration available");
6873 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -08006874 }
6875 if (staticCapability.logicalModemList.size() < 2) {
Michele0ea7d782019-03-19 14:58:42 -07006876 loge("isMultiSimSupportedInternal: maximum number of modem is < 2");
6877 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -08006878 }
6879 // Check if support of multiple SIMs is restricted by carrier
6880 if (mTelephonySharedPreferences.getBoolean(PREF_MULTI_SIM_RESTRICTED, false)) {
Michele0ea7d782019-03-19 14:58:42 -07006881 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_CARRIER;
Michele30b57b22019-03-01 12:01:14 -08006882 }
6883
Michele0ea7d782019-03-19 14:58:42 -07006884 return TelephonyManager.MULTISIM_ALLOWED;
Michele30b57b22019-03-01 12:01:14 -08006885 }
6886
Nazanin Bakhshi628473f2019-01-29 17:37:52 -08006887 /**
6888 * Switch configs to enable multi-sim or switch back to single-sim
Nazanin Bakhshi17318782019-03-01 11:56:08 -08006889 * Note: Switch from multi-sim to single-sim is only possible with MODIFY_PHONE_STATE
6890 * permission, but the other way around is possible with either MODIFY_PHONE_STATE
6891 * or carrier privileges
Nazanin Bakhshi628473f2019-01-29 17:37:52 -08006892 * @param numOfSims number of active sims we want to switch to
6893 */
6894 @Override
6895 public void switchMultiSimConfig(int numOfSims) {
Nazanin Bakhshi17318782019-03-01 11:56:08 -08006896 if (numOfSims == 1) {
6897 enforceModifyPermission();
6898 } else {
6899 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6900 mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
6901 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -08006902 final long identity = Binder.clearCallingIdentity();
Michele30b57b22019-03-01 12:01:14 -08006903
Nazanin Bakhshi628473f2019-01-29 17:37:52 -08006904 try {
Michele30b57b22019-03-01 12:01:14 -08006905 //only proceed if multi-sim is not restricted
Michele0ea7d782019-03-19 14:58:42 -07006906 if (isMultiSimSupportedInternal() != TelephonyManager.MULTISIM_ALLOWED) {
Michele30b57b22019-03-01 12:01:14 -08006907 loge("switchMultiSimConfig not possible. It is restricted or not supported.");
6908 return;
6909 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -08006910 mPhoneConfigurationManager.switchMultiSimConfig(numOfSims);
6911 } finally {
6912 Binder.restoreCallingIdentity(identity);
6913 }
6914 }
6915
6916 /**
chen xub4baa772019-04-03 10:23:41 -07006917 * Get whether making changes to modem configurations will trigger reboot.
6918 * Return value defaults to true.
Nazanin Bakhshi5fe5ef22019-01-30 10:52:09 -08006919 */
6920 @Override
chen xub4baa772019-04-03 10:23:41 -07006921 public boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage) {
6922 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6923 mApp, subId, callingPackage, "doesSwitchMultiSimConfigTriggerReboot")) {
6924 return false;
6925 }
Nazanin Bakhshi5fe5ef22019-01-30 10:52:09 -08006926 final long identity = Binder.clearCallingIdentity();
6927 try {
6928 return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
6929 } finally {
6930 Binder.restoreCallingIdentity(identity);
6931 }
6932 }
6933
Nathan Harold29f5f052019-02-15 13:41:57 -08006934 private void updateModemStateMetrics() {
6935 TelephonyMetrics metrics = TelephonyMetrics.getInstance();
6936 // TODO: check the state for each modem if the api is ready.
6937 metrics.updateEnabledModemBitmap((1 << TelephonyManager.from(mApp).getPhoneCount()) - 1);
6938 }
6939
Pengquan Meng3889a572019-01-23 11:16:29 -08006940 @Override
6941 public int[] getSlotsMapping() {
6942 enforceReadPrivilegedPermission("getSlotsMapping");
6943
6944 final long identity = Binder.clearCallingIdentity();
6945 try {
6946 int phoneCount = TelephonyManager.getDefault().getPhoneCount();
6947 // All logical slots should have a mapping to a physical slot.
6948 int[] logicalSlotsMapping = new int[phoneCount];
6949 UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
6950 for (int i = 0; i < slotInfos.length; i++) {
6951 if (SubscriptionManager.isValidPhoneId(slotInfos[i].getLogicalSlotIdx())) {
6952 logicalSlotsMapping[slotInfos[i].getLogicalSlotIdx()] = i;
6953 }
6954 }
6955 return logicalSlotsMapping;
6956 } finally {
6957 Binder.restoreCallingIdentity(identity);
6958 }
6959 }
Nathan Harold48d6fd52019-02-06 19:01:40 -08006960
6961 /**
6962 * Get the IRadio HAL Version
6963 */
6964 @Override
6965 public int getRadioHalVersion() {
6966 Phone phone = getDefaultPhone();
6967 if (phone == null) return -1;
6968 HalVersion hv = phone.getHalVersion();
6969 if (hv.equals(HalVersion.UNKNOWN)) return -1;
6970 return hv.major * 100 + hv.minor;
6971 }
Malcolm Chendc8c10e2019-04-10 18:25:07 -07006972
6973 /**
6974 * Mms is allowed if
6975 * 1) user data is turned on, or
6976 * 2) Mms is un-metered, or
6977 * 3) alwaysAllowMms setting is turned on.
6978 */
6979 @Override
6980 public boolean isMmsDataEnabled(int subId, String callingPackage) {
6981 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6982 mApp, subId, callingPackage, "isMmsDataEnabled")) {
6983 throw new SecurityException("Needs READ_PHONE_STATE for isMmsDataEnabled");
6984 }
6985
6986 // Now that all security checks passes, perform the operation as ourselves.
6987 final long identity = Binder.clearCallingIdentity();
6988 try {
6989 Phone phone = getPhone(subId);
6990 if (phone == null) return false;
6991
6992 boolean isMetered = ApnSettingUtils.isMeteredApnType(ApnSetting.getApnTypeString(
6993 TYPE_MMS), phone);
6994 return !isMetered || phone.getDataEnabledSettings().isDataEnabled(TYPE_MMS);
6995 } finally {
6996 Binder.restoreCallingIdentity(identity);
6997 }
6998 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006999}