blob: cf320693b85d410be3f449002b4a78466c906980 [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;
Gil Cukierman1c0eb932022-12-06 22:28:24 +000020import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
jimsunf9ec1622022-09-13 21:18:43 +080021import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO;
Hall Liud892bec2018-11-30 14:51:45 -080022
Shuo Qianccbaf742021-02-22 18:32:21 -080023import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
24import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
Tyler Gunn7bcdc742019-10-04 15:56:59 -070025import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_IMS;
Ta-wei Yen87c49842016-05-13 21:19:52 -070026import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
joonhunshin3e154242021-09-17 06:33:39 +000027import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT;
Ta-wei Yen87c49842016-05-13 21:19:52 -070028
Brad Ebinger34c09a52021-02-17 23:23:21 +000029import android.Manifest;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080030import android.Manifest.permission;
Hall Liua1548bd2019-12-24 14:14:12 -080031import android.annotation.NonNull;
Tyler Gunnf70ed162019-04-03 15:28:53 -070032import android.annotation.Nullable;
sandeepjsb6c87872021-09-27 15:34:44 +000033import android.annotation.RequiresPermission;
Sarah Chin532d6bb2022-12-28 22:50:43 -080034import android.app.ActivityManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070035import android.app.AppOpsManager;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080036import android.app.PendingIntent;
Tyler Gunn64144d92022-03-17 14:16:41 -070037import android.app.PropertyInvalidatedCache;
Brad Ebinger4f6208e2021-03-23 21:04:45 +000038import android.app.compat.CompatChanges;
Hall Liu82694d52020-12-11 18:22:04 -080039import android.app.role.RoleManager;
sandeepjsb6c87872021-09-27 15:34:44 +000040import android.compat.annotation.ChangeId;
41import android.compat.annotation.EnabledSince;
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -070042import android.content.ComponentName;
Amit Mahajan7dbbd822019-03-13 17:33:47 -070043import android.content.ContentResolver;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070044import android.content.Context;
45import android.content.Intent;
Derek Tan97ebb422014-09-05 16:55:38 -070046import android.content.SharedPreferences;
Derek Tan740e1672017-06-27 14:56:27 -070047import android.content.pm.ComponentInfo;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070048import android.content.pm.PackageManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070049import android.net.Uri;
50import android.os.AsyncResult;
51import android.os.Binder;
Hall Liuf19c44f2018-11-27 14:38:17 -080052import android.os.Build;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070053import android.os.Bundle;
Thomas Nguyen8ee49682023-02-01 11:46:09 -080054import android.os.CancellationSignal;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070055import android.os.Handler;
yinxu504e1392017-04-12 16:03:22 -070056import android.os.IBinder;
Thomas Nguyen8ee49682023-02-01 11:46:09 -080057import android.os.ICancellationSignal;
tom hsu0b59d292022-09-29 23:49:21 +080058import android.os.LocaleList;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070059import android.os.Looper;
60import android.os.Message;
yinxu504e1392017-04-12 16:03:22 -070061import android.os.Messenger;
Hall Liua1548bd2019-12-24 14:14:12 -080062import android.os.ParcelFileDescriptor;
Malcolm Chen6ca97372019-07-01 16:28:21 -070063import android.os.ParcelUuid;
Tyler Gunn65d45c22017-06-05 11:22:26 -070064import android.os.PersistableBundle;
Shuo Qiancd19c462020-01-16 20:51:11 -080065import android.os.Process;
Brad Ebinger5f64b052017-12-14 14:26:15 -080066import android.os.RemoteException;
Adam Lesinski903a54c2016-04-11 14:49:52 -070067import android.os.ResultReceiver;
Brad Ebinger1ce9c432019-07-16 13:19:44 -070068import android.os.ServiceSpecificException;
Rambo Wang0f050d82021-02-12 11:43:36 -080069import android.os.SystemClock;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070070import android.os.UserHandle;
Stuart Scott981d8582015-04-21 14:09:50 -070071import android.os.UserManager;
Sooraj Sasindran9a909312016-07-18 11:57:25 -070072import android.os.WorkSource;
Derek Tan97ebb422014-09-05 16:55:38 -070073import android.preference.PreferenceManager;
Naina Nallurid63128d2019-09-17 14:10:30 -070074import android.provider.DeviceConfig;
Ihab Awadf2177b72013-11-25 13:33:23 -080075import android.provider.Settings;
Amit Mahajan7dbbd822019-03-13 17:33:47 -070076import android.provider.Telephony;
arunvoddud7401012022-12-15 16:08:12 +000077import android.service.carrier.CarrierIdentifier;
Inseob Kim14bb3d02018-12-13 17:11:34 +090078import android.sysprop.TelephonyProperties;
Santos Cordon7a1885b2015-02-03 11:15:19 -080079import android.telecom.PhoneAccount;
Nancy Chen31f9ba12016-01-06 11:42:12 -080080import android.telecom.PhoneAccountHandle;
Andrew Lee9431b832015-03-09 18:46:45 -070081import android.telecom.TelecomManager;
Gary Jian3aa9a762022-01-24 16:41:19 +080082import android.telephony.AccessNetworkConstants;
83import android.telephony.ActivityStatsTechSpecificInfo;
Chen Xu227e06f2019-09-26 22:48:11 -070084import android.telephony.Annotation.ApnType;
Jack Yu0eda6842022-04-18 00:34:46 -070085import android.telephony.Annotation.DataActivityType;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080086import android.telephony.Annotation.ThermalMitigationResult;
Sarah Chin2ec39f62022-08-31 17:03:26 -070087import android.telephony.AnomalyReporter;
Shuo Qian4a594052020-01-23 11:59:30 -080088import android.telephony.CallForwardingInfo;
Junda Liu12f7d802015-05-01 12:06:44 -070089import android.telephony.CarrierConfigManager;
Michele Berionne482f8202018-11-27 18:57:59 -080090import android.telephony.CarrierRestrictionRules;
Hui Wang9b5793a2022-12-05 14:38:06 -060091import android.telephony.CellBroadcastIdRange;
yincheng zhao2737e882019-09-06 17:06:54 -070092import android.telephony.CellIdentity;
Meng Wanga10e89e2019-12-09 13:13:01 -080093import android.telephony.CellIdentityCdma;
94import android.telephony.CellIdentityGsm;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070095import android.telephony.CellInfo;
Nathan Haroldf180aac2018-06-01 18:43:55 -070096import android.telephony.CellInfoGsm;
97import android.telephony.CellInfoWcdma;
Sooraj Sasindran9a909312016-07-18 11:57:25 -070098import android.telephony.ClientRequestStats;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080099import android.telephony.DataThrottlingRequest;
Hui Wang641e81c2020-10-12 12:14:23 -0700100import android.telephony.IBootstrapAuthenticationCallback;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -0700101import android.telephony.ICellInfoCallback;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700102import android.telephony.IccOpenLogicalChannelResponse;
Hall Liu1aa510f2017-11-22 17:40:08 -0800103import android.telephony.LocationAccessPolicy;
Ta-wei Yen87c49842016-05-13 21:19:52 -0700104import android.telephony.ModemActivityInfo;
Jake Hambye994d462014-02-03 13:10:13 -0800105import android.telephony.NeighboringCellInfo;
yinxu504e1392017-04-12 16:03:22 -0700106import android.telephony.NetworkScanRequest;
Michele4245e952019-02-04 11:36:23 -0800107import android.telephony.PhoneCapability;
Hall Liud892bec2018-11-30 14:51:45 -0800108import android.telephony.PhoneNumberRange;
Wink Saville5d475dd2014-10-17 15:00:58 -0700109import android.telephony.RadioAccessFamily;
Hall Liub2ac8ef2019-02-28 15:56:23 -0800110import android.telephony.RadioAccessSpecifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700111import android.telephony.ServiceState;
Nathan Harold46b42aa2017-03-10 19:38:22 -0800112import android.telephony.SignalStrength;
Rambo Wanga5cc9b72021-01-07 10:51:54 -0800113import android.telephony.SignalStrengthUpdateRequest;
114import android.telephony.SignalThresholdInfo;
Wink Saville0f3b5fc2014-11-11 08:40:49 -0800115import android.telephony.SubscriptionInfo;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800116import android.telephony.SubscriptionManager;
Peter Wangc035ce42020-01-08 21:00:22 -0800117import android.telephony.TelephonyFrameworkInitializer;
Sanket Padawe99ef1e32016-05-18 16:12:33 -0700118import android.telephony.TelephonyHistogram;
Ta-wei Yenb6929602016-05-24 15:48:27 -0700119import android.telephony.TelephonyManager;
Jack Yuf5badd92022-12-08 00:50:53 -0800120import android.telephony.TelephonyManager.SimState;
Hall Liub2ac8ef2019-02-28 15:56:23 -0800121import android.telephony.TelephonyScanManager;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800122import android.telephony.ThermalMitigationRequest;
Jordan Liu5aa07002018-12-18 15:44:48 -0800123import android.telephony.UiccCardInfo;
sandeepjsb6c87872021-09-27 15:34:44 +0000124import android.telephony.UiccPortInfo;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000125import android.telephony.UiccSlotInfo;
sandeepjsb6c87872021-09-27 15:34:44 +0000126import android.telephony.UiccSlotMapping;
Tyler Gunn65d45c22017-06-05 11:22:26 -0700127import android.telephony.UssdResponse;
Ta-wei Yenb6929602016-05-24 15:48:27 -0700128import android.telephony.VisualVoicemailSmsFilterSettings;
Hongbo Zeng0e18b162021-04-07 16:52:18 +0800129import android.telephony.data.NetworkSlicingConfig;
Jack Yub5d8f642018-11-26 11:20:48 -0800130import android.telephony.emergency.EmergencyNumber;
Hui Wang641e81c2020-10-12 12:14:23 -0700131import android.telephony.gba.GbaAuthRequest;
132import android.telephony.gba.UaSecurityProtocolIdentifier;
Brad Ebinger1ce9c432019-07-16 13:19:44 -0700133import android.telephony.ims.ImsException;
Brad Ebinger1c8542e2019-01-14 13:43:14 -0800134import android.telephony.ims.ProvisioningManager;
Hui Wang761a6682020-10-31 05:12:53 +0000135import android.telephony.ims.RcsClientConfiguration;
Brad Ebinger14d467f2021-02-12 06:18:28 +0000136import android.telephony.ims.RcsContactUceCapability;
Brad Ebingera34a6c22019-10-22 17:36:18 -0700137import android.telephony.ims.RegistrationManager;
joonhunshincffb7fc2021-11-28 07:32:01 +0000138import android.telephony.ims.aidl.IFeatureProvisioningCallback;
Brad Ebinger35c841c2018-10-01 10:40:55 -0700139import android.telephony.ims.aidl.IImsCapabilityCallback;
Brad Ebinger22bc3e42018-01-16 09:39:35 -0800140import android.telephony.ims.aidl.IImsConfig;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -0700141import android.telephony.ims.aidl.IImsConfigCallback;
Brad Ebinger22bc3e42018-01-16 09:39:35 -0800142import android.telephony.ims.aidl.IImsRegistration;
Brad Ebinger35c841c2018-10-01 10:40:55 -0700143import android.telephony.ims.aidl.IImsRegistrationCallback;
Hui Wang761a6682020-10-31 05:12:53 +0000144import android.telephony.ims.aidl.IRcsConfigCallback;
Brad Ebingerbc7dd582019-10-17 17:03:22 -0700145import android.telephony.ims.feature.ImsFeature;
Brad Ebinger1c8542e2019-01-14 13:43:14 -0800146import android.telephony.ims.stub.ImsConfigImplBase;
Brad Ebinger1f2b5082018-02-08 16:11:32 -0800147import android.telephony.ims.stub.ImsRegistrationImplBase;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800148import android.telephony.satellite.ISatelliteStateListener;
Sarah Chineccfbd12023-01-20 19:00:35 -0800149import android.telephony.satellite.PointingInfo;
Aishwarya Mallampati224317a2023-02-13 22:09:30 +0000150import android.telephony.satellite.SatelliteCallback;
Sarah Chin503828c2023-02-01 23:54:20 -0800151import android.telephony.satellite.SatelliteCapabilities;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000152import android.telephony.satellite.SatelliteDatagram;
Sarah Chineccfbd12023-01-20 19:00:35 -0800153import android.telephony.satellite.SatelliteManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700154import android.text.TextUtils;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800155import android.util.ArraySet;
Hall Liud60acc92020-05-21 17:09:35 -0700156import android.util.EventLog;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700157import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -0800158import android.util.Pair;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800159
Andrew Lee312e8172014-10-23 17:01:36 -0700160import com.android.ims.ImsManager;
Brad Ebinger34bef922017-11-09 10:27:08 -0800161import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Linbcdf8b32021-01-14 16:44:13 +0800162import com.android.ims.rcs.uce.eab.EabUtil;
SongFerngWangfd89b102021-05-27 22:44:54 +0800163import com.android.internal.annotations.VisibleForTesting;
Shuo Qian4a594052020-01-23 11:59:30 -0800164import com.android.internal.telephony.CallForwardInfo;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700165import com.android.internal.telephony.CallManager;
Tyler Gunn52dcf772017-04-26 11:30:31 -0700166import com.android.internal.telephony.CallStateException;
Tyler Gunnd4339262021-05-03 14:46:49 -0700167import com.android.internal.telephony.CallTracker;
Rambo Wang9c9ffdd2022-01-13 21:51:44 -0800168import com.android.internal.telephony.CarrierPrivilegesTracker;
chen xu651eec72018-11-11 19:03:44 -0800169import com.android.internal.telephony.CarrierResolver;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700170import com.android.internal.telephony.CellNetworkScanResult;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700171import com.android.internal.telephony.CommandException;
Shuo Qian4a594052020-01-23 11:59:30 -0800172import com.android.internal.telephony.CommandsInterface;
Hui Wang641e81c2020-10-12 12:14:23 -0700173import com.android.internal.telephony.GbaManager;
Shuo Qianccbaf742021-02-22 18:32:21 -0800174import com.android.internal.telephony.GsmCdmaPhone;
Nathan Harold48d6fd52019-02-06 19:01:40 -0800175import com.android.internal.telephony.HalVersion;
Hall Liu73f5d362020-01-20 13:42:00 -0800176import com.android.internal.telephony.IBooleanConsumer;
Hall Liu27d24262020-09-18 19:04:59 -0700177import com.android.internal.telephony.ICallForwardingInfoCallback;
Hunsuk Choi3b742d62021-10-25 19:48:34 +0000178import com.android.internal.telephony.IImsStateCallback;
Brad Ebingera63db5f2019-04-23 16:31:13 -0700179import com.android.internal.telephony.IIntegerConsumer;
Hall Liud892bec2018-11-30 14:51:45 -0800180import com.android.internal.telephony.INumberVerificationCallback;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700181import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -0800182import com.android.internal.telephony.IccCard;
Jack Yuf5badd92022-12-08 00:50:53 -0800183import com.android.internal.telephony.IccCardConstants;
Rambo Wanga1782702021-11-10 20:15:19 -0800184import com.android.internal.telephony.IccLogicalChannelRequest;
Jack Yu5f7092c2018-04-13 14:05:37 -0700185import com.android.internal.telephony.LocaleTracker;
yinxub1bed742017-04-17 11:45:04 -0700186import com.android.internal.telephony.NetworkScanRequestTracker;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700187import com.android.internal.telephony.OperatorInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700188import com.android.internal.telephony.Phone;
Malcolm Chen2c63d402018-08-14 16:00:53 -0700189import com.android.internal.telephony.PhoneConfigurationManager;
Nathan Harolda667c152016-12-14 11:27:20 -0800190import com.android.internal.telephony.PhoneConstantConversions;
Ta-wei Yen87c49842016-05-13 21:19:52 -0700191import com.android.internal.telephony.PhoneConstants;
Wink Saville36469e72014-06-11 15:17:00 -0700192import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -0700193import com.android.internal.telephony.ProxyController;
Sanket Padawe99ef1e32016-05-18 16:12:33 -0700194import com.android.internal.telephony.RIL;
SongFerngWang8c6e82e2021-03-02 22:09:29 +0800195import com.android.internal.telephony.RILConstants;
Sarah Chineccfbd12023-01-20 19:00:35 -0800196import com.android.internal.telephony.RILUtils;
Daniel Bright94f43662021-03-01 14:43:40 -0800197import com.android.internal.telephony.RadioInterfaceCapabilityController;
Jack Yu5f7092c2018-04-13 14:05:37 -0700198import com.android.internal.telephony.ServiceStateTracker;
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +0000199import com.android.internal.telephony.SmsApplication;
Amit Mahajandccb3f12019-05-13 13:48:32 -0700200import com.android.internal.telephony.SmsController;
Brad Ebingera63db5f2019-04-23 16:31:13 -0700201import com.android.internal.telephony.SmsPermissions;
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800202import com.android.internal.telephony.SubscriptionController;
Peter Wang59571be2020-01-27 12:35:15 +0800203import com.android.internal.telephony.TelephonyIntents;
Jeff Davidson7e17e312018-02-13 18:17:36 -0800204import com.android.internal.telephony.TelephonyPermissions;
Jack Yu27422a52022-03-21 10:38:05 -0700205import com.android.internal.telephony.data.DataUtils;
Hunsuk Choi42cc62a2022-10-16 06:03:40 +0000206import com.android.internal.telephony.domainselection.DomainSelectionResolver;
sqianf4ca7ed2019-01-15 18:32:07 -0800207import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Derek Tan740e1672017-06-27 14:56:27 -0700208import com.android.internal.telephony.euicc.EuiccConnector;
Brad Ebinger9c0eb502019-01-23 15:06:19 -0800209import com.android.internal.telephony.ims.ImsResolver;
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700210import com.android.internal.telephony.imsphone.ImsPhone;
211import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
joonhunshin3e154242021-09-17 06:33:39 +0000212import com.android.internal.telephony.metrics.RcsStats;
Pengquan Meng6c2dc9f2019-02-06 11:12:53 -0800213import com.android.internal.telephony.metrics.TelephonyMetrics;
Jack Yu285100e2022-12-02 22:48:35 -0800214import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
215import com.android.internal.telephony.subscription.SubscriptionManagerService;
Meng Wangafbc5852019-09-19 17:37:13 -0700216import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700217import com.android.internal.telephony.uicc.IccIoResult;
218import com.android.internal.telephony.uicc.IccUtils;
Nathan Haroldb3014052017-01-25 15:57:32 -0800219import com.android.internal.telephony.uicc.SIMRecords;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700220import com.android.internal.telephony.uicc.UiccCard;
Nathan Haroldb3014052017-01-25 15:57:32 -0800221import com.android.internal.telephony.uicc.UiccCardApplication;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700222import com.android.internal.telephony.uicc.UiccController;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000223import com.android.internal.telephony.uicc.UiccPort;
Jeff Davidson7e17e312018-02-13 18:17:36 -0800224import com.android.internal.telephony.uicc.UiccProfile;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000225import com.android.internal.telephony.uicc.UiccSlot;
zoey chenc730df82019-12-18 17:07:20 +0800226import com.android.internal.telephony.util.LocaleUtils;
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +0000227import com.android.internal.telephony.util.TelephonyUtils;
fionaxu7ed723d2017-05-30 18:58:54 -0700228import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
Hall Liu27d24262020-09-18 19:04:59 -0700229import com.android.internal.util.FunctionalUtils;
Jake Hambye994d462014-02-03 13:10:13 -0800230import com.android.internal.util.HexDump;
Hall Liuaa4211e2021-01-20 15:43:39 -0800231import com.android.phone.callcomposer.CallComposerPictureManager;
232import com.android.phone.callcomposer.CallComposerPictureTransfer;
233import com.android.phone.callcomposer.ImageData;
Brad Ebingera63db5f2019-04-23 16:31:13 -0700234import com.android.phone.settings.PickSmsSubscriptionActivity;
Sarah Chin46355ba2022-11-01 23:51:16 -0700235import com.android.phone.slice.SlicePurchaseController;
arunvoddud7401012022-12-15 16:08:12 +0000236import com.android.phone.utils.CarrierAllowListInfo;
Ta-wei Yenc9df0432017-04-17 17:09:07 -0700237import com.android.phone.vvm.PhoneAccountHandleConverter;
Ta-wei Yen527a9c02017-01-06 15:29:25 -0800238import com.android.phone.vvm.RemoteVvmTaskManager;
Ta-wei Yenc9df0432017-04-17 17:09:07 -0700239import com.android.phone.vvm.VisualVoicemailSettingsUtil;
Ta-wei Yenc8905312017-03-28 11:14:45 -0700240import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800241import com.android.services.telephony.TelecomAccountRegistry;
242import com.android.services.telephony.TelephonyConnectionService;
Peter Wang44b186e2020-01-13 23:33:09 -0800243import com.android.telephony.Rlog;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800244
Hall Liu82694d52020-12-11 18:22:04 -0800245import java.io.ByteArrayOutputStream;
Ta-wei Yenc236d6b2016-06-21 13:33:12 -0700246import java.io.FileDescriptor;
Hall Liu82694d52020-12-11 18:22:04 -0800247import java.io.IOException;
248import java.io.InputStream;
Ta-wei Yenc236d6b2016-06-21 13:33:12 -0700249import java.io.PrintWriter;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700250import java.util.ArrayList;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800251import java.util.Arrays;
Muralidhar Reddyeb809e32021-11-19 03:07:54 +0000252import java.util.Collection;
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -0800253import java.util.Collections;
sqian11b7a0e2018-12-05 18:48:28 -0800254import java.util.HashMap;
sqianf4ca7ed2019-01-15 18:32:07 -0800255import java.util.HashSet;
Jake Hambye994d462014-02-03 13:10:13 -0800256import java.util.List;
Narayan Kamath1c496c22015-04-16 14:40:19 +0100257import java.util.Locale;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800258import java.util.Map;
Nazanin Bakhshif71371d2019-04-29 17:29:44 -0700259import java.util.NoSuchElementException;
Hall Liu82694d52020-12-11 18:22:04 -0800260import java.util.Objects;
sqianf4ca7ed2019-01-15 18:32:07 -0800261import java.util.Set;
Sarah Chin2ec39f62022-08-31 17:03:26 -0700262import java.util.UUID;
Sarah Chineccfbd12023-01-20 19:00:35 -0800263import java.util.concurrent.ConcurrentHashMap;
Hall Liu82694d52020-12-11 18:22:04 -0800264import java.util.concurrent.Executors;
Peter Wangdafb9ac2020-01-15 14:13:38 -0800265import java.util.concurrent.atomic.AtomicBoolean;
Hall Liu73f5d362020-01-20 13:42:00 -0800266import java.util.function.Consumer;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700267
268/**
269 * Implementation of the ITelephony interface.
270 */
Santos Cordon117fee72014-05-16 17:56:12 -0700271public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700272 private static final String LOG_TAG = "PhoneInterfaceManager";
273 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
274 private static final boolean DBG_LOC = false;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800275 private static final boolean DBG_MERGE = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700276
277 // Message codes used with mMainThreadHandler
278 private static final int CMD_HANDLE_PIN_MMI = 1;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700279 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
280 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700281 private static final int CMD_OPEN_CHANNEL = 9;
282 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
283 private static final int CMD_CLOSE_CHANNEL = 11;
284 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800285 private static final int CMD_NV_READ_ITEM = 13;
286 private static final int EVENT_NV_READ_ITEM_DONE = 14;
287 private static final int CMD_NV_WRITE_ITEM = 15;
288 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
289 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
290 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
chen xu6dac5ab2018-10-26 17:39:23 -0700291 private static final int CMD_RESET_MODEM_CONFIG = 19;
292 private static final int EVENT_RESET_MODEM_CONFIG_DONE = 20;
SongFerngWang3ef3e072020-12-21 16:41:52 +0800293 private static final int CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK = 21;
294 private static final int EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE = 22;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800295 private static final int CMD_SEND_ENVELOPE = 25;
296 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Shuo Qian850e4d6a2018-04-25 21:02:08 +0000297 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
298 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
Derek Tan6b088ee2014-09-05 14:15:18 -0700299 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
300 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
301 private static final int CMD_EXCHANGE_SIM_IO = 31;
302 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800303 private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
304 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
Stuart Scott54788802015-03-30 13:18:01 -0700305 private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
306 private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700307 private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
308 private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700309 private static final int CMD_PERFORM_NETWORK_SCAN = 39;
310 private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
311 private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
312 private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
Meng Wang1a7c35a2016-05-05 20:56:15 -0700313 private static final int CMD_SET_ALLOWED_CARRIERS = 43;
314 private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
315 private static final int CMD_GET_ALLOWED_CARRIERS = 45;
316 private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
pkanwar32d516d2016-10-14 19:37:38 -0700317 private static final int CMD_HANDLE_USSD_REQUEST = 47;
Nathan Haroldb3014052017-01-25 15:57:32 -0800318 private static final int CMD_GET_FORBIDDEN_PLMNS = 48;
319 private static final int EVENT_GET_FORBIDDEN_PLMNS_DONE = 49;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000320 private static final int CMD_SWITCH_SLOTS = 50;
321 private static final int EVENT_SWITCH_SLOTS_DONE = 51;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700322 private static final int CMD_GET_NETWORK_SELECTION_MODE = 52;
323 private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 53;
324 private static final int CMD_GET_CDMA_ROAMING_MODE = 54;
325 private static final int EVENT_GET_CDMA_ROAMING_MODE_DONE = 55;
326 private static final int CMD_SET_CDMA_ROAMING_MODE = 56;
327 private static final int EVENT_SET_CDMA_ROAMING_MODE_DONE = 57;
328 private static final int CMD_SET_CDMA_SUBSCRIPTION_MODE = 58;
329 private static final int EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE = 59;
Nathan Harold3ff88932018-08-14 10:19:49 -0700330 private static final int CMD_GET_ALL_CELL_INFO = 60;
331 private static final int EVENT_GET_ALL_CELL_INFO_DONE = 61;
332 private static final int CMD_GET_CELL_LOCATION = 62;
333 private static final int EVENT_GET_CELL_LOCATION_DONE = 63;
chen xu6dac5ab2018-10-26 17:39:23 -0700334 private static final int CMD_MODEM_REBOOT = 64;
335 private static final int EVENT_CMD_MODEM_REBOOT_DONE = 65;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -0700336 private static final int CMD_REQUEST_CELL_INFO_UPDATE = 66;
337 private static final int EVENT_REQUEST_CELL_INFO_UPDATE_DONE = 67;
Malcolm Chen8e4ed912019-01-15 20:22:16 -0800338 private static final int CMD_REQUEST_ENABLE_MODEM = 68;
339 private static final int EVENT_ENABLE_MODEM_DONE = 69;
Nazanin Bakhshif71371d2019-04-29 17:29:44 -0700340 private static final int CMD_GET_MODEM_STATUS = 70;
341 private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
yincheng zhao2737e882019-09-06 17:06:54 -0700342 private static final int CMD_SET_FORBIDDEN_PLMNS = 72;
343 private static final int EVENT_SET_FORBIDDEN_PLMNS_DONE = 73;
Naina Nallurid63128d2019-09-17 14:10:30 -0700344 private static final int CMD_ERASE_MODEM_CONFIG = 74;
345 private static final int EVENT_ERASE_MODEM_CONFIG_DONE = 75;
zoey chene02881a2019-12-30 16:11:23 +0800346 private static final int CMD_CHANGE_ICC_LOCK_PASSWORD = 76;
347 private static final int EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE = 77;
348 private static final int CMD_SET_ICC_LOCK_ENABLED = 78;
349 private static final int EVENT_SET_ICC_LOCK_ENABLED_DONE = 79;
Hall Liu73f5d362020-01-20 13:42:00 -0800350 private static final int CMD_SET_SYSTEM_SELECTION_CHANNELS = 80;
351 private static final int EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE = 81;
Peter Wangdafb9ac2020-01-15 14:13:38 -0800352 private static final int MSG_NOTIFY_USER_ACTIVITY = 82;
Shuo Qian4a594052020-01-23 11:59:30 -0800353 private static final int CMD_GET_CALL_FORWARDING = 83;
354 private static final int EVENT_GET_CALL_FORWARDING_DONE = 84;
355 private static final int CMD_SET_CALL_FORWARDING = 85;
356 private static final int EVENT_SET_CALL_FORWARDING_DONE = 86;
357 private static final int CMD_GET_CALL_WAITING = 87;
358 private static final int EVENT_GET_CALL_WAITING_DONE = 88;
359 private static final int CMD_SET_CALL_WAITING = 89;
360 private static final int EVENT_SET_CALL_WAITING_DONE = 90;
Sooraj Sasindran37444802020-08-11 10:40:43 -0700361 private static final int CMD_ENABLE_NR_DUAL_CONNECTIVITY = 91;
362 private static final int EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE = 92;
363 private static final int CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED = 93;
364 private static final int EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE = 94;
Sarah Chinbaab1432020-10-28 13:46:24 -0700365 private static final int CMD_GET_CDMA_SUBSCRIPTION_MODE = 95;
366 private static final int EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE = 96;
Sarah Chin679c08a2020-11-18 13:39:35 -0800367 private static final int CMD_GET_SYSTEM_SELECTION_CHANNELS = 97;
368 private static final int EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE = 98;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800369 private static final int CMD_SET_DATA_THROTTLING = 99;
370 private static final int EVENT_SET_DATA_THROTTLING_DONE = 100;
Jordan Liu109698e2020-11-24 14:50:34 -0800371 private static final int CMD_SET_SIM_POWER = 101;
372 private static final int EVENT_SET_SIM_POWER_DONE = 102;
Rambo Wanga5cc9b72021-01-07 10:51:54 -0800373 private static final int CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST = 103;
374 private static final int EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE = 104;
375 private static final int CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST = 105;
376 private static final int EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE = 106;
SongFerngWang3ef3e072020-12-21 16:41:52 +0800377 private static final int CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON = 107;
378 private static final int EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE = 108;
Michele Berionne5e411512020-11-13 02:36:59 +0000379 private static final int CMD_PREPARE_UNATTENDED_REBOOT = 109;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +0800380 private static final int CMD_GET_SLICING_CONFIG = 110;
381 private static final int EVENT_GET_SLICING_CONFIG_DONE = 111;
Kai Shif70f46f2021-03-03 13:59:46 -0800382 private static final int CMD_ERASE_DATA_SHARED_PREFERENCES = 112;
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -0700383 private static final int CMD_ENABLE_VONR = 113;
384 private static final int EVENT_ENABLE_VONR_DONE = 114;
385 private static final int CMD_IS_VONR_ENABLED = 115;
386 private static final int EVENT_IS_VONR_ENABLED_DONE = 116;
Sarah Chin2ec39f62022-08-31 17:03:26 -0700387 private static final int CMD_PURCHASE_PREMIUM_CAPABILITY = 117;
388 private static final int EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE = 118;
Sarah Chineccfbd12023-01-20 19:00:35 -0800389 private static final int CMD_START_SATELLITE_POSITION_UPDATES = 119;
390 private static final int EVENT_START_SATELLITE_POSITION_UPDATES_DONE = 120;
391 private static final int CMD_STOP_SATELLITE_POSITION_UPDATES = 121;
392 private static final int EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE = 122;
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +0000393 private static final int CMD_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG = 123;
394 private static final int EVENT_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG_DONE = 124;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800395 private static final int CMD_PROVISION_SATELLITE_SERVICE = 125;
396 private static final int EVENT_PROVISION_SATELLITE_SERVICE_DONE = 126;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -0800397 private static final int CMD_DEPROVISION_SATELLITE_SERVICE = 127;
398 private static final int EVENT_DEPROVISION_SATELLITE_SERVICE_DONE = 128;
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800399 private static final int CMD_SET_SATELLITE_ENABLED = 129;
400 private static final int EVENT_SET_SATELLITE_ENABLED_DONE = 130;
401 private static final int CMD_IS_SATELLITE_ENABLED = 131;
402 private static final int EVENT_IS_SATELLITE_ENABLED_DONE = 132;
403 private static final int CMD_IS_SATELLITE_SUPPORTED = 133;
404 private static final int EVENT_IS_SATELLITE_SUPPORTED_DONE = 134;
405 private static final int CMD_GET_SATELLITE_CAPABILITIES = 135;
406 private static final int EVENT_GET_SATELLITE_CAPABILITIES_DONE = 136;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000407 private static final int CMD_POLL_PENDING_SATELLITE_DATAGRAMS = 137;
408 private static final int EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE = 138;
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +0000409 private static final int CMD_SEND_SATELLITE_DATAGRAM = 139;
410 private static final int EVENT_SEND_SATELLITE_DATAGRAM_DONE = 140;
Sarah Chindf715ec2023-02-13 13:46:24 -0800411 private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 141;
412 private static final int EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE = 142;
413 private static final int CMD_GET_TIME_SATELLITE_NEXT_VISIBLE = 143;
414 private static final int EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE = 144;
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -0800415 // Parameters of select command.
416 private static final int SELECT_COMMAND = 0xA4;
417 private static final int SELECT_P1 = 0x04;
418 private static final int SELECT_P2 = 0;
419 private static final int SELECT_P3 = 0x10;
420
Gil Cukierman1c0eb932022-12-06 22:28:24 +0000421 // Toggling null cipher and integrity support was added in IRadioNetwork 2.1
422 private static final int MIN_NULL_CIPHER_AND_INTEGRITY_VERSION = 201;
423
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700424 /** The singleton instance. */
425 private static PhoneInterfaceManager sInstance;
Jack Nudelman644b91a2021-03-12 14:09:48 -0800426 private static List<String> sThermalMitigationAllowlistedPackages = new ArrayList<>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700427
Wink Saville3ab207e2014-11-20 13:07:20 -0800428 private PhoneGlobals mApp;
Wink Saville3ab207e2014-11-20 13:07:20 -0800429 private CallManager mCM;
Brad Ebinger24c29992019-12-05 13:03:21 -0800430 private ImsResolver mImsResolver;
Stuart Scott981d8582015-04-21 14:09:50 -0700431 private UserManager mUserManager;
Wink Saville3ab207e2014-11-20 13:07:20 -0800432 private AppOpsManager mAppOps;
Grace Jia0ddb3612021-04-22 13:35:26 -0700433 private PackageManager mPm;
Wink Saville3ab207e2014-11-20 13:07:20 -0800434 private MainThreadHandler mMainThreadHandler;
Jack Yue37dd262022-12-16 11:53:37 -0800435 private final SubscriptionController mSubscriptionController;
Wink Saville3ab207e2014-11-20 13:07:20 -0800436 private SharedPreferences mTelephonySharedPreferences;
Malcolm Chen2c63d402018-08-14 16:00:53 -0700437 private PhoneConfigurationManager mPhoneConfigurationManager;
Daniel Bright94f43662021-03-01 14:43:40 -0800438 private final RadioInterfaceCapabilityController mRadioInterfaceCapabilities;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700439
Peter Wangdafb9ac2020-01-15 14:13:38 -0800440 /** User Activity */
441 private AtomicBoolean mNotifyUserActivity;
Peter Wangdafb9ac2020-01-15 14:13:38 -0800442 private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
443
Jeff Davidson8ab02b22020-03-28 12:24:40 -0700444 private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800445
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800446 /**
447 * Map key: subId, value: callback to get error code of the provision request.
448 */
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800449 private final ConcurrentHashMap<Integer, Consumer<Integer>> mSatelliteProvisionCallbacks =
Sarah Chineccfbd12023-01-20 19:00:35 -0800450 new ConcurrentHashMap<>();
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800451 /**
452 * Map key: subId, value: SatellitePositionUpdateHandler to notify registrants.
453 */
454 private final ConcurrentHashMap<IBinder, SatellitePositionUpdateHandler>
455 mSatellitePositionUpdateHandlers = new ConcurrentHashMap<>();
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800456 /**
457 * Map key: subId, value: SatelliteProvisionStateChangedHandler to notify registrants.
458 */
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800459 private final ConcurrentHashMap<Integer, SatelliteProvisionStateChangedHandler>
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800460 mSatelliteProvisionStateChangedHandlers = new ConcurrentHashMap<>();
461
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800462 private Boolean mIsSatelliteSupported = null;
463 private final Object mIsSatelliteSupportedLock = new Object();
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800464 private final ResultReceiver mSatelliteSupportedReceiver;
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800465
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000466 /**
467 * Map key: subId, value: SatelliteStateChangeHandler to notify registrants.
468 */
469 private ConcurrentHashMap<Integer, SatelliteStateListenerHandler>
470 mSatelliteStateListenerHandlers = new ConcurrentHashMap<>();
471
472 /**
473 * Map key: subId, value: SatelliteDatagramListenerHandler to notify registrants.
474 */
475 private ConcurrentHashMap<Integer, SatelliteDatagramListenerHandler>
476 mSatelliteDatagramListenerHandlers = new ConcurrentHashMap<>();
477
Derek Tan97ebb422014-09-05 16:55:38 -0700478 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
479 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
Jeff Sharkey85190e62014-12-05 09:40:12 -0800480 private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
Brad Ebinger1c8542e2019-01-14 13:43:14 -0800481 private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
Derek Tan89e89d42014-07-08 17:00:10 -0700482
Michelecea4cf22018-12-21 15:00:11 -0800483 // String to store multi SIM allowed
484 private static final String PREF_MULTI_SIM_RESTRICTED = "multisim_restricted";
485
Derek Tan740e1672017-06-27 14:56:27 -0700486 // The AID of ISD-R.
487 private static final String ISDR_AID = "A0000005591010FFFFFFFF8900000100";
488
yinxub1bed742017-04-17 11:45:04 -0700489 private NetworkScanRequestTracker mNetworkScanRequestTracker;
490
David Kelly5e06a7f2018-03-12 14:10:59 +0000491 private static final int TYPE_ALLOCATION_CODE_LENGTH = 8;
492 private static final int MANUFACTURER_CODE_LENGTH = 8;
493
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800494 private static final int SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS = -1;
Jack Nudelman5d6a98b2021-03-04 14:26:25 -0800495 private static final int MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE = -2;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800496
Sarah Chin2ec39f62022-08-31 17:03:26 -0700497 private static final String PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID =
498 "24bf97a6-e8a6-44d8-a6a4-255d7548733c";
499
Derek Tan89e89d42014-07-08 17:00:10 -0700500 /**
Naina Nallurid63128d2019-09-17 14:10:30 -0700501 * Experiment flag to enable erase modem config on reset network, default value is false
502 */
503 public static final String RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED =
504 "reset_network_erase_modem_config_enabled";
505
Rambo Wang0f050d82021-02-12 11:43:36 -0800506 private static final int SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS = 2000; // 2 seconds
Chen Xu540470b2021-12-14 17:15:47 -0800507
Gary Jian76280a42022-12-07 16:18:33 +0800508 private static final int MODEM_ACTIVITY_TIME_OFFSET_CORRECTION_MS = 50;
509
sandeepjsb6c87872021-09-27 15:34:44 +0000510 /**
511 * With support for MEP(multiple enabled profile) in Android T, a SIM card can have more than
512 * one ICCID active at the same time.
513 * Apps should use below API signatures if targeting SDK is T and beyond.
514 *
515 * @hide
516 */
517 @ChangeId
518 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
519 public static final long GET_API_SIGNATURES_FROM_UICC_PORT_INFO = 202110963L;
Rambo Wang0f050d82021-02-12 11:43:36 -0800520
Naina Nallurid63128d2019-09-17 14:10:30 -0700521 /**
Chen Xu540470b2021-12-14 17:15:47 -0800522 * Apps targeting on Android T and beyond will get exception whenever icc close channel
523 * operation fails.
524 */
525 @ChangeId
526 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
527 public static final long ICC_CLOSE_CHANNEL_EXCEPTION_ON_FAILURE = 208739934L;
528
529 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700530 * A request object to use for transmitting data to an ICC.
531 */
532 private static final class IccAPDUArgument {
533 public int channel, cla, command, p1, p2, p3;
534 public String data;
535
536 public IccAPDUArgument(int channel, int cla, int command,
537 int p1, int p2, int p3, String data) {
538 this.channel = channel;
539 this.cla = cla;
540 this.command = command;
541 this.p1 = p1;
542 this.p2 = p2;
543 this.p3 = p3;
544 this.data = data;
545 }
546 }
547
548 /**
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700549 * A request object to use for transmitting data to an ICC.
550 */
551 private static final class ManualNetworkSelectionArgument {
552 public OperatorInfo operatorInfo;
553 public boolean persistSelection;
554
555 public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
556 this.operatorInfo = operatorInfo;
557 this.persistSelection = persistSelection;
558 }
559 }
560
Sarah Chin71b3a852022-09-28 15:54:19 -0700561 private static final class PurchasePremiumCapabilityArgument {
562 public @TelephonyManager.PremiumCapability int capability;
Sarah Chin71b3a852022-09-28 15:54:19 -0700563 public @NonNull IIntegerConsumer callback;
564
565 PurchasePremiumCapabilityArgument(@TelephonyManager.PremiumCapability int capability,
Sarah Chinb8218c22023-01-04 13:35:29 -0800566 @NonNull IIntegerConsumer callback) {
Sarah Chin71b3a852022-09-28 15:54:19 -0700567 this.capability = capability;
Sarah Chin71b3a852022-09-28 15:54:19 -0700568 this.callback = callback;
569 }
570 }
571
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800572 private static final class ProvisionSatelliteServiceArgument {
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800573 public @NonNull String token;
574 public @NonNull Consumer<Integer> callback;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800575 public int subId;
576
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800577 ProvisionSatelliteServiceArgument(String token, Consumer<Integer> callback, int subId) {
578 this.token = token;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800579 this.callback = callback;
580 this.subId = subId;
581 }
582 }
583
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +0000584 private static final class SendSatelliteDatagramArgument {
585 public @SatelliteManager.DatagramType int datagramType;
586 public @NonNull SatelliteDatagram datagram;
587 public @NonNull Consumer<Integer> callback;
588
589 SendSatelliteDatagramArgument(@SatelliteManager.DatagramType int datagramType,
590 SatelliteDatagram datagram, Consumer<Integer> callback) {
591 this.datagramType = datagramType;
592 this.datagram = datagram;
593 this.callback = callback;
594 }
595 }
596
Sarah Chineccfbd12023-01-20 19:00:35 -0800597 private static final class SatellitePositionUpdateHandler extends Handler {
598 public static final int EVENT_POSITION_UPDATE = 1;
599 public static final int EVENT_MESSAGE_TRANSFER_STATE_UPDATE = 2;
600
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800601 private final ISatelliteStateListener mCallback;
Sarah Chineccfbd12023-01-20 19:00:35 -0800602
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800603 SatellitePositionUpdateHandler(ISatelliteStateListener callback, Looper looper) {
Sarah Chineccfbd12023-01-20 19:00:35 -0800604 super(looper);
605 mCallback = callback;
606 }
607
608 @Override
609 public void handleMessage(@NonNull Message msg) {
610 switch (msg.what) {
611 case EVENT_POSITION_UPDATE: {
612 AsyncResult ar = (AsyncResult) msg.obj;
613 PointingInfo pointingInfo = (PointingInfo) ar.result;
614 try {
615 mCallback.onSatellitePositionUpdate(pointingInfo);
616 } catch (RemoteException e) {
617 loge("EVENT_POSITION_UPDATE RemoteException: " + e);
618 }
619 break;
620 }
621 case EVENT_MESSAGE_TRANSFER_STATE_UPDATE: {
622 AsyncResult ar = (AsyncResult) msg.obj;
623 int state = (int) ar.result;
624 try {
Sarah Chindf715ec2023-02-13 13:46:24 -0800625 // TODO: get correct responses back from indication
626 mCallback.onMessageTransferStateUpdate(state, 0, 0, 0);
Sarah Chineccfbd12023-01-20 19:00:35 -0800627 } catch (RemoteException e) {
628 loge("EVENT_MESSAGE_TRANSFER_STATE_UPDATE RemoteException: " + e);
629 }
630 break;
631 }
632 default:
633 loge("SatellitePositionUpdateHandler unknown event: " + msg.what);
634 }
635 }
636 }
637
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800638 private static final class SatelliteProvisionStateChangedHandler extends Handler {
639 public static final int EVENT_PROVISION_STATE_CHANGED = 1;
640
641 private ConcurrentHashMap<IBinder, ISatelliteStateListener> mListeners;
642 private final int mSubId;
643
644 SatelliteProvisionStateChangedHandler(Looper looper, int subId) {
645 super(looper);
646 mListeners = new ConcurrentHashMap<>();
647 mSubId = subId;
648 }
649
650 public void addListener(ISatelliteStateListener listener) {
651 mListeners.put(listener.asBinder(), listener);
652 }
653
654 public boolean removeListener(ISatelliteStateListener listener) {
655 return (mListeners.remove(listener.asBinder()) != null);
656 }
657
658 @Override
659 public void handleMessage(@NonNull Message msg) {
660 switch (msg.what) {
661 case EVENT_PROVISION_STATE_CHANGED: {
662 AsyncResult ar = (AsyncResult) msg.obj;
663 boolean provisioned = (boolean) ar.userObj;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800664 log("Received EVENT_PROVISION_STATE_CHANGED for subId=" + mSubId
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800665 + ", provisioned=" + provisioned);
666 mListeners.values().forEach(listener -> {
667 try {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -0800668 listener.onSatelliteProvisionStateChanged(provisioned);
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800669 } catch (RemoteException e) {
670 log("EVENT_PROVISION_STATE_CHANGED RemoteException: " + e);
671 }
672 });
673
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800674 setSatelliteProvisioned(provisioned);
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800675 /**
676 * TODO: Take bugreport if provisioned is true and user did not initiate the
677 * provision procedure for the corresponding subscription.
678 */
679 break;
680 }
681 default:
682 loge("SatelliteProvisionStateChangedHandler unknown event: " + msg.what);
683 }
684 }
685
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800686 private void setSatelliteProvisioned(boolean isProvisioned) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800687 if (mSubId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
688 SubscriptionManager.setSubscriptionProperty(
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800689 mSubId, SubscriptionManager.SATELLITE_ENABLED, isProvisioned ? "1" : "0");
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800690 } else {
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800691 //TODO (b/267826133): set via SatelliteController.
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800692 }
693 }
694 }
695
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000696 private static final class SatelliteStateListenerHandler extends Handler {
697 public static final int EVENT_SATELLITE_MODEM_STATE_CHANGE = 1;
Aishwarya Mallampati224317a2023-02-13 22:09:30 +0000698 public static final int EVENT_PENDING_DATAGRAM_COUNT = 2;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000699
700 private ConcurrentHashMap<IBinder, ISatelliteStateListener> mListeners;
701 private final int mSubId;
702
703 SatelliteStateListenerHandler(Looper looper, int subId) {
704 super(looper);
705 mSubId = subId;
706 mListeners = new ConcurrentHashMap<>();
707 }
708
709 public void addListener(ISatelliteStateListener listener) {
710 mListeners.put(listener.asBinder(), listener);
711 }
712
713 public boolean removeListener(ISatelliteStateListener listener) {
714 return (mListeners.remove(listener.asBinder()) != null);
715 }
716
717 @Override
718 public void handleMessage(@NonNull Message msg) {
719 switch (msg.what) {
720 case EVENT_SATELLITE_MODEM_STATE_CHANGE : {
721 AsyncResult ar = (AsyncResult) msg.obj;
722 int state = (int) ar.result;
723 log("Received EVENT_SATELLITE_MODEM_STATE_CHANGE for subId=" + mSubId
724 + ", state=" + state);
725 mListeners.values().forEach(listener -> {
726 try {
727 listener.onSatelliteModemStateChange(state);
728 } catch (RemoteException e) {
729 log("EVENT_SATELLITE_MODEM_STATE_CHANGE RemoteException: " + e);
730 }
731 });
732 break;
733 }
Aishwarya Mallampati224317a2023-02-13 22:09:30 +0000734 case EVENT_PENDING_DATAGRAM_COUNT: {
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000735 AsyncResult ar = (AsyncResult) msg.obj;
736 int count = (int) ar.result;
Aishwarya Mallampati224317a2023-02-13 22:09:30 +0000737 log("Received EVENT_PENDING_DATAGRAM_COUNT for subId=" + mSubId
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000738 + ", count=" + count);
739 mListeners.values().forEach(listener -> {
740 try {
Aishwarya Mallampati224317a2023-02-13 22:09:30 +0000741 listener.onPendingDatagramCount(count);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000742 } catch (RemoteException e) {
Aishwarya Mallampati224317a2023-02-13 22:09:30 +0000743 log("EVENT_PENDING_DATAGRAM_COUNT RemoteException: " + e);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000744 }
745 });
746 break;
747 }
748 default:
749 loge("SatelliteStateListenerHandler unknown event: " + msg.what);
750 }
751 }
752 }
753
754 private static final class SatelliteDatagramListenerHandler extends Handler {
755 public static final int EVENT_SATELLITE_DATAGRAMS_RECEIVED = 1;
756
757 private ConcurrentHashMap<IBinder, ISatelliteStateListener> mListeners;
758 private final int mSubId;
759
760 SatelliteDatagramListenerHandler(Looper looper, int subId) {
761 super(looper);
762 mSubId = subId;
763 mListeners = new ConcurrentHashMap<>();
764 }
765
766 public void addListener(ISatelliteStateListener listener) {
767 mListeners.put(listener.asBinder(), listener);
768 }
769
770 public boolean removeListener(ISatelliteStateListener listener) {
771 return (mListeners.remove(listener.asBinder()) != null);
772 }
773
774 @Override
775 public void handleMessage(@NonNull Message msg) {
776 switch (msg.what) {
777 case EVENT_SATELLITE_DATAGRAMS_RECEIVED : {
778 AsyncResult ar = (AsyncResult) msg.obj;
779 byte[][] datagrams = (byte[][]) ar.result;
780 SatelliteDatagram[] satelliteDatagramArray =
781 convertToSatelliteDatagramArray(datagrams);
782
783 log("Received EVENT_SATELLITE_DATAGRAMS_RECEIVED for subId=" + mSubId);
784 mListeners.values().forEach(listener -> {
785 try {
786 listener.onSatelliteDatagrams(satelliteDatagramArray);
787 } catch (RemoteException e) {
788 log("EVENT_SATELLITE_DATAGRAMS_RECEIVED RemoteException: " + e);
789 }
790 });
791 break;
792 }
793 default:
794 loge("SatelliteDatagramListenerHandler unknown event: " + msg.what);
795 }
796 }
797 }
798
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700799 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700800 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
801 * request after sending. The main thread will notify the request when it is complete.
802 */
803 private static final class MainThreadRequest {
804 /** The argument to use for the request */
805 public Object argument;
806 /** The result of the request that is run on the main thread */
807 public Object result;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800808 // The subscriber id that this request applies to. Defaults to
809 // SubscriptionManager.INVALID_SUBSCRIPTION_ID
810 public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700811
Nathan Harold92bed182018-10-12 18:16:49 -0700812 // In cases where subId is unavailable, the caller needs to specify the phone.
813 public Phone phone;
814
vagdeviaf9a5b92018-08-15 16:01:53 -0700815 public WorkSource workSource;
816
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700817 public MainThreadRequest(Object argument) {
818 this.argument = argument;
819 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800820
Nathan Harold92bed182018-10-12 18:16:49 -0700821 MainThreadRequest(Object argument, Phone phone, WorkSource workSource) {
822 this.argument = argument;
823 if (phone != null) {
824 this.phone = phone;
825 }
826 this.workSource = workSource;
827 }
828
vagdeviaf9a5b92018-08-15 16:01:53 -0700829 MainThreadRequest(Object argument, Integer subId, WorkSource workSource) {
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800830 this.argument = argument;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800831 if (subId != null) {
832 this.subId = subId;
833 }
vagdeviaf9a5b92018-08-15 16:01:53 -0700834 this.workSource = workSource;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800835 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700836 }
837
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800838 private static final class IncomingThirdPartyCallArgs {
839 public final ComponentName component;
840 public final String callId;
841 public final String callerDisplayName;
842
843 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
844 String callerDisplayName) {
845 this.component = component;
846 this.callId = callId;
847 this.callerDisplayName = callerDisplayName;
848 }
849 }
850
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700851 /**
852 * A handler that processes messages on the main thread in the phone process. Since many
853 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
854 * inbound binder threads to the main thread in the phone process. The Binder thread
855 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
856 * on, which will be notified when the operation completes and will contain the result of the
857 * request.
858 *
859 * <p>If a MainThreadRequest object is provided in the msg.obj field,
860 * note that request.result must be set to something non-null for the calling thread to
861 * unblock.
862 */
863 private final class MainThreadHandler extends Handler {
864 @Override
865 public void handleMessage(Message msg) {
866 MainThreadRequest request;
867 Message onCompleted;
868 AsyncResult ar;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000869 UiccPort uiccPort;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700870 IccAPDUArgument iccArgument;
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800871 final Phone defaultPhone = getDefaultPhone();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700872
873 switch (msg.what) {
Pengquan Menga1bb6272018-09-06 09:59:22 -0700874 case CMD_HANDLE_USSD_REQUEST: {
875 request = (MainThreadRequest) msg.obj;
876 final Phone phone = getPhoneFromRequest(request);
877 Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
Chen Xue9d737e2022-01-01 23:41:31 -0800878 String ussdRequest = ussdObject.first;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700879 ResultReceiver wrappedCallback = ussdObject.second;
Tyler Gunn65d45c22017-06-05 11:22:26 -0700880
Pengquan Menga1bb6272018-09-06 09:59:22 -0700881 if (!isUssdApiAllowed(request.subId)) {
882 // Carrier does not support use of this API, return failure.
883 Rlog.w(LOG_TAG, "handleUssdRequest: carrier does not support USSD apis.");
884 UssdResponse response = new UssdResponse(ussdRequest, null);
885 Bundle returnData = new Bundle();
886 returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
887 wrappedCallback.send(TelephonyManager.USSD_RETURN_FAILURE, returnData);
Tyler Gunn65d45c22017-06-05 11:22:26 -0700888
Pengquan Menga1bb6272018-09-06 09:59:22 -0700889 request.result = true;
890 notifyRequester(request);
891 return;
892 }
Tyler Gunn65d45c22017-06-05 11:22:26 -0700893
Pengquan Menga1bb6272018-09-06 09:59:22 -0700894 try {
895 request.result = phone != null
896 ? phone.handleUssdRequest(ussdRequest, wrappedCallback) : false;
897 } catch (CallStateException cse) {
898 request.result = false;
899 }
900 // Wake up the requesting thread
901 notifyRequester(request);
902 break;
pkanwar32d516d2016-10-14 19:37:38 -0700903 }
904
Yorke Lee716f67e2015-06-17 15:39:16 -0700905 case CMD_HANDLE_PIN_MMI: {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700906 request = (MainThreadRequest) msg.obj;
Yorke Lee716f67e2015-06-17 15:39:16 -0700907 final Phone phone = getPhoneFromRequest(request);
908 request.result = phone != null ?
909 getPhoneFromRequest(request).handlePinMmi((String) request.argument)
910 : false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700911 // Wake up the requesting thread
Pengquan Menga1bb6272018-09-06 09:59:22 -0700912 notifyRequester(request);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700913 break;
Yorke Lee716f67e2015-06-17 15:39:16 -0700914 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700915
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700916 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700917 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700918 iccArgument = (IccAPDUArgument) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000919 uiccPort = getUiccPortFromRequest(request);
920 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700921 loge("iccTransmitApduLogicalChannel: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -0800922 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700923 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700924 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700925 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
Chen Xue9d737e2022-01-01 23:41:31 -0800926 request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000927 uiccPort.iccTransmitApduLogicalChannel(
Chen Xue9d737e2022-01-01 23:41:31 -0800928 iccArgument.channel, iccArgument.cla, iccArgument.command,
929 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
930 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700931 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700932 break;
933
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700934 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700935 ar = (AsyncResult) msg.obj;
936 request = (MainThreadRequest) ar.userObj;
937 if (ar.exception == null && ar.result != null) {
938 request.result = ar.result;
939 } else {
Chen Xue9d737e2022-01-01 23:41:31 -0800940 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700941 if (ar.result == null) {
942 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800943 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700944 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800945 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700946 } else {
947 loge("iccTransmitApduLogicalChannel: Unknown exception");
948 }
949 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700950 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700951 break;
952
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700953 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
954 request = (MainThreadRequest) msg.obj;
955 iccArgument = (IccAPDUArgument) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000956 uiccPort = getUiccPortFromRequest(request);
957 if (uiccPort == null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700958 loge("iccTransmitApduBasicChannel: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -0800959 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700960 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700961 } else {
962 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
Chen Xue9d737e2022-01-01 23:41:31 -0800963 request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000964 uiccPort.iccTransmitApduBasicChannel(
Chen Xue9d737e2022-01-01 23:41:31 -0800965 iccArgument.cla, iccArgument.command, iccArgument.p1,
966 iccArgument.p2,
967 iccArgument.p3, iccArgument.data, onCompleted);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700968 }
969 break;
970
971 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
972 ar = (AsyncResult) msg.obj;
973 request = (MainThreadRequest) ar.userObj;
974 if (ar.exception == null && ar.result != null) {
975 request.result = ar.result;
976 } else {
Chen Xue9d737e2022-01-01 23:41:31 -0800977 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700978 if (ar.result == null) {
979 loge("iccTransmitApduBasicChannel: Empty response");
980 } else if (ar.exception instanceof CommandException) {
981 loge("iccTransmitApduBasicChannel: CommandException: " +
982 ar.exception);
983 } else {
984 loge("iccTransmitApduBasicChannel: Unknown exception");
985 }
986 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700987 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700988 break;
989
990 case CMD_EXCHANGE_SIM_IO:
991 request = (MainThreadRequest) msg.obj;
992 iccArgument = (IccAPDUArgument) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000993 uiccPort = getUiccPortFromRequest(request);
994 if (uiccPort == null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700995 loge("iccExchangeSimIO: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -0800996 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700997 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700998 } else {
999 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
1000 request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001001 uiccPort.iccExchangeSimIO(iccArgument.cla, /* fileID */
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001002 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
1003 iccArgument.data, onCompleted);
1004 }
1005 break;
1006
1007 case EVENT_EXCHANGE_SIM_IO_DONE:
1008 ar = (AsyncResult) msg.obj;
1009 request = (MainThreadRequest) ar.userObj;
1010 if (ar.exception == null && ar.result != null) {
1011 request.result = ar.result;
1012 } else {
Chen Xue9d737e2022-01-01 23:41:31 -08001013 request.result = new IccIoResult(0x6f, 0, (byte[]) null);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001014 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001015 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001016 break;
1017
Derek Tan4d5e5c12014-02-04 11:54:58 -08001018 case CMD_SEND_ENVELOPE:
1019 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001020 uiccPort = getUiccPortFromRequest(request);
1021 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001022 loge("sendEnvelopeWithStatus: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -08001023 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001024 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001025 } else {
1026 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
Chen Xue9d737e2022-01-01 23:41:31 -08001027 uiccPort.sendEnvelopeWithStatus((String) request.argument, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001028 }
Derek Tan4d5e5c12014-02-04 11:54:58 -08001029 break;
1030
1031 case EVENT_SEND_ENVELOPE_DONE:
1032 ar = (AsyncResult) msg.obj;
1033 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -07001034 if (ar.exception == null && ar.result != null) {
1035 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -08001036 } else {
Chen Xue9d737e2022-01-01 23:41:31 -08001037 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Shishir Agrawal9f9877d2014-03-14 09:36:27 -07001038 if (ar.result == null) {
1039 loge("sendEnvelopeWithStatus: Empty response");
1040 } else if (ar.exception instanceof CommandException) {
1041 loge("sendEnvelopeWithStatus: CommandException: " +
1042 ar.exception);
1043 } else {
1044 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
1045 }
Derek Tan4d5e5c12014-02-04 11:54:58 -08001046 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001047 notifyRequester(request);
Derek Tan4d5e5c12014-02-04 11:54:58 -08001048 break;
1049
Shishir Agrawal566b7612013-10-28 14:41:00 -07001050 case CMD_OPEN_CHANNEL:
1051 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001052 uiccPort = getUiccPortFromRequest(request);
Rambo Wanga1782702021-11-10 20:15:19 -08001053 IccLogicalChannelRequest openChannelRequest =
1054 (IccLogicalChannelRequest) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001055 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001056 loge("iccOpenLogicalChannel: No UICC");
Shishir Agrawalfc0492a2016-02-17 11:15:33 -08001057 request.result = new IccOpenLogicalChannelResponse(-1,
Chen Xue9d737e2022-01-01 23:41:31 -08001058 IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001059 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001060 } else {
1061 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
Rambo Wanga1782702021-11-10 20:15:19 -08001062 uiccPort.iccOpenLogicalChannel(openChannelRequest.aid,
1063 openChannelRequest.p2, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001064 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001065 break;
1066
1067 case EVENT_OPEN_CHANNEL_DONE:
1068 ar = (AsyncResult) msg.obj;
1069 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001070 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -07001071 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001072 int[] result = (int[]) ar.result;
1073 int channelId = result[0];
1074 byte[] selectResponse = null;
1075 if (result.length > 1) {
1076 selectResponse = new byte[result.length - 1];
1077 for (int i = 1; i < result.length; ++i) {
1078 selectResponse[i - 1] = (byte) result[i];
1079 }
1080 }
1081 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Chen Xue9d737e2022-01-01 23:41:31 -08001082 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Rambo Wang3b77c4c2021-11-10 20:15:19 -08001083
1084 uiccPort = getUiccPortFromRequest(request);
Rambo Wange53e07d2022-05-10 13:01:13 -07001085 if (uiccPort == null) {
1086 loge("EVENT_OPEN_CHANNEL_DONE: UiccPort is null");
1087 } else {
1088 IccLogicalChannelRequest channelRequest =
1089 (IccLogicalChannelRequest) request.argument;
1090 channelRequest.channel = channelId;
1091 uiccPort.onLogicalChannelOpened(channelRequest);
1092 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001093 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -07001094 if (ar.result == null) {
1095 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -07001096 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001097 if (ar.exception != null) {
1098 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
1099 }
1100
Shishir Agrawal527e8bf2014-08-25 08:54:56 -07001101 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Junda Liua754ba12015-05-20 01:17:52 -07001102 if (ar.exception instanceof CommandException) {
1103 CommandException.Error error =
Chen Xue9d737e2022-01-01 23:41:31 -08001104 ((CommandException) (ar.exception)).getCommandError();
Junda Liua754ba12015-05-20 01:17:52 -07001105 if (error == CommandException.Error.MISSING_RESOURCE) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -07001106 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Junda Liua754ba12015-05-20 01:17:52 -07001107 } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -07001108 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001109 }
1110 }
1111 openChannelResp = new IccOpenLogicalChannelResponse(
Chen Xue9d737e2022-01-01 23:41:31 -08001112 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001113 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -07001114 request.result = openChannelResp;
Pengquan Menga1bb6272018-09-06 09:59:22 -07001115 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001116 break;
1117
1118 case CMD_CLOSE_CHANNEL:
1119 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001120 uiccPort = getUiccPortFromRequest(request);
1121 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001122 loge("iccCloseLogicalChannel: No UICC");
Chen Xua8f0dff2022-02-12 00:34:15 -08001123 request.result = new IllegalArgumentException(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001124 "iccCloseLogicalChannel: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -08001125 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001126 } else {
1127 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001128 uiccPort.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001129 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001130 break;
1131
1132 case EVENT_CLOSE_CHANNEL_DONE:
Chen Xu540470b2021-12-14 17:15:47 -08001133 ar = (AsyncResult) msg.obj;
1134 request = (MainThreadRequest) ar.userObj;
1135 if (ar.exception == null) {
1136 request.result = true;
Rambo Wang3b77c4c2021-11-10 20:15:19 -08001137 uiccPort = getUiccPortFromRequest(request);
Rambo Wange53e07d2022-05-10 13:01:13 -07001138 if (uiccPort == null) {
1139 loge("EVENT_CLOSE_CHANNEL_DONE: UiccPort is null");
1140 } else {
1141 final int channelId = (Integer) request.argument;
1142 uiccPort.onLogicalChannelClosed(channelId);
1143 }
Chen Xu540470b2021-12-14 17:15:47 -08001144 } else {
1145 request.result = false;
Chen Xue9d737e2022-01-01 23:41:31 -08001146 Exception exception = null;
Chen Xu540470b2021-12-14 17:15:47 -08001147 if (ar.exception instanceof CommandException) {
1148 loge("iccCloseLogicalChannel: CommandException: " + ar.exception);
1149 CommandException.Error error =
1150 ((CommandException) (ar.exception)).getCommandError();
Chen Xue9d737e2022-01-01 23:41:31 -08001151 if (error == CommandException.Error.INVALID_ARGUMENTS) {
1152 // should only throw exceptions from the binder threads.
1153 exception = new IllegalArgumentException(
Chen Xu540470b2021-12-14 17:15:47 -08001154 "iccCloseLogicalChannel: invalid argument ");
1155 }
1156 } else {
1157 loge("iccCloseLogicalChannel: Unknown exception");
1158 }
Chen Xua8f0dff2022-02-12 00:34:15 -08001159 request.result = (exception != null) ? exception :
1160 new IllegalStateException(
1161 "exception from modem to close iccLogical Channel");
Chen Xu540470b2021-12-14 17:15:47 -08001162 }
1163 notifyRequester(request);
Jake Hambye994d462014-02-03 13:10:13 -08001164 break;
1165
1166 case CMD_NV_READ_ITEM:
1167 request = (MainThreadRequest) msg.obj;
1168 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001169 defaultPhone.nvReadItem((Integer) request.argument, onCompleted,
1170 request.workSource);
Jake Hambye994d462014-02-03 13:10:13 -08001171 break;
1172
1173 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -07001174 ar = (AsyncResult) msg.obj;
1175 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -08001176 if (ar.exception == null && ar.result != null) {
1177 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -07001178 } else {
Jake Hambye994d462014-02-03 13:10:13 -08001179 request.result = "";
1180 if (ar.result == null) {
1181 loge("nvReadItem: Empty response");
1182 } else if (ar.exception instanceof CommandException) {
1183 loge("nvReadItem: CommandException: " +
1184 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001185 } else {
Jake Hambye994d462014-02-03 13:10:13 -08001186 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -07001187 }
1188 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001189 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001190 break;
1191
Jake Hambye994d462014-02-03 13:10:13 -08001192 case CMD_NV_WRITE_ITEM:
1193 request = (MainThreadRequest) msg.obj;
1194 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
1195 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001196 defaultPhone.nvWriteItem(idValue.first, idValue.second, onCompleted,
vagdeviaf9a5b92018-08-15 16:01:53 -07001197 request.workSource);
Jake Hambye994d462014-02-03 13:10:13 -08001198 break;
1199
1200 case EVENT_NV_WRITE_ITEM_DONE:
1201 handleNullReturnEvent(msg, "nvWriteItem");
1202 break;
1203
1204 case CMD_NV_WRITE_CDMA_PRL:
1205 request = (MainThreadRequest) msg.obj;
1206 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001207 defaultPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
Jake Hambye994d462014-02-03 13:10:13 -08001208 break;
1209
1210 case EVENT_NV_WRITE_CDMA_PRL_DONE:
1211 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
1212 break;
1213
chen xu6dac5ab2018-10-26 17:39:23 -07001214 case CMD_RESET_MODEM_CONFIG:
Jake Hambye994d462014-02-03 13:10:13 -08001215 request = (MainThreadRequest) msg.obj;
chen xu6dac5ab2018-10-26 17:39:23 -07001216 onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001217 defaultPhone.resetModemConfig(onCompleted);
Jake Hambye994d462014-02-03 13:10:13 -08001218 break;
1219
chen xu6dac5ab2018-10-26 17:39:23 -07001220 case EVENT_RESET_MODEM_CONFIG_DONE:
1221 handleNullReturnEvent(msg, "resetModemConfig");
Jake Hambye994d462014-02-03 13:10:13 -08001222 break;
1223
Sooraj Sasindran37444802020-08-11 10:40:43 -07001224 case CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED: {
1225 request = (MainThreadRequest) msg.obj;
1226 onCompleted = obtainMessage(EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE,
1227 request);
1228 Phone phone = getPhoneFromRequest(request);
1229 if (phone != null) {
1230 phone.isNrDualConnectivityEnabled(onCompleted, request.workSource);
1231 } else {
1232 loge("isNRDualConnectivityEnabled: No phone object");
1233 request.result = false;
1234 notifyRequester(request);
1235 }
1236 break;
1237 }
1238
1239 case EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE:
1240 ar = (AsyncResult) msg.obj;
1241 request = (MainThreadRequest) ar.userObj;
1242 if (ar.exception == null && ar.result != null) {
1243 request.result = ar.result;
1244 } else {
1245 // request.result must be set to something non-null
1246 // for the calling thread to unblock
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07001247 if (ar.result != null) {
Sooraj Sasindran37444802020-08-11 10:40:43 -07001248 request.result = ar.result;
1249 } else {
1250 request.result = false;
1251 }
1252 if (ar.result == null) {
1253 loge("isNRDualConnectivityEnabled: Empty response");
1254 } else if (ar.exception instanceof CommandException) {
1255 loge("isNRDualConnectivityEnabled: CommandException: "
1256 + ar.exception);
1257 } else {
1258 loge("isNRDualConnectivityEnabled: Unknown exception");
1259 }
1260 }
1261 notifyRequester(request);
1262 break;
1263
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07001264 case CMD_IS_VONR_ENABLED: {
1265 request = (MainThreadRequest) msg.obj;
1266 onCompleted = obtainMessage(EVENT_IS_VONR_ENABLED_DONE,
1267 request);
1268 Phone phone = getPhoneFromRequest(request);
1269 if (phone != null) {
1270 phone.isVoNrEnabled(onCompleted, request.workSource);
1271 } else {
1272 loge("isVoNrEnabled: No phone object");
1273 request.result = false;
1274 notifyRequester(request);
1275 }
1276 break;
1277 }
1278
1279 case EVENT_IS_VONR_ENABLED_DONE:
1280 ar = (AsyncResult) msg.obj;
1281 request = (MainThreadRequest) ar.userObj;
1282 if (ar.exception == null && ar.result != null) {
1283 request.result = ar.result;
1284 } else {
1285 // request.result must be set to something non-null
1286 // for the calling thread to unblock
1287 if (ar.result != null) {
1288 request.result = ar.result;
1289 } else {
1290 request.result = false;
1291 }
1292 if (ar.result == null) {
1293 loge("isVoNrEnabled: Empty response");
1294 } else if (ar.exception instanceof CommandException) {
1295 loge("isVoNrEnabled: CommandException: "
1296 + ar.exception);
1297 } else {
1298 loge("isVoNrEnabled: Unknown exception");
1299 }
1300 }
1301 notifyRequester(request);
1302 break;
1303
Sooraj Sasindran37444802020-08-11 10:40:43 -07001304 case CMD_ENABLE_NR_DUAL_CONNECTIVITY: {
1305 request = (MainThreadRequest) msg.obj;
1306 onCompleted = obtainMessage(EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE, request);
1307 Phone phone = getPhoneFromRequest(request);
1308 if (phone != null) {
1309 phone.setNrDualConnectivityState((int) request.argument, onCompleted,
1310 request.workSource);
1311 } else {
1312 loge("enableNrDualConnectivity: No phone object");
1313 request.result =
1314 TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
1315 notifyRequester(request);
1316 }
1317 break;
1318 }
1319
1320 case EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE: {
1321 ar = (AsyncResult) msg.obj;
1322 request = (MainThreadRequest) ar.userObj;
1323 if (ar.exception == null) {
1324 request.result =
1325 TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_SUCCESS;
1326 } else {
1327 request.result =
1328 TelephonyManager
1329 .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_ERROR;
1330 if (ar.exception instanceof CommandException) {
1331 CommandException.Error error =
1332 ((CommandException) (ar.exception)).getCommandError();
1333 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
1334 request.result =
1335 TelephonyManager
1336 .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
Sooraj Sasindran29654162021-03-03 23:00:01 +00001337 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1338 request.result =
1339 TelephonyManager
1340 .ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED;
Sooraj Sasindran37444802020-08-11 10:40:43 -07001341 }
1342 loge("enableNrDualConnectivity" + ": CommandException: "
1343 + ar.exception);
1344 } else {
1345 loge("enableNrDualConnectivity" + ": Unknown exception");
1346 }
1347 }
1348 notifyRequester(request);
1349 break;
1350 }
1351
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07001352 case CMD_ENABLE_VONR: {
1353 request = (MainThreadRequest) msg.obj;
1354 onCompleted = obtainMessage(EVENT_ENABLE_VONR_DONE, request);
1355 Phone phone = getPhoneFromRequest(request);
1356 if (phone != null) {
1357 phone.setVoNrEnabled((boolean) request.argument, onCompleted,
1358 request.workSource);
1359 } else {
1360 loge("setVoNrEnabled: No phone object");
1361 request.result =
1362 TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
1363 notifyRequester(request);
1364 }
1365 break;
1366 }
1367
1368 case EVENT_ENABLE_VONR_DONE: {
1369 ar = (AsyncResult) msg.obj;
1370 request = (MainThreadRequest) ar.userObj;
1371 if (ar.exception == null) {
1372 request.result = TelephonyManager.ENABLE_VONR_SUCCESS;
1373 } else {
1374 request.result = TelephonyManager.ENABLE_VONR_RADIO_ERROR;
1375 if (ar.exception instanceof CommandException) {
1376 CommandException.Error error =
1377 ((CommandException) (ar.exception)).getCommandError();
1378 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
1379 request.result = TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
1380 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1381 request.result = TelephonyManager.ENABLE_VONR_REQUEST_NOT_SUPPORTED;
1382 } else {
1383 request.result = TelephonyManager.ENABLE_VONR_RADIO_ERROR;
1384 }
1385 loge("setVoNrEnabled" + ": CommandException: "
1386 + ar.exception);
1387 } else {
1388 loge("setVoNrEnabled" + ": Unknown exception");
1389 }
1390 }
1391 notifyRequester(request);
1392 break;
1393 }
1394
SongFerngWang3ef3e072020-12-21 16:41:52 +08001395 case CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK:
Jake Hamby7c27be32014-03-03 13:25:59 -08001396 request = (MainThreadRequest) msg.obj;
SongFerngWang3ef3e072020-12-21 16:41:52 +08001397 onCompleted = obtainMessage(EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE,
1398 request);
1399 getPhoneFromRequest(request).getAllowedNetworkTypesBitmask(onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -08001400 break;
1401
SongFerngWang3ef3e072020-12-21 16:41:52 +08001402 case EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE:
Jake Hamby7c27be32014-03-03 13:25:59 -08001403 ar = (AsyncResult) msg.obj;
1404 request = (MainThreadRequest) ar.userObj;
1405 if (ar.exception == null && ar.result != null) {
1406 request.result = ar.result; // Integer
1407 } else {
Nazish Tabassume8ba43a2020-07-28 14:49:25 +05301408 // request.result must be set to something non-null
1409 // for the calling thread to unblock
1410 request.result = new int[]{-1};
Jake Hamby7c27be32014-03-03 13:25:59 -08001411 if (ar.result == null) {
SongFerngWang3ef3e072020-12-21 16:41:52 +08001412 loge("getAllowedNetworkTypesBitmask: Empty response");
Jake Hamby7c27be32014-03-03 13:25:59 -08001413 } else if (ar.exception instanceof CommandException) {
SongFerngWang3ef3e072020-12-21 16:41:52 +08001414 loge("getAllowedNetworkTypesBitmask: CommandException: "
1415 + ar.exception);
Jake Hamby7c27be32014-03-03 13:25:59 -08001416 } else {
SongFerngWang3ef3e072020-12-21 16:41:52 +08001417 loge("getAllowedNetworkTypesBitmask: Unknown exception");
Jake Hamby7c27be32014-03-03 13:25:59 -08001418 }
1419 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001420 notifyRequester(request);
Jake Hamby7c27be32014-03-03 13:25:59 -08001421 break;
1422
SongFerngWang3ef3e072020-12-21 16:41:52 +08001423 case CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON:
Jake Hamby7c27be32014-03-03 13:25:59 -08001424 request = (MainThreadRequest) msg.obj;
SongFerngWang3ef3e072020-12-21 16:41:52 +08001425 onCompleted = obtainMessage(EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE,
1426 request);
1427 Pair<Integer, Long> reasonWithNetworkTypes =
1428 (Pair<Integer, Long>) request.argument;
1429 getPhoneFromRequest(request).setAllowedNetworkTypes(
1430 reasonWithNetworkTypes.first,
1431 reasonWithNetworkTypes.second,
1432 onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -08001433 break;
1434
SongFerngWang3ef3e072020-12-21 16:41:52 +08001435 case EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE:
1436 handleNullReturnEvent(msg, "setAllowedNetworkTypesForReason");
Jake Hamby7c27be32014-03-03 13:25:59 -08001437 break;
1438
Shuo Qian850e4d6a2018-04-25 21:02:08 +00001439 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
1440 request = (MainThreadRequest)msg.obj;
1441 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001442 defaultPhone.invokeOemRilRequestRaw((byte[]) request.argument, onCompleted);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00001443 break;
1444
1445 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
1446 ar = (AsyncResult)msg.obj;
1447 request = (MainThreadRequest)ar.userObj;
1448 request.result = ar;
Pengquan Menga1bb6272018-09-06 09:59:22 -07001449 notifyRequester(request);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00001450 break;
1451
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001452 case CMD_SET_VOICEMAIL_NUMBER:
1453 request = (MainThreadRequest) msg.obj;
1454 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
1455 Pair<String, String> tagNum = (Pair<String, String>) request.argument;
Stuart Scott584921c2015-01-15 17:10:34 -08001456 getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
1457 onCompleted);
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001458 break;
1459
1460 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
1461 handleNullReturnEvent(msg, "setVoicemailNumber");
1462 break;
1463
Stuart Scott54788802015-03-30 13:18:01 -07001464 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
1465 request = (MainThreadRequest) msg.obj;
1466 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
1467 request);
1468 getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
1469 break;
1470
1471 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
1472 handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
1473 break;
1474
Shishir Agrawal302c8692015-06-19 13:49:39 -07001475 case CMD_PERFORM_NETWORK_SCAN:
1476 request = (MainThreadRequest) msg.obj;
1477 onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
1478 getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
1479 break;
1480
Hall Liu27d24262020-09-18 19:04:59 -07001481 case CMD_GET_CALL_FORWARDING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001482 request = (MainThreadRequest) msg.obj;
1483 onCompleted = obtainMessage(EVENT_GET_CALL_FORWARDING_DONE, request);
Hall Liu27d24262020-09-18 19:04:59 -07001484 Pair<Integer, TelephonyManager.CallForwardingInfoCallback> args =
1485 (Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
1486 request.argument;
1487 int callForwardingReason = args.first;
1488 request.phone.getCallForwardingOption(callForwardingReason, onCompleted);
Shuo Qian4a594052020-01-23 11:59:30 -08001489 break;
Hall Liu27d24262020-09-18 19:04:59 -07001490 }
1491 case EVENT_GET_CALL_FORWARDING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001492 ar = (AsyncResult) msg.obj;
1493 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001494 TelephonyManager.CallForwardingInfoCallback callback =
1495 ((Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
1496 request.argument).second;
Shuo Qian4a594052020-01-23 11:59:30 -08001497 if (ar.exception == null && ar.result != null) {
Hall Liu27d24262020-09-18 19:04:59 -07001498 CallForwardingInfo callForwardingInfo = null;
Shuo Qian4a594052020-01-23 11:59:30 -08001499 CallForwardInfo[] callForwardInfos = (CallForwardInfo[]) ar.result;
1500 for (CallForwardInfo callForwardInfo : callForwardInfos) {
1501 // Service Class is a bit mask per 3gpp 27.007. Search for
1502 // any service for voice call.
1503 if ((callForwardInfo.serviceClass
1504 & CommandsInterface.SERVICE_CLASS_VOICE) > 0) {
Yuchen Dong69cc1412021-09-27 20:27:01 +08001505 callForwardingInfo = new CallForwardingInfo(
1506 callForwardInfo.status
1507 == CommandsInterface.CF_ACTION_ENABLE,
Hall Liu27d24262020-09-18 19:04:59 -07001508 callForwardInfo.reason,
1509 callForwardInfo.number,
1510 callForwardInfo.timeSeconds);
Shuo Qian4a594052020-01-23 11:59:30 -08001511 break;
1512 }
1513 }
1514 // Didn't find a call forward info for voice call.
1515 if (callForwardingInfo == null) {
Hall Liu27d24262020-09-18 19:04:59 -07001516 callForwardingInfo = new CallForwardingInfo(false /* enabled */,
1517 0 /* reason */, null /* number */, 0 /* timeout */);
Shuo Qian4a594052020-01-23 11:59:30 -08001518 }
Hall Liu27d24262020-09-18 19:04:59 -07001519 callback.onCallForwardingInfoAvailable(callForwardingInfo);
Shuo Qian4a594052020-01-23 11:59:30 -08001520 } else {
1521 if (ar.result == null) {
1522 loge("EVENT_GET_CALL_FORWARDING_DONE: Empty response");
1523 }
1524 if (ar.exception != null) {
1525 loge("EVENT_GET_CALL_FORWARDING_DONE: Exception: " + ar.exception);
1526 }
Hall Liu940c4ca2020-09-29 17:10:18 -07001527 int errorCode = TelephonyManager
1528 .CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN;
Shuo Qian4a594052020-01-23 11:59:30 -08001529 if (ar.exception instanceof CommandException) {
1530 CommandException.Error error =
1531 ((CommandException) (ar.exception)).getCommandError();
1532 if (error == CommandException.Error.FDN_CHECK_FAILURE) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001533 errorCode = TelephonyManager
1534 .CallForwardingInfoCallback.RESULT_ERROR_FDN_CHECK_FAILURE;
Shuo Qian4a594052020-01-23 11:59:30 -08001535 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001536 errorCode = TelephonyManager
1537 .CallForwardingInfoCallback.RESULT_ERROR_NOT_SUPPORTED;
Shuo Qian4a594052020-01-23 11:59:30 -08001538 }
1539 }
Hall Liu27d24262020-09-18 19:04:59 -07001540 callback.onError(errorCode);
Shuo Qian4a594052020-01-23 11:59:30 -08001541 }
Shuo Qian4a594052020-01-23 11:59:30 -08001542 break;
Hall Liu27d24262020-09-18 19:04:59 -07001543 }
Shuo Qian4a594052020-01-23 11:59:30 -08001544
Hall Liu27d24262020-09-18 19:04:59 -07001545 case CMD_SET_CALL_FORWARDING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001546 request = (MainThreadRequest) msg.obj;
1547 onCompleted = obtainMessage(EVENT_SET_CALL_FORWARDING_DONE, request);
Hall Liu27d24262020-09-18 19:04:59 -07001548 request = (MainThreadRequest) msg.obj;
Shuo Qian4a594052020-01-23 11:59:30 -08001549 CallForwardingInfo callForwardingInfoToSet =
Hall Liu27d24262020-09-18 19:04:59 -07001550 ((Pair<CallForwardingInfo, Consumer<Integer>>)
1551 request.argument).first;
1552 request.phone.setCallForwardingOption(
1553 callForwardingInfoToSet.isEnabled()
Calvin Pan258f1f72021-07-28 21:46:56 +08001554 ? CommandsInterface.CF_ACTION_REGISTRATION
Hall Liu27d24262020-09-18 19:04:59 -07001555 : CommandsInterface.CF_ACTION_DISABLE,
Shuo Qian4a594052020-01-23 11:59:30 -08001556 callForwardingInfoToSet.getReason(),
1557 callForwardingInfoToSet.getNumber(),
1558 callForwardingInfoToSet.getTimeoutSeconds(), onCompleted);
1559 break;
Hall Liu27d24262020-09-18 19:04:59 -07001560 }
Shuo Qian4a594052020-01-23 11:59:30 -08001561
Hall Liu27d24262020-09-18 19:04:59 -07001562 case EVENT_SET_CALL_FORWARDING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001563 ar = (AsyncResult) msg.obj;
1564 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001565 Consumer<Integer> callback =
1566 ((Pair<CallForwardingInfo, Consumer<Integer>>)
1567 request.argument).second;
1568 if (ar.exception != null) {
Shuo Qian4a594052020-01-23 11:59:30 -08001569 loge("setCallForwarding exception: " + ar.exception);
Hall Liu940c4ca2020-09-29 17:10:18 -07001570 int errorCode = TelephonyManager.CallForwardingInfoCallback
1571 .RESULT_ERROR_UNKNOWN;
Hall Liu27d24262020-09-18 19:04:59 -07001572 if (ar.exception instanceof CommandException) {
1573 CommandException.Error error =
1574 ((CommandException) (ar.exception)).getCommandError();
1575 if (error == CommandException.Error.FDN_CHECK_FAILURE) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001576 errorCode = TelephonyManager.CallForwardingInfoCallback
1577 .RESULT_ERROR_FDN_CHECK_FAILURE;
Hall Liu27d24262020-09-18 19:04:59 -07001578 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001579 errorCode = TelephonyManager.CallForwardingInfoCallback
1580 .RESULT_ERROR_NOT_SUPPORTED;
Hall Liu27d24262020-09-18 19:04:59 -07001581 }
1582 }
1583 callback.accept(errorCode);
1584 } else {
Hall Liu940c4ca2020-09-29 17:10:18 -07001585 callback.accept(TelephonyManager.CallForwardingInfoCallback.RESULT_SUCCESS);
Shuo Qian4a594052020-01-23 11:59:30 -08001586 }
Shuo Qian4a594052020-01-23 11:59:30 -08001587 break;
Hall Liu27d24262020-09-18 19:04:59 -07001588 }
Shuo Qian4a594052020-01-23 11:59:30 -08001589
Hall Liu27d24262020-09-18 19:04:59 -07001590 case CMD_GET_CALL_WAITING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001591 request = (MainThreadRequest) msg.obj;
1592 onCompleted = obtainMessage(EVENT_GET_CALL_WAITING_DONE, request);
1593 getPhoneFromRequest(request).getCallWaiting(onCompleted);
1594 break;
Hall Liu27d24262020-09-18 19:04:59 -07001595 }
Shuo Qian4a594052020-01-23 11:59:30 -08001596
Hall Liu27d24262020-09-18 19:04:59 -07001597 case EVENT_GET_CALL_WAITING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001598 ar = (AsyncResult) msg.obj;
1599 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001600 Consumer<Integer> callback = (Consumer<Integer>) request.argument;
SongFerngWangebda2c52022-01-11 15:28:38 +08001601 int callWaitingStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
Shuo Qian4a594052020-01-23 11:59:30 -08001602 if (ar.exception == null && ar.result != null) {
Shuo Qiand6a0dba2020-02-18 18:13:49 -08001603 int[] callForwardResults = (int[]) ar.result;
Shuo Qian4a594052020-01-23 11:59:30 -08001604 // Service Class is a bit mask per 3gpp 27.007.
1605 // Search for any service for voice call.
Shuo Qiand6a0dba2020-02-18 18:13:49 -08001606 if (callForwardResults.length > 1
1607 && ((callForwardResults[1]
Hall Liu27d24262020-09-18 19:04:59 -07001608 & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
SongFerngWangebda2c52022-01-11 15:28:38 +08001609 callWaitingStatus = callForwardResults[0] == 0
Hall Liu27d24262020-09-18 19:04:59 -07001610 ? TelephonyManager.CALL_WAITING_STATUS_DISABLED
1611 : TelephonyManager.CALL_WAITING_STATUS_ENABLED;
Shuo Qian4a594052020-01-23 11:59:30 -08001612 } else {
SongFerngWangebda2c52022-01-11 15:28:38 +08001613 callWaitingStatus = TelephonyManager.CALL_WAITING_STATUS_DISABLED;
Shuo Qian4a594052020-01-23 11:59:30 -08001614 }
1615 } else {
1616 if (ar.result == null) {
1617 loge("EVENT_GET_CALL_WAITING_DONE: Empty response");
1618 }
1619 if (ar.exception != null) {
1620 loge("EVENT_GET_CALL_WAITING_DONE: Exception: " + ar.exception);
1621 }
1622 if (ar.exception instanceof CommandException) {
1623 CommandException.Error error =
1624 ((CommandException) (ar.exception)).getCommandError();
1625 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
SongFerngWangebda2c52022-01-11 15:28:38 +08001626 callWaitingStatus =
Shuo Qian4a594052020-01-23 11:59:30 -08001627 TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED;
SongFerngWangebda2c52022-01-11 15:28:38 +08001628 } else if (error == CommandException.Error.FDN_CHECK_FAILURE) {
1629 callWaitingStatus =
1630 TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE;
Shuo Qian4a594052020-01-23 11:59:30 -08001631 }
1632 }
1633 }
SongFerngWangebda2c52022-01-11 15:28:38 +08001634 callback.accept(callWaitingStatus);
Shuo Qian4a594052020-01-23 11:59:30 -08001635 break;
Hall Liu27d24262020-09-18 19:04:59 -07001636 }
Shuo Qian4a594052020-01-23 11:59:30 -08001637
Hall Liu27d24262020-09-18 19:04:59 -07001638 case CMD_SET_CALL_WAITING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001639 request = (MainThreadRequest) msg.obj;
1640 onCompleted = obtainMessage(EVENT_SET_CALL_WAITING_DONE, request);
Hall Liu27d24262020-09-18 19:04:59 -07001641 boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
1642 getPhoneFromRequest(request).setCallWaiting(enable, onCompleted);
Shuo Qian4a594052020-01-23 11:59:30 -08001643 break;
Hall Liu27d24262020-09-18 19:04:59 -07001644 }
Shuo Qian4a594052020-01-23 11:59:30 -08001645
Hall Liu27d24262020-09-18 19:04:59 -07001646 case EVENT_SET_CALL_WAITING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001647 ar = (AsyncResult) msg.obj;
1648 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001649 boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
1650 Consumer<Integer> callback =
1651 ((Pair<Boolean, Consumer<Integer>>) request.argument).second;
1652 if (ar.exception != null) {
Shuo Qian4a594052020-01-23 11:59:30 -08001653 loge("setCallWaiting exception: " + ar.exception);
Hall Liu27d24262020-09-18 19:04:59 -07001654 if (ar.exception instanceof CommandException) {
1655 CommandException.Error error =
1656 ((CommandException) (ar.exception)).getCommandError();
1657 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1658 callback.accept(TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED);
SongFerngWangebda2c52022-01-11 15:28:38 +08001659 } else if (error == CommandException.Error.FDN_CHECK_FAILURE) {
1660 callback.accept(
1661 TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE);
Hall Liu27d24262020-09-18 19:04:59 -07001662 } else {
1663 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
1664 }
1665 } else {
1666 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
1667 }
1668 } else {
1669 callback.accept(enable ? TelephonyManager.CALL_WAITING_STATUS_ENABLED
1670 : TelephonyManager.CALL_WAITING_STATUS_DISABLED);
Shuo Qian4a594052020-01-23 11:59:30 -08001671 }
Shuo Qian4a594052020-01-23 11:59:30 -08001672 break;
Hall Liu27d24262020-09-18 19:04:59 -07001673 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07001674 case EVENT_PERFORM_NETWORK_SCAN_DONE:
1675 ar = (AsyncResult) msg.obj;
1676 request = (MainThreadRequest) ar.userObj;
1677 CellNetworkScanResult cellScanResult;
1678 if (ar.exception == null && ar.result != null) {
1679 cellScanResult = new CellNetworkScanResult(
1680 CellNetworkScanResult.STATUS_SUCCESS,
1681 (List<OperatorInfo>) ar.result);
1682 } else {
1683 if (ar.result == null) {
1684 loge("getCellNetworkScanResults: Empty response");
1685 }
1686 if (ar.exception != null) {
1687 loge("getCellNetworkScanResults: Exception: " + ar.exception);
1688 }
1689 int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
1690 if (ar.exception instanceof CommandException) {
1691 CommandException.Error error =
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001692 ((CommandException) (ar.exception)).getCommandError();
Shishir Agrawal302c8692015-06-19 13:49:39 -07001693 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
1694 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
1695 } else if (error == CommandException.Error.GENERIC_FAILURE) {
1696 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
1697 }
1698 }
1699 cellScanResult = new CellNetworkScanResult(errorCode, null);
1700 }
1701 request.result = cellScanResult;
Pengquan Menga1bb6272018-09-06 09:59:22 -07001702 notifyRequester(request);
Shishir Agrawal302c8692015-06-19 13:49:39 -07001703 break;
1704
1705 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
1706 request = (MainThreadRequest) msg.obj;
Shishir Agrawal77ba3172015-09-10 14:50:19 -07001707 ManualNetworkSelectionArgument selArg =
1708 (ManualNetworkSelectionArgument) request.argument;
Shishir Agrawal302c8692015-06-19 13:49:39 -07001709 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
1710 request);
Shishir Agrawal77ba3172015-09-10 14:50:19 -07001711 getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
1712 selArg.persistSelection, onCompleted);
Shishir Agrawal302c8692015-06-19 13:49:39 -07001713 break;
1714
1715 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
Pengquan Menge3d01e22018-09-20 15:25:35 -07001716 ar = (AsyncResult) msg.obj;
1717 request = (MainThreadRequest) ar.userObj;
1718 if (ar.exception == null) {
1719 request.result = true;
1720 } else {
1721 request.result = false;
1722 loge("setNetworkSelectionModeManual " + ar.exception);
1723 }
1724 notifyRequester(request);
1725 mApp.onNetworkSelectionChanged(request.subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07001726 break;
1727
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001728 case CMD_GET_MODEM_ACTIVITY_INFO:
1729 request = (MainThreadRequest) msg.obj;
1730 onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
James Mattisab947702019-04-03 14:18:34 -07001731 if (defaultPhone != null) {
1732 defaultPhone.getModemActivityInfo(onCompleted, request.workSource);
Shuo Qian8f4750a2020-02-20 17:12:10 -08001733 } else {
1734 ResultReceiver result = (ResultReceiver) request.argument;
1735 Bundle bundle = new Bundle();
1736 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY,
Hall Liu49656c02020-10-09 19:00:11 -07001737 new ModemActivityInfo(0, 0, 0,
1738 new int[ModemActivityInfo.getNumTxPowerLevels()], 0));
Shuo Qian8f4750a2020-02-20 17:12:10 -08001739 result.send(0, bundle);
James Mattisab947702019-04-03 14:18:34 -07001740 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001741 break;
1742
Hall Liud0f208c2020-10-14 16:54:44 -07001743 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE: {
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001744 ar = (AsyncResult) msg.obj;
1745 request = (MainThreadRequest) ar.userObj;
Shuo Qian8f4750a2020-02-20 17:12:10 -08001746 ResultReceiver result = (ResultReceiver) request.argument;
Hall Liud0f208c2020-10-14 16:54:44 -07001747 int error = 0;
Kai Shi917fdc62022-11-28 14:01:02 -08001748 ModemActivityInfo ret = null;
Gary Jian3aa9a762022-01-24 16:41:19 +08001749 if (mLastModemActivityInfo == null) {
1750 mLastModemActivitySpecificInfo = new ActivityStatsTechSpecificInfo[1];
1751 mLastModemActivitySpecificInfo[0] =
1752 new ActivityStatsTechSpecificInfo(
1753 0,
1754 0,
1755 new int[ModemActivityInfo.getNumTxPowerLevels()],
1756 0);
1757 mLastModemActivityInfo =
1758 new ModemActivityInfo(0, 0, 0, mLastModemActivitySpecificInfo);
1759 }
1760
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001761 if (ar.exception == null && ar.result != null) {
Shuo Qian8f4750a2020-02-20 17:12:10 -08001762 // Update the last modem activity info and the result of the request.
1763 ModemActivityInfo info = (ModemActivityInfo) ar.result;
1764 if (isModemActivityInfoValid(info)) {
Gary Jian3aa9a762022-01-24 16:41:19 +08001765 mergeModemActivityInfo(info);
Gary Jian76280a42022-12-07 16:18:33 +08001766 } else {
1767 loge("queryModemActivityInfo: invalid response");
Shuo Qian8f4750a2020-02-20 17:12:10 -08001768 }
Kai Shi917fdc62022-11-28 14:01:02 -08001769 // This is needed to decouple ret from mLastModemActivityInfo
1770 // We don't want to return mLastModemActivityInfo which is updated
1771 // inside mergeModemActivityInfo()
1772 ret = new ModemActivityInfo(
1773 mLastModemActivityInfo.getTimestampMillis(),
1774 mLastModemActivityInfo.getSleepTimeMillis(),
1775 mLastModemActivityInfo.getIdleTimeMillis(),
1776 deepCopyModemActivitySpecificInfo(mLastModemActivitySpecificInfo));
Gary Jian3aa9a762022-01-24 16:41:19 +08001777
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001778 } else {
1779 if (ar.result == null) {
1780 loge("queryModemActivityInfo: Empty response");
Hall Liud0f208c2020-10-14 16:54:44 -07001781 error = TelephonyManager.ModemActivityInfoException
1782 .ERROR_INVALID_INFO_RECEIVED;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001783 } else if (ar.exception instanceof CommandException) {
Gary Jian3aa9a762022-01-24 16:41:19 +08001784 loge("queryModemActivityInfo: CommandException: " + ar.exception);
Hall Liud0f208c2020-10-14 16:54:44 -07001785 error = TelephonyManager.ModemActivityInfoException
1786 .ERROR_MODEM_RESPONSE_ERROR;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001787 } else {
1788 loge("queryModemActivityInfo: Unknown exception");
Hall Liud0f208c2020-10-14 16:54:44 -07001789 error = TelephonyManager.ModemActivityInfoException
1790 .ERROR_UNKNOWN;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001791 }
1792 }
Shuo Qian8f4750a2020-02-20 17:12:10 -08001793 Bundle bundle = new Bundle();
Kai Shi917fdc62022-11-28 14:01:02 -08001794 if (ret != null) {
Gary Jian3aa9a762022-01-24 16:41:19 +08001795 bundle.putParcelable(
1796 TelephonyManager.MODEM_ACTIVITY_RESULT_KEY,
Kai Shi917fdc62022-11-28 14:01:02 -08001797 ret);
Hall Liud0f208c2020-10-14 16:54:44 -07001798 } else {
1799 bundle.putInt(TelephonyManager.EXCEPTION_RESULT_KEY, error);
1800 }
Shuo Qian8f4750a2020-02-20 17:12:10 -08001801 result.send(0, bundle);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001802 notifyRequester(request);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001803 break;
Hall Liud0f208c2020-10-14 16:54:44 -07001804 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001805
Sarah Chin4a9e8b82023-02-10 21:10:57 -08001806 case CMD_SET_ALLOWED_CARRIERS: {
Meng Wang1a7c35a2016-05-05 20:56:15 -07001807 request = (MainThreadRequest) msg.obj;
Michele Berionne482f8202018-11-27 18:57:59 -08001808 CarrierRestrictionRules argument =
1809 (CarrierRestrictionRules) request.argument;
Meng Wang1a7c35a2016-05-05 20:56:15 -07001810 onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
Michele Berionne482f8202018-11-27 18:57:59 -08001811 defaultPhone.setAllowedCarriers(argument, onCompleted, request.workSource);
Meng Wang1a7c35a2016-05-05 20:56:15 -07001812 break;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08001813 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07001814
1815 case EVENT_SET_ALLOWED_CARRIERS_DONE:
1816 ar = (AsyncResult) msg.obj;
1817 request = (MainThreadRequest) ar.userObj;
1818 if (ar.exception == null && ar.result != null) {
1819 request.result = ar.result;
1820 } else {
Michele Berionne482f8202018-11-27 18:57:59 -08001821 request.result = TelephonyManager.SET_CARRIER_RESTRICTION_ERROR;
1822 if (ar.exception instanceof CommandException) {
1823 loge("setAllowedCarriers: CommandException: " + ar.exception);
1824 CommandException.Error error =
1825 ((CommandException) (ar.exception)).getCommandError();
1826 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1827 request.result =
1828 TelephonyManager.SET_CARRIER_RESTRICTION_NOT_SUPPORTED;
1829 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07001830 } else {
1831 loge("setAllowedCarriers: Unknown exception");
1832 }
1833 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001834 notifyRequester(request);
Meng Wang1a7c35a2016-05-05 20:56:15 -07001835 break;
1836
1837 case CMD_GET_ALLOWED_CARRIERS:
1838 request = (MainThreadRequest) msg.obj;
1839 onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001840 defaultPhone.getAllowedCarriers(onCompleted, request.workSource);
Meng Wang1a7c35a2016-05-05 20:56:15 -07001841 break;
1842
1843 case EVENT_GET_ALLOWED_CARRIERS_DONE:
1844 ar = (AsyncResult) msg.obj;
1845 request = (MainThreadRequest) ar.userObj;
1846 if (ar.exception == null && ar.result != null) {
1847 request.result = ar.result;
1848 } else {
Michele Berionne482f8202018-11-27 18:57:59 -08001849 request.result = new IllegalStateException(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001850 "Failed to get carrier restrictions");
Meng Wang1a7c35a2016-05-05 20:56:15 -07001851 if (ar.result == null) {
1852 loge("getAllowedCarriers: Empty response");
1853 } else if (ar.exception instanceof CommandException) {
1854 loge("getAllowedCarriers: CommandException: " +
1855 ar.exception);
1856 } else {
1857 loge("getAllowedCarriers: Unknown exception");
1858 }
1859 }
arunvoddud7401012022-12-15 16:08:12 +00001860 if (request.argument != null) {
1861 // This is for the implementation of carrierRestrictionStatus.
1862 CallerCallbackInfo callbackInfo = (CallerCallbackInfo) request.argument;
1863 Consumer<Integer> callback = callbackInfo.getConsumer();
1864 int callerCarrierId = callbackInfo.getCarrierId();
1865 int lockStatus = TelephonyManager.CARRIER_RESTRICTION_STATUS_UNKNOWN;
1866 if (ar.exception == null && ar.result instanceof CarrierRestrictionRules) {
1867 CarrierRestrictionRules carrierRestrictionRules =
1868 (CarrierRestrictionRules) ar.result;
1869 int carrierId = -1;
1870 try {
1871 CarrierIdentifier carrierIdentifier =
1872 carrierRestrictionRules.getAllowedCarriers().get(0);
1873 carrierId = CarrierResolver.getCarrierIdFromIdentifier(mApp,
1874 carrierIdentifier);
1875 } catch (NullPointerException | IndexOutOfBoundsException ex) {
1876 Rlog.e(LOG_TAG, "CarrierIdentifier exception = " + ex);
1877 }
1878 lockStatus = carrierRestrictionRules.getCarrierRestrictionStatus();
1879 if (carrierId != -1 && callerCarrierId == carrierId && lockStatus
1880 == TelephonyManager.CARRIER_RESTRICTION_STATUS_RESTRICTED) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001881 lockStatus = TelephonyManager
1882 .CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER;
arunvoddud7401012022-12-15 16:08:12 +00001883 }
1884 } else {
1885 Rlog.e(LOG_TAG,
1886 "getCarrierRestrictionStatus: exception ex = " + ar.exception);
1887 }
1888 callback.accept(lockStatus);
1889 } else {
1890 // This is for the implementation of getAllowedCarriers.
1891 notifyRequester(request);
1892 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07001893 break;
1894
Nathan Haroldb3014052017-01-25 15:57:32 -08001895 case EVENT_GET_FORBIDDEN_PLMNS_DONE:
1896 ar = (AsyncResult) msg.obj;
1897 request = (MainThreadRequest) ar.userObj;
1898 if (ar.exception == null && ar.result != null) {
1899 request.result = ar.result;
1900 } else {
1901 request.result = new IllegalArgumentException(
1902 "Failed to retrieve Forbidden Plmns");
1903 if (ar.result == null) {
1904 loge("getForbiddenPlmns: Empty response");
1905 } else {
1906 loge("getForbiddenPlmns: Unknown exception");
1907 }
1908 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001909 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -08001910 break;
1911
1912 case CMD_GET_FORBIDDEN_PLMNS:
1913 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001914 uiccPort = getUiccPortFromRequest(request);
1915 if (uiccPort == null) {
1916 loge("getForbiddenPlmns() UiccPort is null");
Nathan Haroldb3014052017-01-25 15:57:32 -08001917 request.result = new IllegalArgumentException(
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001918 "getForbiddenPlmns() UiccPort is null");
Pengquan Menga1bb6272018-09-06 09:59:22 -07001919 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -08001920 break;
1921 }
1922 Integer appType = (Integer) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001923 UiccCardApplication uiccApp = uiccPort.getApplicationByType(appType);
Nathan Haroldb3014052017-01-25 15:57:32 -08001924 if (uiccApp == null) {
1925 loge("getForbiddenPlmns() no app with specified type -- "
1926 + appType);
1927 request.result = new IllegalArgumentException("Failed to get UICC App");
Pengquan Menga1bb6272018-09-06 09:59:22 -07001928 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -08001929 break;
1930 } else {
1931 if (DBG) logv("getForbiddenPlmns() found app " + uiccApp.getAid()
1932 + " specified type -- " + appType);
1933 }
1934 onCompleted = obtainMessage(EVENT_GET_FORBIDDEN_PLMNS_DONE, request);
1935 ((SIMRecords) uiccApp.getIccRecords()).getForbiddenPlmns(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001936 onCompleted);
Nathan Haroldb3014052017-01-25 15:57:32 -08001937 break;
1938
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001939 case CMD_SWITCH_SLOTS:
1940 request = (MainThreadRequest) msg.obj;
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00001941 List<UiccSlotMapping> slotMapping = (List<UiccSlotMapping>) request.argument;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001942 onCompleted = obtainMessage(EVENT_SWITCH_SLOTS_DONE, request);
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00001943 UiccController.getInstance().switchSlots(slotMapping, onCompleted);
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001944 break;
1945
1946 case EVENT_SWITCH_SLOTS_DONE:
1947 ar = (AsyncResult) msg.obj;
1948 request = (MainThreadRequest) ar.userObj;
1949 request.result = (ar.exception == null);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001950 notifyRequester(request);
1951 break;
1952 case CMD_GET_NETWORK_SELECTION_MODE:
1953 request = (MainThreadRequest) msg.obj;
1954 onCompleted = obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, request);
1955 getPhoneFromRequest(request).getNetworkSelectionMode(onCompleted);
1956 break;
1957
1958 case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
1959 ar = (AsyncResult) msg.obj;
1960 request = (MainThreadRequest) ar.userObj;
1961 if (ar.exception != null) {
1962 request.result = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
1963 } else {
1964 int mode = ((int[]) ar.result)[0];
1965 if (mode == 0) {
1966 request.result = TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
1967 } else {
1968 request.result = TelephonyManager.NETWORK_SELECTION_MODE_MANUAL;
1969 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001970 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001971 notifyRequester(request);
1972 break;
1973 case CMD_GET_CDMA_ROAMING_MODE:
1974 request = (MainThreadRequest) msg.obj;
1975 onCompleted = obtainMessage(EVENT_GET_CDMA_ROAMING_MODE_DONE, request);
1976 getPhoneFromRequest(request).queryCdmaRoamingPreference(onCompleted);
1977 break;
1978 case EVENT_GET_CDMA_ROAMING_MODE_DONE:
1979 ar = (AsyncResult) msg.obj;
1980 request = (MainThreadRequest) ar.userObj;
1981 if (ar.exception != null) {
1982 request.result = TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT;
1983 } else {
1984 request.result = ((int[]) ar.result)[0];
1985 }
1986 notifyRequester(request);
1987 break;
1988 case CMD_SET_CDMA_ROAMING_MODE:
1989 request = (MainThreadRequest) msg.obj;
1990 onCompleted = obtainMessage(EVENT_SET_CDMA_ROAMING_MODE_DONE, request);
1991 int mode = (int) request.argument;
1992 getPhoneFromRequest(request).setCdmaRoamingPreference(mode, onCompleted);
1993 break;
1994 case EVENT_SET_CDMA_ROAMING_MODE_DONE:
1995 ar = (AsyncResult) msg.obj;
1996 request = (MainThreadRequest) ar.userObj;
1997 request.result = ar.exception == null;
1998 notifyRequester(request);
1999 break;
Sarah Chinbaab1432020-10-28 13:46:24 -07002000 case CMD_GET_CDMA_SUBSCRIPTION_MODE:
2001 request = (MainThreadRequest) msg.obj;
2002 onCompleted = obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE, request);
2003 getPhoneFromRequest(request).queryCdmaSubscriptionMode(onCompleted);
2004 break;
2005 case EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE:
2006 ar = (AsyncResult) msg.obj;
2007 request = (MainThreadRequest) ar.userObj;
2008 if (ar.exception != null) {
2009 request.result = TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM;
2010 } else {
2011 request.result = ((int[]) ar.result)[0];
2012 }
2013 notifyRequester(request);
2014 break;
Pengquan Menga1bb6272018-09-06 09:59:22 -07002015 case CMD_SET_CDMA_SUBSCRIPTION_MODE:
2016 request = (MainThreadRequest) msg.obj;
2017 onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
2018 int subscriptionMode = (int) request.argument;
Sarah Chinbaab1432020-10-28 13:46:24 -07002019 getPhoneFromRequest(request).setCdmaSubscriptionMode(
2020 subscriptionMode, onCompleted);
Pengquan Menga1bb6272018-09-06 09:59:22 -07002021 break;
2022 case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
2023 ar = (AsyncResult) msg.obj;
2024 request = (MainThreadRequest) ar.userObj;
2025 request.result = ar.exception == null;
2026 notifyRequester(request);
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00002027 break;
Nathan Harold3ff88932018-08-14 10:19:49 -07002028 case CMD_GET_ALL_CELL_INFO:
2029 request = (MainThreadRequest) msg.obj;
Nathan Harold3ff88932018-08-14 10:19:49 -07002030 onCompleted = obtainMessage(EVENT_GET_ALL_CELL_INFO_DONE, request);
Nathan Harold92bed182018-10-12 18:16:49 -07002031 request.phone.requestCellInfoUpdate(request.workSource, onCompleted);
Nathan Harold3ff88932018-08-14 10:19:49 -07002032 break;
Nathan Harold3ff88932018-08-14 10:19:49 -07002033 case EVENT_GET_ALL_CELL_INFO_DONE:
2034 ar = (AsyncResult) msg.obj;
2035 request = (MainThreadRequest) ar.userObj;
Nathan Harold8d0f1742018-10-02 12:14:47 -07002036 // If a timeout occurs, the response will be null
2037 request.result = (ar.exception == null && ar.result != null)
2038 ? ar.result : new ArrayList<CellInfo>();
Nathan Harold3ff88932018-08-14 10:19:49 -07002039 synchronized (request) {
2040 request.notifyAll();
2041 }
2042 break;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002043 case CMD_REQUEST_CELL_INFO_UPDATE:
2044 request = (MainThreadRequest) msg.obj;
2045 request.phone.requestCellInfoUpdate(request.workSource,
2046 obtainMessage(EVENT_REQUEST_CELL_INFO_UPDATE_DONE, request));
2047 break;
2048 case EVENT_REQUEST_CELL_INFO_UPDATE_DONE:
2049 ar = (AsyncResult) msg.obj;
2050 request = (MainThreadRequest) ar.userObj;
2051 ICellInfoCallback cb = (ICellInfoCallback) request.argument;
2052 try {
2053 if (ar.exception != null) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002054 Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
Meng Wangd8921f42019-09-30 17:13:54 -07002055 cb.onError(
2056 TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
2057 ar.exception.getClass().getName(),
2058 ar.exception.toString());
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002059 } else if (ar.result == null) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002060 Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
Meng Wangd8921f42019-09-30 17:13:54 -07002061 cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null, null);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002062 } else {
2063 // use the result as returned
2064 cb.onCellInfo((List<CellInfo>) ar.result);
2065 }
2066 } catch (RemoteException re) {
2067 Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
2068 }
2069 break;
Sarah Chin679c08a2020-11-18 13:39:35 -08002070 case CMD_GET_CELL_LOCATION: {
Nathan Harold3ff88932018-08-14 10:19:49 -07002071 request = (MainThreadRequest) msg.obj;
2072 WorkSource ws = (WorkSource) request.argument;
2073 Phone phone = getPhoneFromRequest(request);
Meng Wanga10e89e2019-12-09 13:13:01 -08002074 phone.getCellIdentity(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
Nathan Harold3ff88932018-08-14 10:19:49 -07002075 break;
Sarah Chin679c08a2020-11-18 13:39:35 -08002076 }
2077 case EVENT_GET_CELL_LOCATION_DONE: {
Nathan Harold3ff88932018-08-14 10:19:49 -07002078 ar = (AsyncResult) msg.obj;
2079 request = (MainThreadRequest) ar.userObj;
2080 if (ar.exception == null) {
2081 request.result = ar.result;
2082 } else {
Sarah Chin679c08a2020-11-18 13:39:35 -08002083 Phone phone = getPhoneFromRequest(request);
Nathan Harold3ff88932018-08-14 10:19:49 -07002084 request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
Meng Wanga10e89e2019-12-09 13:13:01 -08002085 ? new CellIdentityCdma() : new CellIdentityGsm();
Nathan Harold3ff88932018-08-14 10:19:49 -07002086 }
2087
2088 synchronized (request) {
2089 request.notifyAll();
2090 }
2091 break;
Sarah Chin679c08a2020-11-18 13:39:35 -08002092 }
chen xu6dac5ab2018-10-26 17:39:23 -07002093 case CMD_MODEM_REBOOT:
2094 request = (MainThreadRequest) msg.obj;
2095 onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002096 defaultPhone.rebootModem(onCompleted);
chen xu6dac5ab2018-10-26 17:39:23 -07002097 break;
chen xu6dac5ab2018-10-26 17:39:23 -07002098 case EVENT_CMD_MODEM_REBOOT_DONE:
2099 handleNullReturnEvent(msg, "rebootModem");
2100 break;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002101 case CMD_REQUEST_ENABLE_MODEM: {
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002102 request = (MainThreadRequest) msg.obj;
2103 boolean enable = (boolean) request.argument;
2104 onCompleted = obtainMessage(EVENT_ENABLE_MODEM_DONE, request);
Nazanin Bakhshi33d584b2019-02-27 10:44:32 -08002105 onCompleted.arg1 = enable ? 1 : 0;
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002106 PhoneConfigurationManager.getInstance()
2107 .enablePhone(request.phone, enable, onCompleted);
2108 break;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002109 }
Michele Berionne5e411512020-11-13 02:36:59 +00002110 case EVENT_ENABLE_MODEM_DONE: {
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002111 ar = (AsyncResult) msg.obj;
2112 request = (MainThreadRequest) ar.userObj;
2113 request.result = (ar.exception == null);
Nazanin Bakhshif71371d2019-04-29 17:29:44 -07002114 int phoneId = request.phone.getPhoneId();
Nazanin Bakhshi33d584b2019-02-27 10:44:32 -08002115 //update the cache as modem status has changed
Nazanin Bakhshif71371d2019-04-29 17:29:44 -07002116 if ((boolean) request.result) {
2117 mPhoneConfigurationManager.addToPhoneStatusCache(phoneId, msg.arg1 == 1);
2118 updateModemStateMetrics();
2119 } else {
2120 Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
2121 + ar.exception);
2122 }
2123 notifyRequester(request);
2124 break;
Michele Berionne5e411512020-11-13 02:36:59 +00002125 }
Nazanin Bakhshif71371d2019-04-29 17:29:44 -07002126 case CMD_GET_MODEM_STATUS:
2127 request = (MainThreadRequest) msg.obj;
2128 onCompleted = obtainMessage(EVENT_GET_MODEM_STATUS_DONE, request);
2129 PhoneConfigurationManager.getInstance()
2130 .getPhoneStatusFromModem(request.phone, onCompleted);
2131 break;
2132 case EVENT_GET_MODEM_STATUS_DONE:
2133 ar = (AsyncResult) msg.obj;
2134 request = (MainThreadRequest) ar.userObj;
2135 int id = request.phone.getPhoneId();
2136 if (ar.exception == null && ar.result != null) {
2137 request.result = ar.result;
2138 //update the cache as modem status has changed
2139 mPhoneConfigurationManager.addToPhoneStatusCache(id,
2140 (boolean) request.result);
2141 } else {
2142 // Return true if modem status cannot be retrieved. For most cases,
2143 // modem status is on. And for older version modems, GET_MODEM_STATUS
2144 // and disable modem are not supported. Modem is always on.
2145 // TODO: this should be fixed in R to support a third
2146 // status UNKNOWN b/131631629
2147 request.result = true;
2148 Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
2149 + ar.exception);
2150 }
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002151 notifyRequester(request);
2152 break;
Hall Liu73f5d362020-01-20 13:42:00 -08002153 case CMD_SET_SYSTEM_SELECTION_CHANNELS: {
2154 request = (MainThreadRequest) msg.obj;
2155 onCompleted = obtainMessage(EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE, request);
2156 Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> args =
2157 (Pair<List<RadioAccessSpecifier>, Consumer<Boolean>>) request.argument;
2158 request.phone.setSystemSelectionChannels(args.first, onCompleted);
2159 break;
2160 }
2161 case EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE: {
2162 ar = (AsyncResult) msg.obj;
2163 request = (MainThreadRequest) ar.userObj;
2164 Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> args =
2165 (Pair<List<RadioAccessSpecifier>, Consumer<Boolean>>) request.argument;
2166 args.second.accept(ar.exception == null);
2167 notifyRequester(request);
2168 break;
2169 }
Sarah Chin679c08a2020-11-18 13:39:35 -08002170 case CMD_GET_SYSTEM_SELECTION_CHANNELS: {
2171 request = (MainThreadRequest) msg.obj;
2172 onCompleted = obtainMessage(EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE, request);
2173 Phone phone = getPhoneFromRequest(request);
2174 if (phone != null) {
2175 phone.getSystemSelectionChannels(onCompleted);
2176 } else {
2177 loge("getSystemSelectionChannels: No phone object");
2178 request.result = new ArrayList<RadioAccessSpecifier>();
2179 notifyRequester(request);
2180 }
2181 break;
2182 }
2183 case EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE:
2184 ar = (AsyncResult) msg.obj;
2185 request = (MainThreadRequest) ar.userObj;
2186 if (ar.exception == null && ar.result != null) {
2187 request.result = ar.result;
2188 } else {
Sarah Chin428d1d62021-03-13 03:17:40 -08002189 request.result = new IllegalStateException(
2190 "Failed to retrieve system selecton channels");
Sarah Chin679c08a2020-11-18 13:39:35 -08002191 if (ar.result == null) {
2192 loge("getSystemSelectionChannels: Empty response");
2193 } else {
2194 loge("getSystemSelectionChannels: Unknown exception");
2195 }
2196 }
2197 notifyRequester(request);
2198 break;
yincheng zhao2737e882019-09-06 17:06:54 -07002199 case EVENT_SET_FORBIDDEN_PLMNS_DONE:
2200 ar = (AsyncResult) msg.obj;
2201 request = (MainThreadRequest) ar.userObj;
2202 if (ar.exception == null && ar.result != null) {
2203 request.result = ar.result;
2204 } else {
2205 request.result = -1;
2206 loge("Failed to set Forbidden Plmns");
2207 if (ar.result == null) {
2208 loge("setForbidenPlmns: Empty response");
2209 } else if (ar.exception != null) {
2210 loge("setForbiddenPlmns: Exception: " + ar.exception);
2211 request.result = -1;
2212 } else {
2213 loge("setForbiddenPlmns: Unknown exception");
2214 }
2215 }
2216 notifyRequester(request);
2217 break;
2218 case CMD_SET_FORBIDDEN_PLMNS:
2219 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00002220 uiccPort = getUiccPortFromRequest(request);
2221 if (uiccPort == null) {
2222 loge("setForbiddenPlmns: UiccPort is null");
yincheng zhao2737e882019-09-06 17:06:54 -07002223 request.result = -1;
2224 notifyRequester(request);
2225 break;
2226 }
2227 Pair<Integer, List<String>> setFplmnsArgs =
2228 (Pair<Integer, List<String>>) request.argument;
2229 appType = setFplmnsArgs.first;
2230 List<String> fplmns = setFplmnsArgs.second;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00002231 uiccApp = uiccPort.getApplicationByType(appType);
yincheng zhao2737e882019-09-06 17:06:54 -07002232 if (uiccApp == null) {
2233 loge("setForbiddenPlmns: no app with specified type -- " + appType);
2234 request.result = -1;
2235 loge("Failed to get UICC App");
2236 notifyRequester(request);
2237 } else {
2238 onCompleted = obtainMessage(EVENT_SET_FORBIDDEN_PLMNS_DONE, request);
2239 ((SIMRecords) uiccApp.getIccRecords())
2240 .setForbiddenPlmns(onCompleted, fplmns);
2241 }
yinchengzhao4d163c02019-12-12 15:21:47 -08002242 break;
Naina Nallurid63128d2019-09-17 14:10:30 -07002243 case CMD_ERASE_MODEM_CONFIG:
2244 request = (MainThreadRequest) msg.obj;
2245 onCompleted = obtainMessage(EVENT_ERASE_MODEM_CONFIG_DONE, request);
2246 defaultPhone.eraseModemConfig(onCompleted);
2247 break;
2248 case EVENT_ERASE_MODEM_CONFIG_DONE:
2249 handleNullReturnEvent(msg, "eraseModemConfig");
yincheng zhao2737e882019-09-06 17:06:54 -07002250 break;
zoey chene02881a2019-12-30 16:11:23 +08002251
Kai Shif70f46f2021-03-03 13:59:46 -08002252 case CMD_ERASE_DATA_SHARED_PREFERENCES:
2253 request = (MainThreadRequest) msg.obj;
2254 request.result = defaultPhone.eraseDataInSharedPreferences();
2255 notifyRequester(request);
2256 break;
2257
zoey chene02881a2019-12-30 16:11:23 +08002258 case CMD_CHANGE_ICC_LOCK_PASSWORD:
2259 request = (MainThreadRequest) msg.obj;
2260 onCompleted = obtainMessage(EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE, request);
2261 Pair<String, String> changed = (Pair<String, String>) request.argument;
2262 getPhoneFromRequest(request).getIccCard().changeIccLockPassword(
2263 changed.first, changed.second, onCompleted);
2264 break;
2265 case EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE:
2266 ar = (AsyncResult) msg.obj;
2267 request = (MainThreadRequest) ar.userObj;
2268 if (ar.exception == null) {
2269 request.result = TelephonyManager.CHANGE_ICC_LOCK_SUCCESS;
Michele Berionne5e411512020-11-13 02:36:59 +00002270 // If the operation is successful, update the PIN storage
2271 Pair<String, String> passwords = (Pair<String, String>) request.argument;
2272 int phoneId = getPhoneFromRequest(request).getPhoneId();
Jon Spivack9c3bc762021-10-06 20:53:09 +00002273 UiccController.getInstance().getPinStorage()
2274 .storePin(passwords.second, phoneId);
zoey chene02881a2019-12-30 16:11:23 +08002275 } else {
2276 request.result = msg.arg1;
2277 }
2278 notifyRequester(request);
2279 break;
2280
Michele Berionne5e411512020-11-13 02:36:59 +00002281 case CMD_SET_ICC_LOCK_ENABLED: {
zoey chene02881a2019-12-30 16:11:23 +08002282 request = (MainThreadRequest) msg.obj;
2283 onCompleted = obtainMessage(EVENT_SET_ICC_LOCK_ENABLED_DONE, request);
2284 Pair<Boolean, String> enabled = (Pair<Boolean, String>) request.argument;
2285 getPhoneFromRequest(request).getIccCard().setIccLockEnabled(
2286 enabled.first, enabled.second, onCompleted);
2287 break;
Michele Berionne5e411512020-11-13 02:36:59 +00002288 }
zoey chene02881a2019-12-30 16:11:23 +08002289 case EVENT_SET_ICC_LOCK_ENABLED_DONE:
2290 ar = (AsyncResult) msg.obj;
2291 request = (MainThreadRequest) ar.userObj;
2292 if (ar.exception == null) {
2293 request.result = TelephonyManager.CHANGE_ICC_LOCK_SUCCESS;
Michele Berionne5e411512020-11-13 02:36:59 +00002294 // If the operation is successful, update the PIN storage
2295 Pair<Boolean, String> enabled = (Pair<Boolean, String>) request.argument;
2296 int phoneId = getPhoneFromRequest(request).getPhoneId();
2297 if (enabled.first) {
Jon Spivack9c3bc762021-10-06 20:53:09 +00002298 UiccController.getInstance().getPinStorage()
2299 .storePin(enabled.second, phoneId);
Michele Berionne5e411512020-11-13 02:36:59 +00002300 } else {
2301 UiccController.getInstance().getPinStorage().clearPin(phoneId);
2302 }
zoey chene02881a2019-12-30 16:11:23 +08002303 } else {
2304 request.result = msg.arg1;
2305 }
Michele Berionne5e411512020-11-13 02:36:59 +00002306
2307
zoey chene02881a2019-12-30 16:11:23 +08002308 notifyRequester(request);
2309 break;
2310
Peter Wangdafb9ac2020-01-15 14:13:38 -08002311 case MSG_NOTIFY_USER_ACTIVITY:
2312 removeMessages(MSG_NOTIFY_USER_ACTIVITY);
Peter Wang59571be2020-01-27 12:35:15 +08002313 Intent intent = new Intent(TelephonyIntents.ACTION_USER_ACTIVITY_NOTIFICATION);
Peter Wangdafb9ac2020-01-15 14:13:38 -08002314 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2315 getDefaultPhone().getContext().sendBroadcastAsUser(
2316 intent, UserHandle.ALL, permission.USER_ACTIVITY);
2317 break;
Jack Nudelmanb0b87642020-11-12 15:04:39 -08002318
2319 case CMD_SET_DATA_THROTTLING: {
2320 request = (MainThreadRequest) msg.obj;
2321 onCompleted = obtainMessage(EVENT_SET_DATA_THROTTLING_DONE, request);
2322 DataThrottlingRequest dataThrottlingRequest =
2323 (DataThrottlingRequest) request.argument;
2324 Phone phone = getPhoneFromRequest(request);
2325 if (phone != null) {
2326 phone.setDataThrottling(onCompleted,
2327 request.workSource, dataThrottlingRequest.getDataThrottlingAction(),
2328 dataThrottlingRequest.getCompletionDurationMillis());
2329 } else {
2330 loge("setDataThrottling: No phone object");
2331 request.result =
2332 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
2333 notifyRequester(request);
2334 }
2335
2336 break;
2337 }
2338 case EVENT_SET_DATA_THROTTLING_DONE:
2339 ar = (AsyncResult) msg.obj;
2340 request = (MainThreadRequest) ar.userObj;
2341
2342 if (ar.exception == null) {
2343 request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
2344 } else if (ar.exception instanceof CommandException) {
2345 loge("setDataThrottling: CommandException: " + ar.exception);
2346 CommandException.Error error =
2347 ((CommandException) (ar.exception)).getCommandError();
2348
2349 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
2350 request.result = TelephonyManager
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002351 .THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -08002352 } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
2353 request.result = SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS;
Jack Nudelman5d6a98b2021-03-04 14:26:25 -08002354 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
2355 request.result = MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -08002356 } else {
2357 request.result =
2358 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
2359 }
2360 } else {
2361 request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
2362 }
2363 Log.w(LOG_TAG, "DataThrottlingResult = " + request.result);
2364 notifyRequester(request);
2365 break;
Jordan Liu109698e2020-11-24 14:50:34 -08002366
2367 case CMD_SET_SIM_POWER: {
2368 request = (MainThreadRequest) msg.obj;
2369 onCompleted = obtainMessage(EVENT_SET_SIM_POWER_DONE, request);
2370 request = (MainThreadRequest) msg.obj;
2371 int stateToSet =
2372 ((Pair<Integer, IIntegerConsumer>)
2373 request.argument).first;
2374 request.phone.setSimPowerState(stateToSet, onCompleted, request.workSource);
2375 break;
2376 }
2377 case EVENT_SET_SIM_POWER_DONE: {
2378 ar = (AsyncResult) msg.obj;
2379 request = (MainThreadRequest) ar.userObj;
2380 IIntegerConsumer callback =
2381 ((Pair<Integer, IIntegerConsumer>) request.argument).second;
2382 if (ar.exception != null) {
2383 loge("setSimPower exception: " + ar.exception);
2384 int errorCode = TelephonyManager.CallForwardingInfoCallback
2385 .RESULT_ERROR_UNKNOWN;
2386 if (ar.exception instanceof CommandException) {
2387 CommandException.Error error =
2388 ((CommandException) (ar.exception)).getCommandError();
2389 if (error == CommandException.Error.SIM_ERR) {
2390 errorCode = TelephonyManager.SET_SIM_POWER_STATE_SIM_ERROR;
2391 } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
2392 errorCode = TelephonyManager.SET_SIM_POWER_STATE_ALREADY_IN_STATE;
2393 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
2394 errorCode = TelephonyManager.SET_SIM_POWER_STATE_NOT_SUPPORTED;
2395 } else {
2396 errorCode = TelephonyManager.SET_SIM_POWER_STATE_MODEM_ERROR;
2397 }
2398 }
2399 try {
2400 callback.accept(errorCode);
2401 } catch (RemoteException e) {
2402 // Ignore if the remote process is no longer available to call back.
2403 Log.w(LOG_TAG, "setSimPower: callback not available.");
2404 }
2405 } else {
2406 try {
2407 callback.accept(TelephonyManager.SET_SIM_POWER_STATE_SUCCESS);
2408 } catch (RemoteException e) {
2409 // Ignore if the remote process is no longer available to call back.
2410 Log.w(LOG_TAG, "setSimPower: callback not available.");
2411 }
2412 }
2413 break;
2414 }
Rambo Wanga5cc9b72021-01-07 10:51:54 -08002415 case CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST: {
2416 request = (MainThreadRequest) msg.obj;
2417
2418 final Phone phone = getPhoneFromRequest(request);
2419 if (phone == null || phone.getServiceStateTracker() == null) {
2420 request.result = new IllegalStateException("Phone or SST is null");
2421 notifyRequester(request);
2422 break;
2423 }
2424
2425 Pair<Integer, SignalStrengthUpdateRequest> pair =
2426 (Pair<Integer, SignalStrengthUpdateRequest>) request.argument;
2427 onCompleted = obtainMessage(EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
2428 request);
Rambo Wang6568f172021-02-03 16:56:47 -08002429 phone.getSignalStrengthController().setSignalStrengthUpdateRequest(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002430 request.subId, pair.first /*callingUid*/,
2431 pair.second /*request*/, onCompleted);
Rambo Wanga5cc9b72021-01-07 10:51:54 -08002432 break;
2433 }
2434 case EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
2435 ar = (AsyncResult) msg.obj;
2436 request = (MainThreadRequest) ar.userObj;
2437 // request.result will be the exception of ar if present, true otherwise.
2438 // Be cautious not to leave result null which will wait() forever
2439 request.result = ar.exception != null ? ar.exception : true;
2440 notifyRequester(request);
2441 break;
2442 }
2443 case CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST: {
2444 request = (MainThreadRequest) msg.obj;
2445
2446 Phone phone = getPhoneFromRequest(request);
2447 if (phone == null || phone.getServiceStateTracker() == null) {
2448 request.result = new IllegalStateException("Phone or SST is null");
2449 notifyRequester(request);
2450 break;
2451 }
2452
2453 Pair<Integer, SignalStrengthUpdateRequest> pair =
2454 (Pair<Integer, SignalStrengthUpdateRequest>) request.argument;
2455 onCompleted = obtainMessage(EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
2456 request);
Rambo Wang6568f172021-02-03 16:56:47 -08002457 phone.getSignalStrengthController().clearSignalStrengthUpdateRequest(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002458 request.subId, pair.first /*callingUid*/,
2459 pair.second /*request*/, onCompleted);
Rambo Wanga5cc9b72021-01-07 10:51:54 -08002460 break;
2461 }
2462 case EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
2463 ar = (AsyncResult) msg.obj;
2464 request = (MainThreadRequest) ar.userObj;
2465 request.result = ar.exception != null ? ar.exception : true;
2466 notifyRequester(request);
2467 break;
2468 }
Jordan Liu109698e2020-11-24 14:50:34 -08002469
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002470 case CMD_GET_SLICING_CONFIG: {
2471 request = (MainThreadRequest) msg.obj;
2472 onCompleted = obtainMessage(EVENT_GET_SLICING_CONFIG_DONE, request);
2473 request.phone.getSlicingConfig(onCompleted);
2474 break;
2475 }
2476 case EVENT_GET_SLICING_CONFIG_DONE: {
2477 ar = (AsyncResult) msg.obj;
2478 request = (MainThreadRequest) ar.userObj;
2479 ResultReceiver result = (ResultReceiver) request.argument;
2480
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002481 NetworkSlicingConfig slicingConfig = null;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002482 Bundle bundle = new Bundle();
2483 int resultCode = 0;
2484 if (ar.exception != null) {
2485 Log.e(LOG_TAG, "Exception retrieving slicing configuration="
2486 + ar.exception);
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002487 resultCode = TelephonyManager.NetworkSlicingException.ERROR_MODEM_ERROR;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002488 } else if (ar.result == null) {
2489 Log.w(LOG_TAG, "Timeout Waiting for slicing configuration!");
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002490 resultCode = TelephonyManager.NetworkSlicingException.ERROR_TIMEOUT;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002491 } else {
2492 // use the result as returned
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002493 resultCode = TelephonyManager.NetworkSlicingException.SUCCESS;
2494 slicingConfig = (NetworkSlicingConfig) ar.result;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002495 }
2496
2497 if (slicingConfig == null) {
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002498 slicingConfig = new NetworkSlicingConfig();
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002499 }
2500 bundle.putParcelable(TelephonyManager.KEY_SLICING_CONFIG_HANDLE, slicingConfig);
2501 result.send(resultCode, bundle);
2502 notifyRequester(request);
2503 break;
2504 }
2505
Sarah Chin71b3a852022-09-28 15:54:19 -07002506 case CMD_PURCHASE_PREMIUM_CAPABILITY: {
Sarah Chin2ec39f62022-08-31 17:03:26 -07002507 request = (MainThreadRequest) msg.obj;
2508 onCompleted = obtainMessage(EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE, request);
Sarah Chin71b3a852022-09-28 15:54:19 -07002509 PurchasePremiumCapabilityArgument arg =
2510 (PurchasePremiumCapabilityArgument) request.argument;
Sarah Chin46355ba2022-11-01 23:51:16 -07002511 SlicePurchaseController.getInstance(request.phone).purchasePremiumCapability(
Sarah Chinb8218c22023-01-04 13:35:29 -08002512 arg.capability, onCompleted);
Sarah Chin2ec39f62022-08-31 17:03:26 -07002513 break;
Sarah Chin71b3a852022-09-28 15:54:19 -07002514 }
Sarah Chin2ec39f62022-08-31 17:03:26 -07002515
Sarah Chin71b3a852022-09-28 15:54:19 -07002516 case EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE: {
Sarah Chin2ec39f62022-08-31 17:03:26 -07002517 ar = (AsyncResult) msg.obj;
2518 request = (MainThreadRequest) ar.userObj;
Sarah Chin71b3a852022-09-28 15:54:19 -07002519 PurchasePremiumCapabilityArgument arg =
2520 (PurchasePremiumCapabilityArgument) request.argument;
Sarah Chin2ec39f62022-08-31 17:03:26 -07002521 try {
2522 int result = (int) ar.result;
Sarah Chin71b3a852022-09-28 15:54:19 -07002523 arg.callback.accept(result);
Sarah Chin2ec39f62022-08-31 17:03:26 -07002524 log("purchasePremiumCapability: capability="
Sarah Chin71b3a852022-09-28 15:54:19 -07002525 + TelephonyManager.convertPremiumCapabilityToString(arg.capability)
Sarah Chin2ec39f62022-08-31 17:03:26 -07002526 + ", result= "
2527 + TelephonyManager.convertPurchaseResultToString(result));
2528 } catch (RemoteException e) {
2529 String logStr = "Purchase premium capability "
Sarah Chin71b3a852022-09-28 15:54:19 -07002530 + TelephonyManager.convertPremiumCapabilityToString(arg.capability)
Sarah Chin2ec39f62022-08-31 17:03:26 -07002531 + " failed: " + e;
2532 if (DBG) log(logStr);
2533 AnomalyReporter.reportAnomaly(
2534 UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
2535 }
2536 break;
Sarah Chin71b3a852022-09-28 15:54:19 -07002537 }
Sarah Chin2ec39f62022-08-31 17:03:26 -07002538
Michele Berionne5e411512020-11-13 02:36:59 +00002539 case CMD_PREPARE_UNATTENDED_REBOOT:
2540 request = (MainThreadRequest) msg.obj;
2541 request.result =
Rafael Higuera Silvad9630642021-09-20 15:32:01 +00002542 UiccController.getInstance().getPinStorage()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002543 .prepareUnattendedReboot(request.workSource);
Michele Berionne5e411512020-11-13 02:36:59 +00002544 notifyRequester(request);
2545 break;
2546
Sarah Chineccfbd12023-01-20 19:00:35 -08002547 case CMD_START_SATELLITE_POSITION_UPDATES: {
2548 request = (MainThreadRequest) msg.obj;
2549 onCompleted =
2550 obtainMessage(EVENT_START_SATELLITE_POSITION_UPDATES_DONE, request);
2551 Phone phone = getPhoneFromRequest(request);
2552 if (phone != null) {
2553 phone.startSatellitePositionUpdates(onCompleted);
2554 } else {
2555 loge("startSatellitePositionUpdates: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002556 ((Consumer<Integer>) request.argument).accept(
2557 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Sarah Chineccfbd12023-01-20 19:00:35 -08002558 }
2559 break;
2560 }
2561
2562 case EVENT_START_SATELLITE_POSITION_UPDATES_DONE: {
2563 ar = (AsyncResult) msg.obj;
2564 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002565 int error = getSatelliteError(ar, "startSatellitePositionUpdates", false);
2566 ((Consumer<Integer>) request.argument).accept(error);
Sarah Chineccfbd12023-01-20 19:00:35 -08002567 break;
2568 }
2569
2570 case CMD_STOP_SATELLITE_POSITION_UPDATES: {
2571 request = (MainThreadRequest) msg.obj;
2572 onCompleted =
2573 obtainMessage(EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE, request);
2574 Phone phone = getPhoneFromRequest(request);
2575 if (phone != null) {
2576 phone.stopSatellitePositionUpdates(onCompleted);
2577 } else {
2578 loge("stopSatellitePositionUpdates: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002579 ((Consumer<Integer>) request.argument).accept(
2580 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Sarah Chineccfbd12023-01-20 19:00:35 -08002581 }
2582 break;
2583 }
2584
2585 case EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE: {
2586 ar = (AsyncResult) msg.obj;
2587 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002588 int error = getSatelliteError(ar, "stopSatellitePositionUpdates", false);
2589 ((Consumer<Integer>) request.argument).accept(error);
Sarah Chineccfbd12023-01-20 19:00:35 -08002590 break;
2591 }
2592
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002593 case CMD_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG: {
2594 request = (MainThreadRequest) msg.obj;
2595 onCompleted = obtainMessage(EVENT_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG_DONE,
2596 request);
2597 Phone phone = getPhoneFromRequest(request);
2598 if (phone != null) {
2599 phone.getMaxCharactersPerSatelliteTextMessage(onCompleted);
2600 } else {
2601 loge("getMaxCharactersPerSatelliteTextMessage: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002602 ((ResultReceiver) request.argument).send(
2603 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002604 }
2605 break;
2606 }
2607
2608 case EVENT_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG_DONE: {
2609 ar = (AsyncResult) msg.obj;
2610 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002611 int error =
2612 getSatelliteError(ar, "getMaxCharactersPerSatelliteTextMessage", true);
2613 Bundle bundle = new Bundle();
2614 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002615 int maxCharLimit = ((int[]) ar.result)[0];
Sarah Chin503828c2023-02-01 23:54:20 -08002616 if (DBG) log("getMaxCharactersPerSatelliteTextMessage: " + maxCharLimit);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002617 bundle.putInt(SatelliteManager.KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT,
2618 maxCharLimit);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002619 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002620 ((ResultReceiver) request.argument).send(error, bundle);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002621 break;
2622 }
2623
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002624 case CMD_PROVISION_SATELLITE_SERVICE: {
2625 request = (MainThreadRequest) msg.obj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002626 onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_SERVICE_DONE, request);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002627 Phone phone = getPhoneFromRequest(request);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002628 ProvisionSatelliteServiceArgument argument =
2629 (ProvisionSatelliteServiceArgument) request.argument;
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002630 if (phone != null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002631 handleCmdProvisionSatelliteService(argument, phone, onCompleted);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002632 } else {
2633 loge("provisionSatelliteService: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002634 argument.callback.accept(
2635 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002636 notifyRequester(request);
2637 }
2638 break;
2639 }
2640
2641 case EVENT_PROVISION_SATELLITE_SERVICE_DONE: {
2642 ar = (AsyncResult) msg.obj;
2643 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002644 int errorCode = getSatelliteError(ar, "provisionSatelliteService", false);
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002645 handleEventProvisionSatelliteServiceDone(
2646 (ProvisionSatelliteServiceArgument) request.argument, errorCode);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002647 notifyRequester(request);
2648 break;
2649 }
2650
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002651 case CMD_DEPROVISION_SATELLITE_SERVICE: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002652 request = (MainThreadRequest) msg.obj;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002653 onCompleted = obtainMessage(EVENT_DEPROVISION_SATELLITE_SERVICE_DONE, request);
2654 Phone phone = getPhoneFromRequest(request);
2655 ProvisionSatelliteServiceArgument argument =
2656 (ProvisionSatelliteServiceArgument) request.argument;
2657 if (phone != null) {
2658 handleCmdDeprovisionSatelliteService(argument, phone, onCompleted);
2659 } else {
2660 loge("deprovisionSatelliteService: No phone object");
2661 if (argument.callback != null) {
2662 argument.callback.accept(
2663 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
2664 }
2665 notifyRequester(request);
2666 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002667 break;
2668 }
2669
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002670 case EVENT_DEPROVISION_SATELLITE_SERVICE_DONE: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002671 ar = (AsyncResult) msg.obj;
2672 request = (MainThreadRequest) ar.userObj;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002673 int errorCode = getSatelliteError(ar, "deprovisionSatelliteService", false);
2674 handleEventDeprovisionSatelliteServiceDone(
2675 (ProvisionSatelliteServiceArgument) request.argument, errorCode);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002676 notifyRequester(request);
2677 break;
2678 }
2679
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002680 case CMD_SET_SATELLITE_ENABLED: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002681 request = (MainThreadRequest) msg.obj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002682 onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request);
2683 Pair<Boolean, Consumer<Integer>> argument =
2684 (Pair<Boolean, Consumer<Integer>>) request.argument;
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002685 Phone phone = getPhoneFromRequest(request);
2686 if (phone != null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002687 boolean enable = argument.first.booleanValue();
2688 phone.setSatellitePower(onCompleted, enable);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002689 } else {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002690 loge("setSatelliteEnabled: No phone object");
2691 argument.second.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002692 notifyRequester(request);
2693 }
2694 break;
2695 }
2696
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002697 case EVENT_SET_SATELLITE_ENABLED_DONE: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002698 ar = (AsyncResult) msg.obj;
2699 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002700 Pair<Boolean, Consumer<Integer>> argument =
2701 (Pair<Boolean, Consumer<Integer>>) request.argument;
2702 int error = getSatelliteError(ar, "setSatelliteEnabled", false);
2703 argument.second.accept(error);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002704 break;
2705 }
2706
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002707 case CMD_IS_SATELLITE_ENABLED: {
Sarah Chin503828c2023-02-01 23:54:20 -08002708 request = (MainThreadRequest) msg.obj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002709 onCompleted = obtainMessage(EVENT_IS_SATELLITE_ENABLED_DONE, request);
Sarah Chin503828c2023-02-01 23:54:20 -08002710 Phone phone = getPhoneFromRequest(request);
2711 if (phone != null) {
2712 phone.isSatellitePowerOn(onCompleted);
2713 } else {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002714 loge("isSatelliteEnabled: No phone object");
2715 ((ResultReceiver) request.argument).send(
2716 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Sarah Chin503828c2023-02-01 23:54:20 -08002717 }
2718 break;
2719 }
2720
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002721 case EVENT_IS_SATELLITE_ENABLED_DONE: {
Sarah Chin503828c2023-02-01 23:54:20 -08002722 ar = (AsyncResult) msg.obj;
2723 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002724 int error = getSatelliteError(ar, "isSatelliteEnabled", true);
2725 Bundle bundle = new Bundle();
2726 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2727 boolean enabled = ((int[]) ar.result)[0] == 1;
2728 if (DBG) log("isSatelliteEnabled: " + enabled);
2729 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled);
Sarah Chin503828c2023-02-01 23:54:20 -08002730 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002731 ((ResultReceiver) request.argument).send(error, bundle);
Sarah Chin503828c2023-02-01 23:54:20 -08002732 break;
2733 }
2734
2735 case CMD_IS_SATELLITE_SUPPORTED: {
2736 request = (MainThreadRequest) msg.obj;
2737 onCompleted = obtainMessage(EVENT_IS_SATELLITE_SUPPORTED_DONE, request);
2738 Phone phone = getPhoneFromRequest(request);
2739 if (phone != null) {
2740 phone.isSatelliteSupported(onCompleted);
2741 } else {
2742 loge("isSatelliteSupported: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002743 ((ResultReceiver) request.argument).send(
2744 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Sarah Chin503828c2023-02-01 23:54:20 -08002745 }
2746 break;
2747 }
2748
2749 case EVENT_IS_SATELLITE_SUPPORTED_DONE: {
2750 ar = (AsyncResult) msg.obj;
2751 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002752 int error = getSatelliteError(ar, "isSatelliteSupported", true);
2753 Bundle bundle = new Bundle();
2754 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2755 boolean supported = ((int[]) ar.result)[0] == 1;
2756 if (DBG) log("isSatelliteSupported: " + supported);
2757 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported);
Thomas Nguyene77de6d2023-02-10 17:42:43 -08002758 synchronized (mIsSatelliteSupportedLock) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002759 mIsSatelliteSupported = supported;
2760 }
2761 } else {
2762 synchronized (mIsSatelliteSupportedLock) {
2763 mIsSatelliteSupported = null;
Thomas Nguyene77de6d2023-02-10 17:42:43 -08002764 }
Sarah Chin503828c2023-02-01 23:54:20 -08002765 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002766 ((ResultReceiver) request.argument).send(error, bundle);
Sarah Chin503828c2023-02-01 23:54:20 -08002767 break;
2768 }
2769
2770 case CMD_GET_SATELLITE_CAPABILITIES: {
2771 request = (MainThreadRequest) msg.obj;
2772 onCompleted = obtainMessage(EVENT_GET_SATELLITE_CAPABILITIES_DONE, request);
2773 Phone phone = getPhoneFromRequest(request);
2774 if (phone != null) {
2775 phone.getSatelliteCapabilities(onCompleted);
2776 } else {
2777 loge("getSatelliteCapabilities: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002778 ((ResultReceiver) request.argument).send(
2779 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Sarah Chin503828c2023-02-01 23:54:20 -08002780 }
2781 break;
2782 }
2783
2784 case EVENT_GET_SATELLITE_CAPABILITIES_DONE: {
2785 ar = (AsyncResult) msg.obj;
2786 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002787 int error = getSatelliteError(ar, "getSatelliteCapabilities", true);
2788 Bundle bundle = new Bundle();
2789 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
Sarah Chin503828c2023-02-01 23:54:20 -08002790 SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result;
2791 if (DBG) log("getSatelliteCapabilities: " + capabilities);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002792 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
2793 capabilities);
Sarah Chin503828c2023-02-01 23:54:20 -08002794 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002795 ((ResultReceiver) request.argument).send(error, bundle);
Sarah Chin503828c2023-02-01 23:54:20 -08002796 break;
2797 }
2798
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +00002799 case CMD_POLL_PENDING_SATELLITE_DATAGRAMS: {
2800 request = (MainThreadRequest) msg.obj;
2801 onCompleted = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE,
2802 request);
2803 Phone phone = getPhoneFromRequest(request);
2804 if (phone != null) {
2805 phone.pollPendingSatelliteDatagrams(onCompleted);
2806 } else {
2807 loge("pollPendingSatelliteDatagrams: No phone object");
Aishwarya Mallampati224317a2023-02-13 22:09:30 +00002808 ((Consumer<Integer>) request.argument)
2809 .accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +00002810 }
2811 break;
2812 }
2813
2814 case EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE: {
2815 ar = (AsyncResult) msg.obj;
2816 request = (MainThreadRequest) ar.userObj;
Aishwarya Mallampati224317a2023-02-13 22:09:30 +00002817 int error = getSatelliteError(ar, "pollPendingSatelliteDatagrams", false);
2818 ((Consumer<Integer>) request.argument).accept(error);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +00002819 break;
2820 }
2821
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +00002822 case CMD_SEND_SATELLITE_DATAGRAM: {
2823 request = (MainThreadRequest) msg.obj;
2824 onCompleted =
2825 obtainMessage(EVENT_SEND_SATELLITE_DATAGRAM_DONE, request);
2826 Phone phone = getPhoneFromRequest(request);
2827 SendSatelliteDatagramArgument argument =
2828 (SendSatelliteDatagramArgument) request.argument;
2829 if (phone != null) {
2830 phone.sendSatelliteDatagram(onCompleted, argument.datagram);
2831 } else {
2832 loge("sendSatelliteDatagram: No phone object");
2833 argument.callback
2834 .accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
2835 }
2836 break;
2837 }
2838
2839 case EVENT_SEND_SATELLITE_DATAGRAM_DONE: {
2840 ar = (AsyncResult) msg.obj;
2841 request = (MainThreadRequest) ar.userObj;
2842 int error = getSatelliteError(ar, "sendSatelliteDatagram",
2843 false);
2844 SendSatelliteDatagramArgument argument =
2845 (SendSatelliteDatagramArgument) request.argument;
2846 argument.callback.accept(error);
2847 break;
2848 }
2849
Sarah Chindf715ec2023-02-13 13:46:24 -08002850 case CMD_IS_SATELLITE_COMMUNICATION_ALLOWED: {
2851 request = (MainThreadRequest) msg.obj;
2852 onCompleted = obtainMessage(EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE,
2853 request);
2854 Phone phone = getPhoneFromRequest(request);
2855 if (phone != null) {
2856 phone.isSatelliteCommunicationAllowedForCurrentLocation(onCompleted);
2857 } else {
2858 loge("isSatelliteCommunicationAllowedForCurrentLocation: No phone object");
2859 ((ResultReceiver) request.argument).send(
2860 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
2861 }
2862 break;
2863 }
2864
2865 case EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE: {
2866 ar = (AsyncResult) msg.obj;
2867 request = (MainThreadRequest) ar.userObj;
2868 int error = getSatelliteError(
2869 ar, "isSatelliteCommunicationAllowedForCurrentLocation", true);
2870 Bundle bundle = new Bundle();
2871 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2872 boolean communicationAllowed = ((int[]) ar.result)[0] == 1;
2873 if (DBG) {
2874 log("isSatelliteCommunicationAllowedForCurrentLocation: "
2875 + communicationAllowed);
2876 }
2877 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED,
2878 communicationAllowed);
2879 }
2880 ((ResultReceiver) request.argument).send(error, bundle);
2881 break;
2882 }
2883
2884 case CMD_GET_TIME_SATELLITE_NEXT_VISIBLE: {
2885 request = (MainThreadRequest) msg.obj;
2886 onCompleted = obtainMessage(EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE,
2887 request);
2888 Phone phone = getPhoneFromRequest(request);
2889 if (phone != null) {
2890 phone.requestTimeForNextSatelliteVisibility(onCompleted);
2891 } else {
2892 loge("requestTimeForNextSatelliteVisibility: No phone object");
2893 ((ResultReceiver) request.argument).send(
2894 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
2895 }
2896 break;
2897 }
2898
2899 case EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE: {
2900 ar = (AsyncResult) msg.obj;
2901 request = (MainThreadRequest) ar.userObj;
2902 int error =
2903 getSatelliteError(ar, "requestTimeForNextSatelliteVisibility", true);
2904 Bundle bundle = new Bundle();
2905 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2906 int nextVisibilityDuration = ((int[]) ar.result)[0];
2907 if (DBG) {
2908 log("requestTimeForNextSatelliteVisibility: " + nextVisibilityDuration);
2909 }
2910 bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY,
2911 nextVisibilityDuration);
2912 }
2913 ((ResultReceiver) request.argument).send(error, bundle);
2914 break;
2915 }
2916
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002917 default:
2918 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
2919 break;
2920 }
2921 }
Jake Hambye994d462014-02-03 13:10:13 -08002922
Pengquan Menga1bb6272018-09-06 09:59:22 -07002923 private void notifyRequester(MainThreadRequest request) {
2924 synchronized (request) {
2925 request.notifyAll();
2926 }
2927 }
2928
Jake Hambye994d462014-02-03 13:10:13 -08002929 private void handleNullReturnEvent(Message msg, String command) {
2930 AsyncResult ar = (AsyncResult) msg.obj;
2931 MainThreadRequest request = (MainThreadRequest) ar.userObj;
2932 if (ar.exception == null) {
2933 request.result = true;
2934 } else {
2935 request.result = false;
2936 if (ar.exception instanceof CommandException) {
2937 loge(command + ": CommandException: " + ar.exception);
2938 } else {
2939 loge(command + ": Unknown exception");
2940 }
2941 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07002942 notifyRequester(request);
Jake Hambye994d462014-02-03 13:10:13 -08002943 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002944 }
2945
2946 /**
2947 * Posts the specified command to be executed on the main thread,
2948 * waits for the request to complete, and returns the result.
2949 * @see #sendRequestAsync
2950 */
2951 private Object sendRequest(int command, Object argument) {
Rambo Wang0f050d82021-02-12 11:43:36 -08002952 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, null,
2953 null, -1 /*timeoutInMs*/);
vagdeviaf9a5b92018-08-15 16:01:53 -07002954 }
2955
2956 /**
2957 * Posts the specified command to be executed on the main thread,
2958 * waits for the request to complete, and returns the result.
2959 * @see #sendRequestAsync
2960 */
2961 private Object sendRequest(int command, Object argument, WorkSource workSource) {
2962 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
Rambo Wang0f050d82021-02-12 11:43:36 -08002963 null, workSource, -1 /*timeoutInMs*/);
Wink Saville36469e72014-06-11 15:17:00 -07002964 }
2965
2966 /**
2967 * Posts the specified command to be executed on the main thread,
2968 * waits for the request to complete, and returns the result.
2969 * @see #sendRequestAsync
2970 */
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002971 private Object sendRequest(int command, Object argument, Integer subId) {
Rambo Wang0f050d82021-02-12 11:43:36 -08002972 return sendRequest(command, argument, subId, null, null, -1 /*timeoutInMs*/);
2973 }
2974
2975 /**
2976 * Posts the specified command to be executed on the main thread,
2977 * waits for the request to complete for at most {@code timeoutInMs}, and returns the result
2978 * if not timeout or null otherwise.
2979 * @see #sendRequestAsync
2980 */
2981 private @Nullable Object sendRequest(int command, Object argument, Integer subId,
2982 long timeoutInMs) {
2983 return sendRequest(command, argument, subId, null, null, timeoutInMs);
vagdeviaf9a5b92018-08-15 16:01:53 -07002984 }
2985
2986 /**
2987 * Posts the specified command to be executed on the main thread,
2988 * waits for the request to complete, and returns the result.
2989 * @see #sendRequestAsync
2990 */
Nathan Harold92bed182018-10-12 18:16:49 -07002991 private Object sendRequest(int command, Object argument, int subId, WorkSource workSource) {
Rambo Wang0f050d82021-02-12 11:43:36 -08002992 return sendRequest(command, argument, subId, null, workSource, -1 /*timeoutInMs*/);
Nathan Harold92bed182018-10-12 18:16:49 -07002993 }
2994
2995 /**
2996 * Posts the specified command to be executed on the main thread,
2997 * waits for the request to complete, and returns the result.
2998 * @see #sendRequestAsync
2999 */
3000 private Object sendRequest(int command, Object argument, Phone phone, WorkSource workSource) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003001 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phone,
3002 workSource, -1 /*timeoutInMs*/);
Nathan Harold92bed182018-10-12 18:16:49 -07003003 }
3004
3005 /**
Rambo Wang0f050d82021-02-12 11:43:36 -08003006 * Posts the specified command to be executed on the main thread. If {@code timeoutInMs} is
3007 * negative, waits for the request to complete, and returns the result. Otherwise, wait for
3008 * maximum of {@code timeoutInMs} milliseconds, interrupt and return null.
Nathan Harold92bed182018-10-12 18:16:49 -07003009 * @see #sendRequestAsync
3010 */
Rambo Wang0f050d82021-02-12 11:43:36 -08003011 private @Nullable Object sendRequest(int command, Object argument, Integer subId, Phone phone,
3012 WorkSource workSource, long timeoutInMs) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003013 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
3014 throw new RuntimeException("This method will deadlock if called from the main thread.");
3015 }
3016
Nathan Harold92bed182018-10-12 18:16:49 -07003017 MainThreadRequest request = null;
3018 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && phone != null) {
3019 throw new IllegalArgumentException("subId and phone cannot both be specified!");
3020 } else if (phone != null) {
3021 request = new MainThreadRequest(argument, phone, workSource);
3022 } else {
3023 request = new MainThreadRequest(argument, subId, workSource);
3024 }
3025
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003026 Message msg = mMainThreadHandler.obtainMessage(command, request);
3027 msg.sendToTarget();
3028
Rambo Wang0f050d82021-02-12 11:43:36 -08003029
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003030 synchronized (request) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003031 if (timeoutInMs >= 0) {
3032 // Wait for at least timeoutInMs before returning null request result
3033 long now = SystemClock.elapsedRealtime();
3034 long deadline = now + timeoutInMs;
Grace Jia8a0a1e82021-05-23 22:59:52 -07003035 while (request.result == null && now < deadline) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003036 try {
3037 request.wait(deadline - now);
3038 } catch (InterruptedException e) {
3039 // Do nothing, go back and check if request is completed or timeout
3040 } finally {
3041 now = SystemClock.elapsedRealtime();
3042 }
3043 }
3044 } else {
3045 // Wait for the request to complete
3046 while (request.result == null) {
3047 try {
3048 request.wait();
3049 } catch (InterruptedException e) {
3050 // Do nothing, go back and wait until the request is complete
3051 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003052 }
3053 }
3054 }
Rambo Wang0f050d82021-02-12 11:43:36 -08003055 if (request.result == null) {
3056 Log.wtf(LOG_TAG,
3057 "sendRequest: Blocking command timed out. Something has gone terribly wrong.");
3058 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003059 return request.result;
3060 }
3061
3062 /**
3063 * Asynchronous ("fire and forget") version of sendRequest():
3064 * Posts the specified command to be executed on the main thread, and
3065 * returns immediately.
3066 * @see #sendRequest
3067 */
3068 private void sendRequestAsync(int command) {
3069 mMainThreadHandler.sendEmptyMessage(command);
3070 }
3071
3072 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07003073 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07003074 * @see {@link #sendRequest(int)}
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07003075 */
3076 private void sendRequestAsync(int command, Object argument) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07003077 sendRequestAsync(command, argument, null, null);
3078 }
3079
3080 /**
3081 * Same as {@link #sendRequestAsync(int,Object)} except it takes a Phone and WorkSource.
3082 * @see {@link #sendRequest(int,Object)}
3083 */
3084 private void sendRequestAsync(
3085 int command, Object argument, Phone phone, WorkSource workSource) {
3086 MainThreadRequest request = new MainThreadRequest(argument, phone, workSource);
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07003087 Message msg = mMainThreadHandler.obtainMessage(command, request);
3088 msg.sendToTarget();
3089 }
3090
3091 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003092 * Initialize the singleton PhoneInterfaceManager instance.
3093 * This is only done once, at startup, from PhoneApp.onCreate().
3094 */
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003095 /* package */ static PhoneInterfaceManager init(PhoneGlobals app) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003096 synchronized (PhoneInterfaceManager.class) {
3097 if (sInstance == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003098 sInstance = new PhoneInterfaceManager(app);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003099 } else {
3100 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
3101 }
3102 return sInstance;
3103 }
3104 }
3105
3106 /** Private constructor; @see init() */
Jordan Liu1979a042020-03-20 21:39:35 +00003107 private PhoneInterfaceManager(PhoneGlobals app) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003108 mApp = app;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003109 mCM = PhoneGlobals.getInstance().mCM;
Brad Ebingerd1947d82021-05-17 20:54:49 +00003110 mImsResolver = ImsResolver.getInstance();
Stuart Scott981d8582015-04-21 14:09:50 -07003111 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003112 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
Grace Jia0ddb3612021-04-22 13:35:26 -07003113 mPm = app.getSystemService(PackageManager.class);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003114 mMainThreadHandler = new MainThreadHandler();
Jack Yue37dd262022-12-16 11:53:37 -08003115 if (!PhoneFactory.isSubscriptionManagerServiceEnabled()) {
3116 mSubscriptionController = SubscriptionController.getInstance();
3117 } else {
3118 mSubscriptionController = null;
3119 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003120 mTelephonySharedPreferences =
3121 PreferenceManager.getDefaultSharedPreferences(mApp);
yinxub1bed742017-04-17 11:45:04 -07003122 mNetworkScanRequestTracker = new NetworkScanRequestTracker();
Malcolm Chen2c63d402018-08-14 16:00:53 -07003123 mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
Daniel Bright94f43662021-03-01 14:43:40 -08003124 mRadioInterfaceCapabilities = RadioInterfaceCapabilityController.getInstance();
Peter Wanga3cf4ac2020-01-27 09:39:46 +08003125 mNotifyUserActivity = new AtomicBoolean(false);
Tyler Gunn64144d92022-03-17 14:16:41 -07003126 PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003127 publish();
arunvoddud7401012022-12-15 16:08:12 +00003128 CarrierAllowListInfo.loadInstance(mApp);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08003129 mSatelliteSupportedReceiver = new ResultReceiver(mMainThreadHandler) {
3130 @Override
3131 protected void onReceiveResult(int resultCode, Bundle resultData) {
3132 if (resultCode == SatelliteManager.SATELLITE_ERROR_NONE
3133 && resultData.containsKey(SatelliteManager.KEY_SATELLITE_SUPPORTED)) {
3134 synchronized (mIsSatelliteSupportedLock) {
3135 mIsSatelliteSupported = resultData.getBoolean(
3136 SatelliteManager.KEY_SATELLITE_SUPPORTED);
3137 }
3138 } else {
3139 synchronized (mIsSatelliteSupportedLock) {
3140 mIsSatelliteSupported = null;
3141 }
3142 }
3143 }
3144 };
3145 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
3146 mSatelliteSupportedReceiver);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003147 }
3148
Gil Cukierman1c0eb932022-12-06 22:28:24 +00003149 @VisibleForTesting
3150 public SharedPreferences getSharedPreferences() {
3151 return mTelephonySharedPreferences;
3152 }
3153
Gil Cukierman92cc7db2023-01-06 19:25:53 +00003154 /**
3155 * Get the default phone for this device.
3156 */
3157 @VisibleForTesting
3158 public Phone getDefaultPhone() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003159 Phone thePhone = getPhone(getDefaultSubscription());
3160 return (thePhone != null) ? thePhone : PhoneFactory.getDefaultPhone();
3161 }
3162
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003163 private void publish() {
3164 if (DBG) log("publish: " + this);
3165
Peter Wangc035ce42020-01-08 21:00:22 -08003166 TelephonyFrameworkInitializer
3167 .getTelephonyServiceManager()
3168 .getTelephonyServiceRegisterer()
3169 .register(this);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003170 }
3171
Stuart Scott584921c2015-01-15 17:10:34 -08003172 private Phone getPhoneFromRequest(MainThreadRequest request) {
Jordan Liu4c733742019-02-28 12:03:40 -08003173 if (request.phone != null) {
3174 return request.phone;
3175 } else {
3176 return getPhoneFromSubId(request.subId);
3177 }
3178 }
3179
3180 private Phone getPhoneFromSubId(int subId) {
3181 return (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
3182 ? getDefaultPhone() : getPhone(subId);
Stuart Scott584921c2015-01-15 17:10:34 -08003183 }
3184
Aishwarya Mallampati5e581e12023-01-17 21:57:06 +00003185 /**
3186 * Get phone object associated with a subscription.
3187 * Return default phone if phone object associated with subscription is null
3188 * @param subId - subscriptionId
3189 * @return phone object associated with a subscription or default phone if null.
3190 */
3191 private Phone getPhoneFromSubIdOrDefault(int subId) {
3192 Phone phone = getPhoneFromSubId(subId);
3193 if (phone == null) {
3194 phone = getDefaultPhone();
3195 }
3196 return phone;
3197 }
3198
Rambo Wange53e07d2022-05-10 13:01:13 -07003199 @Nullable
3200 private UiccPort getUiccPortFromRequest(@NonNull MainThreadRequest request) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003201 Phone phone = getPhoneFromRequest(request);
3202 return phone == null ? null :
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00003203 UiccController.getInstance().getUiccPort(phone.getPhoneId());
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003204 }
3205
Wink Saville36469e72014-06-11 15:17:00 -07003206 // returns phone associated with the subId.
Wink Savilleb564aae2014-10-23 10:18:09 -07003207 private Phone getPhone(int subId) {
Jack Yu285100e2022-12-02 22:48:35 -08003208 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -07003209 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003210
Kai Shif70f46f2021-03-03 13:59:46 -08003211 private void sendEraseModemConfig(@NonNull Phone phone) {
3212 Boolean success = (Boolean) sendRequest(CMD_ERASE_MODEM_CONFIG, null);
3213 if (DBG) log("eraseModemConfig:" + ' ' + (success ? "ok" : "fail"));
3214 }
3215
3216 private void sendEraseDataInSharedPreferences(@NonNull Phone phone) {
3217 Boolean success = (Boolean) sendRequest(CMD_ERASE_DATA_SHARED_PREFERENCES, null);
3218 if (DBG) log("eraseDataInSharedPreferences:" + ' ' + (success ? "ok" : "fail"));
Naina Nallurid63128d2019-09-17 14:10:30 -07003219 }
3220
Peter Wang44b186e2020-01-13 23:33:09 -08003221 private boolean isImsAvailableOnDevice() {
3222 PackageManager pm = getDefaultPhone().getContext().getPackageManager();
3223 if (pm == null) {
3224 // For some reason package manger is not available.. This will fail internally anyway,
3225 // so do not throw error and allow.
3226 return true;
3227 }
3228 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
3229 }
3230
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003231 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003232 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -07003233 }
3234
Wink Savilleb564aae2014-10-23 10:18:09 -07003235 public void dialForSubscriber(int subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003236 if (DBG) log("dial: " + number);
3237 // No permission check needed here: This is just a wrapper around the
3238 // ACTION_DIAL intent, which is available to any app since it puts up
3239 // the UI before it does anything.
3240
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003241 final long identity = Binder.clearCallingIdentity();
3242 try {
3243 String url = createTelUrl(number);
3244 if (url == null) {
3245 return;
3246 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003247
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003248 // PENDING: should we just silently fail if phone is offhook or ringing?
3249 PhoneConstants.State state = mCM.getState(subId);
3250 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
3251 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
3252 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3253 mApp.startActivity(intent);
3254 }
3255 } finally {
3256 Binder.restoreCallingIdentity(identity);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003257 }
3258 }
3259
3260 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003261 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -07003262 }
3263
Wink Savilleb564aae2014-10-23 10:18:09 -07003264 public void callForSubscriber(int subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003265 if (DBG) log("call: " + number);
3266
3267 // This is just a wrapper around the ACTION_CALL intent, but we still
3268 // need to do a permission check since we're calling startActivity()
3269 // from the context of the phone app.
3270 enforceCallPermission();
3271
Jordan Liu1617b712019-07-10 15:06:26 -07003272 if (mAppOps.noteOp(AppOpsManager.OPSTR_CALL_PHONE, Binder.getCallingUid(), callingPackage)
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003273 != AppOpsManager.MODE_ALLOWED) {
3274 return;
3275 }
3276
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003277 final long identity = Binder.clearCallingIdentity();
3278 try {
3279 String url = createTelUrl(number);
3280 if (url == null) {
3281 return;
3282 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003283
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003284 boolean isValid = false;
3285 final List<SubscriptionInfo> slist = getActiveSubscriptionInfoListPrivileged();
3286 if (slist != null) {
3287 for (SubscriptionInfo subInfoRecord : slist) {
3288 if (subInfoRecord.getSubscriptionId() == subId) {
3289 isValid = true;
3290 break;
3291 }
Wink Saville3ab207e2014-11-20 13:07:20 -08003292 }
Wink Saville08874612014-08-31 19:19:58 -07003293 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003294 if (!isValid) {
3295 return;
3296 }
Wink Saville08874612014-08-31 19:19:58 -07003297
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003298 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
3299 intent.putExtra(SUBSCRIPTION_KEY, subId);
3300 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3301 mApp.startActivity(intent);
3302 } finally {
3303 Binder.restoreCallingIdentity(identity);
3304 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003305 }
3306
Wink Savilleb564aae2014-10-23 10:18:09 -07003307 public boolean supplyPinForSubscriber(int subId, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003308 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07003309 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
3310 }
3311
Wink Savilleb564aae2014-10-23 10:18:09 -07003312 public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003313 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07003314 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
3315 }
3316
Wink Savilleb564aae2014-10-23 10:18:09 -07003317 public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003318 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003319
3320 final long identity = Binder.clearCallingIdentity();
3321 try {
Michele Berionne5e411512020-11-13 02:36:59 +00003322 Phone phone = getPhone(subId);
3323 final UnlockSim checkSimPin = new UnlockSim(phone.getPhoneId(), phone.getIccCard());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003324 checkSimPin.start();
3325 return checkSimPin.unlockSim(null, pin);
3326 } finally {
3327 Binder.restoreCallingIdentity(identity);
3328 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003329 }
3330
Wink Savilleb564aae2014-10-23 10:18:09 -07003331 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003332 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003333
3334 final long identity = Binder.clearCallingIdentity();
3335 try {
Michele Berionne5e411512020-11-13 02:36:59 +00003336 Phone phone = getPhone(subId);
3337 final UnlockSim checkSimPuk = new UnlockSim(phone.getPhoneId(), phone.getIccCard());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003338 checkSimPuk.start();
3339 return checkSimPuk.unlockSim(puk, pin);
3340 } finally {
3341 Binder.restoreCallingIdentity(identity);
3342 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003343 }
3344
3345 /**
Wink Saville9de0f752013-10-22 19:04:03 -07003346 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003347 * a synchronous one.
3348 */
3349 private static class UnlockSim extends Thread {
3350
3351 private final IccCard mSimCard;
Michele Berionne5e411512020-11-13 02:36:59 +00003352 private final int mPhoneId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003353
3354 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -07003355 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
3356 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003357
3358 // For replies from SimCard interface
3359 private Handler mHandler;
3360
3361 // For async handler to identify request type
3362 private static final int SUPPLY_PIN_COMPLETE = 100;
3363
Michele Berionne5e411512020-11-13 02:36:59 +00003364 UnlockSim(int phoneId, IccCard simCard) {
3365 mPhoneId = phoneId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003366 mSimCard = simCard;
3367 }
3368
3369 @Override
3370 public void run() {
3371 Looper.prepare();
3372 synchronized (UnlockSim.this) {
3373 mHandler = new Handler() {
3374 @Override
3375 public void handleMessage(Message msg) {
3376 AsyncResult ar = (AsyncResult) msg.obj;
3377 switch (msg.what) {
3378 case SUPPLY_PIN_COMPLETE:
3379 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
3380 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -07003381 mRetryCount = msg.arg1;
3382 if (ar.exception != null) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08003383 CommandException.Error error = null;
3384 if (ar.exception instanceof CommandException) {
3385 error = ((CommandException) (ar.exception))
3386 .getCommandError();
3387 }
3388 if (error == CommandException.Error.PASSWORD_INCORRECT) {
Wink Saville9de0f752013-10-22 19:04:03 -07003389 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
Thomas Nguyen8ee49682023-02-01 11:46:09 -08003390 } else if (error == CommandException.Error.ABORTED) {
3391 /* When UiccCardApp dispose, handle message and return
3392 exception */
vivi.lib5e9ada2019-09-12 16:04:24 +08003393 mResult = PhoneConstants.PIN_OPERATION_ABORTED;
Wink Saville9de0f752013-10-22 19:04:03 -07003394 } else {
3395 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
3396 }
3397 } else {
3398 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
3399 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003400 mDone = true;
3401 UnlockSim.this.notifyAll();
3402 }
3403 break;
3404 }
3405 }
3406 };
3407 UnlockSim.this.notifyAll();
3408 }
3409 Looper.loop();
3410 }
3411
3412 /*
3413 * Use PIN or PUK to unlock SIM card
3414 *
3415 * If PUK is null, unlock SIM card with PIN
3416 *
3417 * If PUK is not null, unlock SIM card with PUK and set PIN code
3418 */
Wink Saville9de0f752013-10-22 19:04:03 -07003419 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003420
3421 while (mHandler == null) {
3422 try {
3423 wait();
3424 } catch (InterruptedException e) {
3425 Thread.currentThread().interrupt();
3426 }
3427 }
3428 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
3429
3430 if (puk == null) {
3431 mSimCard.supplyPin(pin, callback);
3432 } else {
3433 mSimCard.supplyPuk(puk, pin, callback);
3434 }
3435
3436 while (!mDone) {
3437 try {
3438 Log.d(LOG_TAG, "wait for done");
3439 wait();
3440 } catch (InterruptedException e) {
3441 // Restore the interrupted status
3442 Thread.currentThread().interrupt();
3443 }
3444 }
3445 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07003446 int[] resultArray = new int[2];
3447 resultArray[0] = mResult;
3448 resultArray[1] = mRetryCount;
Michele Berionne5e411512020-11-13 02:36:59 +00003449
3450 if (mResult == PhoneConstants.PIN_RESULT_SUCCESS && pin.length() > 0) {
Jon Spivack9c3bc762021-10-06 20:53:09 +00003451 UiccController.getInstance().getPinStorage().storePin(pin, mPhoneId);
Michele Berionne5e411512020-11-13 02:36:59 +00003452 }
3453
Wink Saville9de0f752013-10-22 19:04:03 -07003454 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003455 }
3456 }
3457
Nathan Harold7c8d0f12020-05-28 20:40:31 -07003458 /**
3459 * This method has been removed due to privacy and stability concerns.
3460 */
3461 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003462 public void updateServiceLocation() {
Nathan Harold7c8d0f12020-05-28 20:40:31 -07003463 Log.e(LOG_TAG, "Call to unsupported method updateServiceLocation()");
3464 return;
Wink Saville36469e72014-06-11 15:17:00 -07003465 }
3466
Nathan Harold1f889d82020-06-04 17:05:26 -07003467 @Override
3468 public void updateServiceLocationWithPackageName(String callingPackage) {
3469 mApp.getSystemService(AppOpsManager.class)
3470 .checkPackage(Binder.getCallingUid(), callingPackage);
3471
Nathan Haroldf096d982020-11-18 17:18:06 -08003472 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Harold1f889d82020-06-04 17:05:26 -07003473 if (targetSdk > android.os.Build.VERSION_CODES.R) {
3474 // Callers targeting S have no business invoking this method.
3475 return;
3476 }
3477
3478 LocationAccessPolicy.LocationPermissionResult locationResult =
3479 LocationAccessPolicy.checkLocationPermission(mApp,
3480 new LocationAccessPolicy.LocationPermissionQuery.Builder()
3481 .setCallingPackage(callingPackage)
3482 .setCallingFeatureId(null)
3483 .setCallingPid(Binder.getCallingPid())
3484 .setCallingUid(Binder.getCallingUid())
3485 .setMethod("updateServiceLocation")
3486 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
3487 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
3488 .build());
3489 // Apps that lack location permission have no business calling this method;
3490 // however, because no permission was declared in the public API, denials must
3491 // all be "soft".
3492 switch (locationResult) {
3493 case DENIED_HARD: /* fall through */
3494 case DENIED_SOFT:
3495 return;
3496 }
3497
3498 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003499 final long identity = Binder.clearCallingIdentity();
3500 try {
Nathan Harold1f889d82020-06-04 17:05:26 -07003501 final Phone phone = getPhone(getDefaultSubscription());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003502 if (phone != null) {
Nathan Harold1f889d82020-06-04 17:05:26 -07003503 phone.updateServiceLocation(workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003504 }
3505 } finally {
3506 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003507 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003508 }
3509
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003510 @Deprecated
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003511 @Override
3512 public boolean isRadioOn(String callingPackage) {
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003513 return isRadioOnWithFeature(callingPackage, null);
3514 }
3515
3516
3517 @Override
3518 public boolean isRadioOnWithFeature(String callingPackage, String callingFeatureId) {
3519 return isRadioOnForSubscriberWithFeature(getDefaultSubscription(), callingPackage,
3520 callingFeatureId);
3521 }
3522
3523 @Deprecated
3524 @Override
3525 public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
3526 return isRadioOnForSubscriberWithFeature(subId, callingPackage, null);
Wink Saville36469e72014-06-11 15:17:00 -07003527 }
3528
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003529 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003530 public boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage,
3531 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003532 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003533 mApp, subId, callingPackage, callingFeatureId, "isRadioOnForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003534 return false;
3535 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003536
3537 final long identity = Binder.clearCallingIdentity();
3538 try {
3539 return isRadioOnForSubscriber(subId);
3540 } finally {
3541 Binder.restoreCallingIdentity(identity);
3542 }
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003543 }
3544
3545 private boolean isRadioOnForSubscriber(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003546 final long identity = Binder.clearCallingIdentity();
3547 try {
3548 final Phone phone = getPhone(subId);
3549 if (phone != null) {
3550 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
3551 } else {
3552 return false;
3553 }
3554 } finally {
3555 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003556 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003557 }
3558
3559 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003560 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003561 }
Wink Saville36469e72014-06-11 15:17:00 -07003562
Wink Savilleb564aae2014-10-23 10:18:09 -07003563 public void toggleRadioOnOffForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003564 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003565
3566 final long identity = Binder.clearCallingIdentity();
3567 try {
3568 final Phone phone = getPhone(subId);
3569 if (phone != null) {
3570 phone.setRadioPower(!isRadioOnForSubscriber(subId));
3571 }
3572 } finally {
3573 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003574 }
Wink Saville36469e72014-06-11 15:17:00 -07003575 }
3576
3577 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003578 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07003579 }
3580
Wink Savilleb564aae2014-10-23 10:18:09 -07003581 public boolean setRadioForSubscriber(int subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07003582 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003583
3584 final long identity = Binder.clearCallingIdentity();
3585 try {
3586 final Phone phone = getPhone(subId);
3587 if (phone == null) {
3588 return false;
3589 }
3590 if ((phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF) != turnOn) {
3591 toggleRadioOnOffForSubscriber(subId);
3592 }
3593 return true;
3594 } finally {
3595 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003596 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003597 }
Wink Saville36469e72014-06-11 15:17:00 -07003598
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003599 public boolean needMobileRadioShutdown() {
Shuo Qianfa7b6b32019-12-10 10:40:38 -08003600 enforceReadPrivilegedPermission("needMobileRadioShutdown");
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003601 /*
3602 * If any of the Radios are available, it will need to be
3603 * shutdown. So return true if any Radio is available.
3604 */
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003605 final long identity = Binder.clearCallingIdentity();
3606 try {
3607 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
3608 Phone phone = PhoneFactory.getPhone(i);
3609 if (phone != null && phone.isRadioAvailable()) return true;
3610 }
3611 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
3612 return false;
3613 } finally {
3614 Binder.restoreCallingIdentity(identity);
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003615 }
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003616 }
3617
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003618 @Override
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003619 public void shutdownMobileRadios() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003620 enforceModifyPermission();
3621
3622 final long identity = Binder.clearCallingIdentity();
3623 try {
3624 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
3625 logv("Shutting down Phone " + i);
3626 shutdownRadioUsingPhoneId(i);
3627 }
3628 } finally {
3629 Binder.restoreCallingIdentity(identity);
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003630 }
3631 }
3632
3633 private void shutdownRadioUsingPhoneId(int phoneId) {
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003634 Phone phone = PhoneFactory.getPhone(phoneId);
3635 if (phone != null && phone.isRadioAvailable()) {
3636 phone.shutdownRadio();
3637 }
3638 }
3639
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003640 public boolean setRadioPower(boolean turnOn) {
Jack Yub4e16162017-05-15 12:48:40 -07003641 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003642
Ling Ma83dc5ea2023-01-12 15:06:04 -08003643 if (!turnOn) {
3644 log("setRadioPower off: callingPackage=" + getCurrentPackageName());
3645 }
3646
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003647 final long identity = Binder.clearCallingIdentity();
3648 try {
3649 final Phone defaultPhone = PhoneFactory.getDefaultPhone();
3650 if (defaultPhone != null) {
3651 defaultPhone.setRadioPower(turnOn);
3652 return true;
3653 } else {
3654 loge("There's no default phone.");
3655 return false;
3656 }
3657 } finally {
3658 Binder.restoreCallingIdentity(identity);
Wei Liu9ae2a062016-08-08 11:09:34 -07003659 }
Wink Saville36469e72014-06-11 15:17:00 -07003660 }
3661
Wink Savilleb564aae2014-10-23 10:18:09 -07003662 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003663 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003664
Ling Ma83dc5ea2023-01-12 15:06:04 -08003665 if (!turnOn) {
3666 log("setRadioPowerForSubscriber off: subId=" + subId
3667 + ",callingPackage=" + getCurrentPackageName());
3668 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003669 final long identity = Binder.clearCallingIdentity();
3670 try {
3671 final Phone phone = getPhone(subId);
3672 if (phone != null) {
3673 phone.setRadioPower(turnOn);
3674 return true;
3675 } else {
3676 return false;
3677 }
3678 } finally {
3679 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003680 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003681 }
3682
Thomas Nguyenfd0572f2022-07-15 22:28:49 +00003683 /**
3684 * Vote on powering off the radio for a reason. The radio will be turned on only when there is
3685 * no reason to power it off. When any of the voters want to power it off, it will be turned
3686 * off. In case of emergency, the radio will be turned on even if there are some reasons for
3687 * powering it off, and these radio off votes will be cleared.
3688 * Multiple apps can vote for the same reason and the last vote will take effect. Each app is
3689 * responsible for its vote. A powering-off vote of a reason will be maintained until it is
3690 * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call
3691 * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make
3692 * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to
3693 * check its vote.
3694 *
3695 * @param subId The subscription ID.
3696 * @param reason The reason for powering off radio.
3697 * @return true on success and false on failure.
3698 */
3699 public boolean requestRadioPowerOffForReason(int subId,
3700 @TelephonyManager.RadioPowerReason int reason) {
3701 enforceModifyPermission();
3702
Ling Ma83dc5ea2023-01-12 15:06:04 -08003703 log("requestRadioPowerOffForReason: subId=" + subId
3704 + ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
Thomas Nguyenfd0572f2022-07-15 22:28:49 +00003705 final long identity = Binder.clearCallingIdentity();
3706 try {
3707 final Phone phone = getPhone(subId);
3708 if (phone != null) {
3709 phone.setRadioPowerForReason(false, reason);
3710 return true;
3711 } else {
3712 return false;
3713 }
3714 } finally {
3715 Binder.restoreCallingIdentity(identity);
3716 }
3717 }
3718
3719 /**
3720 * Remove the vote on powering off the radio for a reason, as requested by
3721 * {@link requestRadioPowerOffForReason}.
3722 *
3723 * @param subId The subscription ID.
3724 * @param reason The reason for powering off radio.
3725 * @return true on success and false on failure.
3726 */
3727 public boolean clearRadioPowerOffForReason(int subId,
3728 @TelephonyManager.RadioPowerReason int reason) {
3729 enforceModifyPermission();
3730
3731 final long identity = Binder.clearCallingIdentity();
3732 try {
3733 final Phone phone = getPhone(subId);
3734 if (phone != null) {
3735 phone.setRadioPowerForReason(true, reason);
3736 return true;
3737 } else {
3738 return false;
3739 }
3740 } finally {
3741 Binder.restoreCallingIdentity(identity);
3742 }
3743 }
3744
3745 /**
3746 * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}.
3747 *
3748 * @param subId The subscription ID.
3749 * @param callingPackage The package making the call.
3750 * @param callingFeatureId The feature in the package.
3751 * @return List of reasons for powering off radio.
3752 */
3753 public List getRadioPowerOffReasons(int subId, String callingPackage, String callingFeatureId) {
3754 enforceReadPrivilegedPermission("getRadioPowerOffReasons");
3755
3756 final long identity = Binder.clearCallingIdentity();
3757 List result = new ArrayList();
3758 try {
3759 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId,
3760 callingPackage, callingFeatureId, "getRadioPowerOffReasons")) {
3761 return result;
3762 }
3763
3764 final Phone phone = getPhone(subId);
3765 if (phone != null) {
3766 result.addAll(phone.getRadioPowerOffReasons());
3767 }
3768 } finally {
3769 Binder.restoreCallingIdentity(identity);
3770 }
3771 return result;
3772 }
3773
Wink Saville36469e72014-06-11 15:17:00 -07003774 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07003775 @Override
Sarah Chinecc78c42022-03-31 21:16:48 -07003776 public boolean enableDataConnectivity(String callingPackage) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003777 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003778
3779 final long identity = Binder.clearCallingIdentity();
3780 try {
Jack Yu285100e2022-12-02 22:48:35 -08003781 int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003782 final Phone phone = getPhone(subId);
3783 if (phone != null) {
Jack Yu7968c6d2022-07-31 00:43:21 -07003784 phone.getDataSettingsManager().setDataEnabled(
3785 TelephonyManager.DATA_ENABLED_REASON_USER, true, callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003786 return true;
3787 } else {
3788 return false;
3789 }
3790 } finally {
3791 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003792 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003793 }
3794
Wink Saville36469e72014-06-11 15:17:00 -07003795 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07003796 @Override
Sarah Chinecc78c42022-03-31 21:16:48 -07003797 public boolean disableDataConnectivity(String callingPackage) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003798 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003799
3800 final long identity = Binder.clearCallingIdentity();
3801 try {
Jack Yu285100e2022-12-02 22:48:35 -08003802 int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003803 final Phone phone = getPhone(subId);
3804 if (phone != null) {
Jack Yu7968c6d2022-07-31 00:43:21 -07003805 phone.getDataSettingsManager().setDataEnabled(
3806 TelephonyManager.DATA_ENABLED_REASON_USER, false, callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003807 return true;
3808 } else {
3809 return false;
3810 }
3811 } finally {
3812 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003813 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003814 }
3815
Sanket Padawe356d7632015-06-22 14:03:32 -07003816 @Override
Jack Yuacf8a132017-05-01 17:00:48 -07003817 public boolean isDataConnectivityPossible(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003818 final long identity = Binder.clearCallingIdentity();
3819 try {
3820 final Phone phone = getPhone(subId);
3821 if (phone != null) {
Jack Yu59824e12022-03-23 01:42:44 -07003822 return phone.isDataAllowed();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003823 } else {
3824 return false;
3825 }
3826 } finally {
3827 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003828 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003829 }
3830
3831 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003832 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07003833 }
3834
pkanwarae03a6b2016-11-06 20:37:09 -08003835 public void handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003836 enforceCallPermission();
3837
3838 final long identity = Binder.clearCallingIdentity();
3839 try {
3840 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3841 return;
3842 }
3843 Pair<String, ResultReceiver> ussdObject = new Pair(ussdRequest, wrappedCallback);
3844 sendRequest(CMD_HANDLE_USSD_REQUEST, ussdObject, subId);
3845 } finally {
3846 Binder.restoreCallingIdentity(identity);
3847 }
pkanwar32d516d2016-10-14 19:37:38 -07003848 };
3849
Wink Savilleb564aae2014-10-23 10:18:09 -07003850 public boolean handlePinMmiForSubscriber(int subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003851 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003852
3853 final long identity = Binder.clearCallingIdentity();
3854 try {
3855 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3856 return false;
3857 }
3858 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
3859 } finally {
3860 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003861 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003862 }
3863
Brad Ebinger4f6208e2021-03-23 21:04:45 +00003864 /**
3865 * @deprecated This method is deprecated and is only being kept due to an UnsupportedAppUsage
3866 * tag on getCallState Binder call.
3867 */
3868 @Deprecated
3869 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003870 public int getCallState() {
Brad Ebinger4f6208e2021-03-23 21:04:45 +00003871 if (CompatChanges.isChangeEnabled(
3872 TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION,
3873 Binder.getCallingUid())) {
3874 // Do not allow this API to be called on API version 31+, it should only be
3875 // called on old apps using this Binder call directly.
3876 throw new SecurityException("This method can only be used for applications "
3877 + "targeting API version 30 or less.");
3878 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003879 final long identity = Binder.clearCallingIdentity();
3880 try {
Brad Ebinger4f6208e2021-03-23 21:04:45 +00003881 Phone phone = getPhone(getDefaultSubscription());
3882 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
3883 PhoneConstantConversions.convertCallState(phone.getState());
3884 } finally {
3885 Binder.restoreCallingIdentity(identity);
3886 }
3887 }
3888
3889 @Override
3890 public int getCallStateForSubscription(int subId, String callingPackage, String featureId) {
3891 if (CompatChanges.isChangeEnabled(
3892 TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION,
3893 Binder.getCallingUid())) {
3894 // Check READ_PHONE_STATE for API version 31+
3895 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId, callingPackage,
3896 featureId, "getCallStateForSubscription")) {
3897 throw new SecurityException("getCallState requires READ_PHONE_STATE for apps "
3898 + "targeting API level 31+.");
3899 }
3900 }
3901 final long identity = Binder.clearCallingIdentity();
3902 try {
3903 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003904 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
3905 PhoneConstantConversions.convertCallState(phone.getState());
3906 } finally {
3907 Binder.restoreCallingIdentity(identity);
3908 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003909 }
3910
Sanket Padawe356d7632015-06-22 14:03:32 -07003911 @Override
Nathan Harolde037c472019-06-26 00:41:07 +00003912 public int getDataState() {
Jack Yu285100e2022-12-02 22:48:35 -08003913 return getDataStateForSubId(SubscriptionManager.getDefaultDataSubscriptionId());
Nathan Haroldc4689b12019-06-14 16:58:30 -07003914 }
3915
3916 @Override
3917 public int getDataStateForSubId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003918 final long identity = Binder.clearCallingIdentity();
3919 try {
Nathan Haroldc4689b12019-06-14 16:58:30 -07003920 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003921 if (phone != null) {
Jack Yu7968c6d2022-07-31 00:43:21 -07003922 return phone.getDataNetworkController().getInternetDataNetworkState();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003923 } else {
3924 return PhoneConstantConversions.convertDataState(
3925 PhoneConstants.DataState.DISCONNECTED);
3926 }
3927 } finally {
3928 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003929 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003930 }
3931
Sanket Padawe356d7632015-06-22 14:03:32 -07003932 @Override
Jack Yu0eda6842022-04-18 00:34:46 -07003933 public @DataActivityType int getDataActivity() {
Jack Yu285100e2022-12-02 22:48:35 -08003934 return getDataActivityForSubId(SubscriptionManager.getDefaultDataSubscriptionId());
Nathan Haroldc4689b12019-06-14 16:58:30 -07003935 }
3936
3937 @Override
Jack Yu0eda6842022-04-18 00:34:46 -07003938 public @DataActivityType int getDataActivityForSubId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003939 final long identity = Binder.clearCallingIdentity();
3940 try {
Nathan Haroldc4689b12019-06-14 16:58:30 -07003941 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003942 if (phone != null) {
Jack Yu0eda6842022-04-18 00:34:46 -07003943 return phone.getDataActivityState();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003944 } else {
3945 return TelephonyManager.DATA_ACTIVITY_NONE;
3946 }
3947 } finally {
3948 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003949 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003950 }
3951
3952 @Override
Meng Wanga10e89e2019-12-09 13:13:01 -08003953 public CellIdentity getCellLocation(String callingPackage, String callingFeatureId) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003954 mApp.getSystemService(AppOpsManager.class)
Hall Liu1aa510f2017-11-22 17:40:08 -08003955 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08003956
3957 LocationAccessPolicy.LocationPermissionResult locationResult =
3958 LocationAccessPolicy.checkLocationPermission(mApp,
3959 new LocationAccessPolicy.LocationPermissionQuery.Builder()
3960 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07003961 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08003962 .setCallingPid(Binder.getCallingPid())
3963 .setCallingUid(Binder.getCallingUid())
3964 .setMethod("getCellLocation")
Hall Liu773ba022020-01-24 18:07:12 -08003965 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08003966 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
3967 .build());
3968 switch (locationResult) {
3969 case DENIED_HARD:
3970 throw new SecurityException("Not allowed to access cell location");
3971 case DENIED_SOFT:
Meng Wanga10e89e2019-12-09 13:13:01 -08003972 return (getDefaultPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
3973 ? new CellIdentityCdma() : new CellIdentityGsm();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003974 }
3975
Narayan Kamathf04b5a12018-01-09 11:47:15 +00003976 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003977 final long identity = Binder.clearCallingIdentity();
3978 try {
3979 if (DBG_LOC) log("getCellLocation: is active user");
Jack Yu285100e2022-12-02 22:48:35 -08003980 int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Meng Wanga10e89e2019-12-09 13:13:01 -08003981 return (CellIdentity) sendRequest(CMD_GET_CELL_LOCATION, workSource, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003982 } finally {
3983 Binder.restoreCallingIdentity(identity);
3984 }
Svetoslav64fad262015-04-14 14:35:21 -07003985 }
3986
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003987 @Override
Jack Yueb1e7fe2020-02-22 19:38:58 -08003988 public String getNetworkCountryIsoForPhone(int phoneId) {
Jonathan Basseribf5362b2017-07-19 12:22:35 -07003989 // Reporting the correct network country is ambiguous when IWLAN could conflict with
3990 // registered cell info, so return a NULL country instead.
3991 final long identity = Binder.clearCallingIdentity();
3992 try {
Malcolm Chen3732c2b2018-07-18 20:15:24 -07003993 if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
3994 // Get default phone in this case.
3995 phoneId = SubscriptionManager.DEFAULT_PHONE_INDEX;
3996 }
Jack Yu285100e2022-12-02 22:48:35 -08003997 final int subId = SubscriptionManager.getSubscriptionId(phoneId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003998 Phone phone = PhoneFactory.getPhone(phoneId);
Nathan Harold532f51c2020-04-21 19:31:10 -07003999 if (phone == null) return "";
4000 ServiceStateTracker sst = phone.getServiceStateTracker();
4001 if (sst == null) return "";
4002 LocaleTracker lt = sst.getLocaleTracker();
4003 if (lt == null) return "";
Shuo Qian9418a922021-03-09 11:21:16 -08004004 return lt.getCurrentCountry();
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004005 } finally {
4006 Binder.restoreCallingIdentity(identity);
4007 }
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004008 }
4009
Nathan Harold7c8d0f12020-05-28 20:40:31 -07004010 /**
4011 * This method was removed due to potential issues caused by performing partial
4012 * updates of service state, and lack of a credible use case.
4013 *
4014 * This has the ability to break the telephony implementation by disabling notification of
4015 * changes in device connectivity. DO NOT USE THIS!
4016 */
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004017 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004018 public void enableLocationUpdates() {
4019 mApp.enforceCallingOrSelfPermission(
4020 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004021 }
4022
Nathan Harold7c8d0f12020-05-28 20:40:31 -07004023 /**
4024 * This method was removed due to potential issues caused by performing partial
4025 * updates of service state, and lack of a credible use case.
4026 *
4027 * This has the ability to break the telephony implementation by disabling notification of
4028 * changes in device connectivity. DO NOT USE THIS!
4029 */
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004030 @Override
4031 public void disableLocationUpdates() {
4032 mApp.enforceCallingOrSelfPermission(
4033 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004034 }
4035
4036 @Override
4037 @SuppressWarnings("unchecked")
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004038 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage,
4039 String callingFeatureId) {
Nathan Haroldb55f63b2021-07-27 11:27:38 -07004040 try {
4041 mApp.getSystemService(AppOpsManager.class)
4042 .checkPackage(Binder.getCallingUid(), callingPackage);
4043 } catch (SecurityException e) {
4044 EventLog.writeEvent(0x534e4554, "190619791", Binder.getCallingUid());
4045 throw e;
4046 }
4047
Nathan Haroldf096d982020-11-18 17:18:06 -08004048 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Harolddbea45a2018-08-30 14:35:07 -07004049 if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
4050 throw new SecurityException(
4051 "getNeighboringCellInfo() is unavailable to callers targeting Q+ SDK levels.");
4052 }
Nathan Haroldb4d55612018-07-20 13:13:08 -07004053
Jordan Liu1617b712019-07-10 15:06:26 -07004054 if (mAppOps.noteOp(AppOpsManager.OPSTR_NEIGHBORING_CELLS, Binder.getCallingUid(),
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004055 callingPackage) != AppOpsManager.MODE_ALLOWED) {
4056 return null;
4057 }
Svetoslav64fad262015-04-14 14:35:21 -07004058
Svetoslav Ganov4a9d4482017-06-20 19:53:35 -07004059 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004060
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004061 List<CellInfo> info = getAllCellInfo(callingPackage, callingFeatureId);
Nathan Haroldf180aac2018-06-01 18:43:55 -07004062 if (info == null) return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004063
Nathan Haroldf180aac2018-06-01 18:43:55 -07004064 List<NeighboringCellInfo> neighbors = new ArrayList<NeighboringCellInfo>();
4065 for (CellInfo ci : info) {
4066 if (ci instanceof CellInfoGsm) {
4067 neighbors.add(new NeighboringCellInfo((CellInfoGsm) ci));
4068 } else if (ci instanceof CellInfoWcdma) {
4069 neighbors.add(new NeighboringCellInfo((CellInfoWcdma) ci));
4070 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004071 }
Nathan Haroldf180aac2018-06-01 18:43:55 -07004072 return (neighbors.size()) > 0 ? neighbors : null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004073 }
4074
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004075 private List<CellInfo> getCachedCellInfo() {
4076 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
4077 for (Phone phone : PhoneFactory.getPhones()) {
4078 List<CellInfo> info = phone.getAllCellInfo();
4079 if (info != null) cellInfos.addAll(info);
4080 }
4081 return cellInfos;
4082 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004083
4084 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004085 public List<CellInfo> getAllCellInfo(String callingPackage, String callingFeatureId) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004086 mApp.getSystemService(AppOpsManager.class)
Hall Liu1aa510f2017-11-22 17:40:08 -08004087 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08004088
4089 LocationAccessPolicy.LocationPermissionResult locationResult =
4090 LocationAccessPolicy.checkLocationPermission(mApp,
4091 new LocationAccessPolicy.LocationPermissionQuery.Builder()
4092 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004093 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08004094 .setCallingPid(Binder.getCallingPid())
4095 .setCallingUid(Binder.getCallingUid())
4096 .setMethod("getAllCellInfo")
Nathan Harold5ae50b52019-02-20 15:46:36 -08004097 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08004098 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
4099 .build());
4100 switch (locationResult) {
4101 case DENIED_HARD:
4102 throw new SecurityException("Not allowed to access cell info");
4103 case DENIED_SOFT:
4104 return new ArrayList<>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004105 }
4106
Nathan Haroldf096d982020-11-18 17:18:06 -08004107 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004108 if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
4109 return getCachedCellInfo();
4110 }
4111
Svetoslav Ganov4a9d4482017-06-20 19:53:35 -07004112 if (DBG_LOC) log("getAllCellInfo: is active user");
Narayan Kamathf04b5a12018-01-09 11:47:15 +00004113 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004114 final long identity = Binder.clearCallingIdentity();
4115 try {
4116 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
4117 for (Phone phone : PhoneFactory.getPhones()) {
Nathan Harold3ff88932018-08-14 10:19:49 -07004118 final List<CellInfo> info = (List<CellInfo>) sendRequest(
Nathan Harold92bed182018-10-12 18:16:49 -07004119 CMD_GET_ALL_CELL_INFO, null, phone, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004120 if (info != null) cellInfos.addAll(info);
4121 }
4122 return cellInfos;
4123 } finally {
4124 Binder.restoreCallingIdentity(identity);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004125 }
4126 }
4127
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07004128 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004129 public void requestCellInfoUpdate(int subId, ICellInfoCallback cb, String callingPackage,
4130 String callingFeatureId) {
4131 requestCellInfoUpdateInternal(subId, cb, callingPackage, callingFeatureId,
4132 getWorkSource(Binder.getCallingUid()));
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004133 }
4134
4135 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004136 public void requestCellInfoUpdateWithWorkSource(int subId, ICellInfoCallback cb,
4137 String callingPackage, String callingFeatureId, WorkSource workSource) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004138 enforceModifyPermission();
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004139 requestCellInfoUpdateInternal(subId, cb, callingPackage, callingFeatureId, workSource);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004140 }
4141
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004142 private void requestCellInfoUpdateInternal(int subId, ICellInfoCallback cb,
4143 String callingPackage, String callingFeatureId, WorkSource workSource) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004144 mApp.getSystemService(AppOpsManager.class)
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004145 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08004146
4147 LocationAccessPolicy.LocationPermissionResult locationResult =
4148 LocationAccessPolicy.checkLocationPermission(mApp,
4149 new LocationAccessPolicy.LocationPermissionQuery.Builder()
4150 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004151 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08004152 .setCallingPid(Binder.getCallingPid())
4153 .setCallingUid(Binder.getCallingUid())
4154 .setMethod("requestCellInfoUpdate")
Hall Liud60acc92020-05-21 17:09:35 -07004155 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
4156 .setMinSdkVersionForFine(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08004157 .build());
4158 switch (locationResult) {
4159 case DENIED_HARD:
Nathan Haroldf096d982020-11-18 17:18:06 -08004160 if (TelephonyPermissions
4161 .getTargetSdk(mApp, callingPackage) < Build.VERSION_CODES.Q) {
Hall Liud60acc92020-05-21 17:09:35 -07004162 // Safetynet logging for b/154934934
4163 EventLog.writeEvent(0x534e4554, "154934934", Binder.getCallingUid());
4164 }
Hall Liuf19c44f2018-11-27 14:38:17 -08004165 throw new SecurityException("Not allowed to access cell info");
4166 case DENIED_SOFT:
Nathan Haroldf096d982020-11-18 17:18:06 -08004167 if (TelephonyPermissions
4168 .getTargetSdk(mApp, callingPackage) < Build.VERSION_CODES.Q) {
Hall Liud60acc92020-05-21 17:09:35 -07004169 // Safetynet logging for b/154934934
4170 EventLog.writeEvent(0x534e4554, "154934934", Binder.getCallingUid());
4171 }
Nathan Harold5320c422019-05-09 10:26:08 -07004172 try {
4173 cb.onCellInfo(new ArrayList<CellInfo>());
4174 } catch (RemoteException re) {
4175 // Drop without consequences
4176 }
Hall Liuf19c44f2018-11-27 14:38:17 -08004177 return;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004178 }
4179
Nathan Harolda939a962019-05-09 10:13:47 -07004180
4181 final Phone phone = getPhoneFromSubId(subId);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004182 if (phone == null) throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
4183
4184 sendRequestAsync(CMD_REQUEST_CELL_INFO_UPDATE, cb, phone, workSource);
4185 }
4186
4187 @Override
Aishwarya Mallampati0603fb12022-08-24 21:16:56 +00004188 public void setCellInfoListRate(int rateInMillis, int subId) {
Jack Yua8d8cb82017-01-16 10:15:34 -08004189 enforceModifyPermission();
Narayan Kamathf04b5a12018-01-09 11:47:15 +00004190 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004191
4192 final long identity = Binder.clearCallingIdentity();
4193 try {
Aishwarya Mallampati0603fb12022-08-24 21:16:56 +00004194 Phone phone = getPhone(subId);
4195 if (phone == null) {
4196 getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
4197 } else {
4198 phone.setCellInfoListRate(rateInMillis, workSource);
4199 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004200 } finally {
4201 Binder.restoreCallingIdentity(identity);
4202 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004203 }
4204
Shishir Agrawala9f32182016-04-12 12:00:16 -07004205 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004206 public String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004207 Phone phone = PhoneFactory.getPhone(slotIndex);
4208 if (phone == null) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004209 return null;
4210 }
Jeff Davidson913390f2018-02-23 17:11:49 -08004211 int subId = phone.getSubId();
Grace Jia0ddb3612021-04-22 13:35:26 -07004212 enforceCallingPackage(callingPackage, Binder.getCallingUid(), "getImeiForSlot");
Michael Groover70af6dc2018-10-01 16:23:15 -07004213 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004214 callingPackage, callingFeatureId, "getImeiForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004215 return null;
4216 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004217
4218 final long identity = Binder.clearCallingIdentity();
4219 try {
4220 return phone.getImei();
4221 } finally {
4222 Binder.restoreCallingIdentity(identity);
4223 }
Shishir Agrawala9f32182016-04-12 12:00:16 -07004224 }
4225
4226 @Override
arunvoddud5c6ce02022-12-11 06:03:12 +00004227 public String getPrimaryImei(String callingPackage, String callingFeatureId) {
4228 enforceCallingPackage(callingPackage, Binder.getCallingUid(), "getPrimaryImei");
4229 if (!checkCallingOrSelfReadDeviceIdentifiersForAnySub(mApp, callingPackage,
4230 callingFeatureId, "getPrimaryImei")) {
4231 throw new SecurityException("Caller does not have permission");
4232 }
4233 final long identity = Binder.clearCallingIdentity();
4234 try {
4235 for (Phone phone : PhoneFactory.getPhones()) {
4236 if (phone.getImeiType() == Phone.IMEI_TYPE_PRIMARY) {
4237 return phone.getImei();
4238 }
4239 }
4240 throw new UnsupportedOperationException("Operation not supported");
4241 } finally {
4242 Binder.restoreCallingIdentity(identity);
4243 }
4244 }
4245
4246 @Override
David Kelly5e06a7f2018-03-12 14:10:59 +00004247 public String getTypeAllocationCodeForSlot(int slotIndex) {
4248 Phone phone = PhoneFactory.getPhone(slotIndex);
4249 String tac = null;
4250 if (phone != null) {
4251 String imei = phone.getImei();
Vala Zadehab005552021-09-21 15:54:29 -07004252 try {
4253 tac = imei == null ? null : imei.substring(0, TYPE_ALLOCATION_CODE_LENGTH);
4254 } catch (IndexOutOfBoundsException e) {
4255 Log.e(LOG_TAG, "IMEI length shorter than upper index.");
4256 return null;
4257 }
David Kelly5e06a7f2018-03-12 14:10:59 +00004258 }
4259 return tac;
4260 }
4261
4262 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004263 public String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
Shuo Qian13d89152021-05-10 23:58:11 -07004264 try {
4265 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4266 } catch (SecurityException se) {
4267 EventLog.writeEvent(0x534e4554, "186530496", Binder.getCallingUid());
4268 throw new SecurityException("Package " + callingPackage + " does not belong to "
4269 + Binder.getCallingUid());
4270 }
Jeff Davidson913390f2018-02-23 17:11:49 -08004271 Phone phone = PhoneFactory.getPhone(slotIndex);
4272 if (phone == null) {
Jack Yu2af8d712017-03-15 17:14:14 -07004273 return null;
4274 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004275
Jeff Davidson913390f2018-02-23 17:11:49 -08004276 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07004277 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004278 callingPackage, callingFeatureId, "getMeidForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004279 return null;
4280 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004281
4282 final long identity = Binder.clearCallingIdentity();
4283 try {
4284 return phone.getMeid();
4285 } finally {
4286 Binder.restoreCallingIdentity(identity);
4287 }
Jack Yu2af8d712017-03-15 17:14:14 -07004288 }
4289
4290 @Override
David Kelly5e06a7f2018-03-12 14:10:59 +00004291 public String getManufacturerCodeForSlot(int slotIndex) {
4292 Phone phone = PhoneFactory.getPhone(slotIndex);
4293 String manufacturerCode = null;
4294 if (phone != null) {
4295 String meid = phone.getMeid();
Vala Zadehab005552021-09-21 15:54:29 -07004296 try {
4297 manufacturerCode =
4298 meid == null ? null : meid.substring(0, MANUFACTURER_CODE_LENGTH);
4299 } catch (IndexOutOfBoundsException e) {
4300 Log.e(LOG_TAG, "MEID length shorter than upper index.");
4301 return null;
4302 }
David Kelly5e06a7f2018-03-12 14:10:59 +00004303 }
4304 return manufacturerCode;
4305 }
4306
4307 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004308 public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage,
4309 String callingFeatureId) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004310 Phone phone = PhoneFactory.getPhone(slotIndex);
4311 if (phone == null) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004312 return null;
4313 }
Jeff Davidson913390f2018-02-23 17:11:49 -08004314 int subId = phone.getSubId();
4315 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004316 mApp, subId, callingPackage, callingFeatureId,
4317 "getDeviceSoftwareVersionForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004318 return null;
4319 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004320
4321 final long identity = Binder.clearCallingIdentity();
4322 try {
4323 return phone.getDeviceSvn();
4324 } finally {
4325 Binder.restoreCallingIdentity(identity);
4326 }
Shishir Agrawala9f32182016-04-12 12:00:16 -07004327 }
4328
fionaxu43304da2017-11-27 22:51:16 -08004329 @Override
4330 public int getSubscriptionCarrierId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004331 final long identity = Binder.clearCallingIdentity();
4332 try {
4333 final Phone phone = getPhone(subId);
4334 return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID : phone.getCarrierId();
4335 } finally {
4336 Binder.restoreCallingIdentity(identity);
4337 }
fionaxu43304da2017-11-27 22:51:16 -08004338 }
4339
4340 @Override
4341 public String getSubscriptionCarrierName(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004342 final long identity = Binder.clearCallingIdentity();
4343 try {
4344 final Phone phone = getPhone(subId);
4345 return phone == null ? null : phone.getCarrierName();
4346 } finally {
4347 Binder.restoreCallingIdentity(identity);
4348 }
fionaxu43304da2017-11-27 22:51:16 -08004349 }
4350
calvinpanffe225e2018-11-01 19:43:06 +08004351 @Override
chen xu0026ca62019-03-06 15:28:50 -08004352 public int getSubscriptionSpecificCarrierId(int subId) {
chen xu25637222018-11-04 17:17:00 -08004353 final long identity = Binder.clearCallingIdentity();
4354 try {
4355 final Phone phone = getPhone(subId);
4356 return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID
chen xu0026ca62019-03-06 15:28:50 -08004357 : phone.getSpecificCarrierId();
chen xu25637222018-11-04 17:17:00 -08004358 } finally {
4359 Binder.restoreCallingIdentity(identity);
4360 }
4361 }
4362
4363 @Override
chen xu0026ca62019-03-06 15:28:50 -08004364 public String getSubscriptionSpecificCarrierName(int subId) {
chen xu25637222018-11-04 17:17:00 -08004365 final long identity = Binder.clearCallingIdentity();
4366 try {
4367 final Phone phone = getPhone(subId);
chen xu0026ca62019-03-06 15:28:50 -08004368 return phone == null ? null : phone.getSpecificCarrierName();
chen xu25637222018-11-04 17:17:00 -08004369 } finally {
4370 Binder.restoreCallingIdentity(identity);
4371 }
4372 }
4373
chen xu651eec72018-11-11 19:03:44 -08004374 @Override
chen xu864e11c2018-12-06 22:10:03 -08004375 public int getCarrierIdFromMccMnc(int slotIndex, String mccmnc, boolean isSubscriptionMccMnc) {
4376 if (!isSubscriptionMccMnc) {
4377 enforceReadPrivilegedPermission("getCarrierIdFromMccMnc");
4378 }
chen xu651eec72018-11-11 19:03:44 -08004379 final Phone phone = PhoneFactory.getPhone(slotIndex);
4380 if (phone == null) {
4381 return TelephonyManager.UNKNOWN_CARRIER_ID;
4382 }
4383 final long identity = Binder.clearCallingIdentity();
4384 try {
4385 return CarrierResolver.getCarrierIdFromMccMnc(phone.getContext(), mccmnc);
4386 } finally {
4387 Binder.restoreCallingIdentity(identity);
4388 }
4389 }
4390
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004391 //
4392 // Internal helper methods.
4393 //
4394
Sanket Padaweee13a9b2016-03-08 17:30:28 -08004395 /**
Grace Jia0ddb3612021-04-22 13:35:26 -07004396 * Make sure the caller is the calling package itself
4397 *
4398 * @throws SecurityException if the caller is not the calling package
4399 */
4400 private void enforceCallingPackage(String callingPackage, int callingUid, String message) {
4401 int packageUid = -1;
Grace Jiadbefca02021-04-26 15:13:31 -07004402 PackageManager pm = mApp.getBaseContext().createContextAsUser(
4403 UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
Grace Jia0ddb3612021-04-22 13:35:26 -07004404 try {
Grace Jiadbefca02021-04-26 15:13:31 -07004405 packageUid = pm.getPackageUid(callingPackage, 0);
Grace Jia0ddb3612021-04-22 13:35:26 -07004406 } catch (PackageManager.NameNotFoundException e) {
4407 // packageUid is -1
4408 }
4409 if (packageUid != callingUid) {
4410 throw new SecurityException(message + ": Package " + callingPackage
4411 + " does not belong to " + callingUid);
4412 }
4413 }
4414
4415 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004416 * Make sure the caller has the MODIFY_PHONE_STATE permission.
4417 *
4418 * @throws SecurityException if the caller does not have the required permission
4419 */
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004420 @VisibleForTesting
4421 public void enforceModifyPermission() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004422 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
4423 }
4424
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004425 /**
arunvoddud7401012022-12-15 16:08:12 +00004426 * Make sure the caller has the READ_PHONE_STATE permission.
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004427 *
4428 * @throws SecurityException if the caller does not have the required permission
4429 */
4430 @VisibleForTesting
4431 public void enforceReadPermission() {
arunvoddud7401012022-12-15 16:08:12 +00004432 enforceReadPermission(null);
4433 }
4434
4435 /**
4436 * Make sure the caller has the READ_PHONE_STATE permissions.
4437 *
4438 * @throws SecurityException if the caller does not have the READ_PHONE_STATE permission.
4439 */
4440 @VisibleForTesting
4441 public void enforceReadPermission(String msg) {
4442 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, msg);
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004443 }
4444
Shuo Qian3b6ee772019-11-13 17:43:31 -08004445 private void enforceActiveEmergencySessionPermission() {
4446 mApp.enforceCallingOrSelfPermission(
4447 android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
4448 }
4449
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004450 /**
4451 * Make sure the caller has the CALL_PHONE permission.
4452 *
4453 * @throws SecurityException if the caller does not have the required permission
4454 */
4455 private void enforceCallPermission() {
4456 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
4457 }
4458
paulhu5a773602019-08-23 19:17:33 +08004459 private void enforceSettingsPermission() {
4460 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, null);
Stuart Scott8eef64f2015-04-08 15:13:54 -07004461 }
4462
Michele Berionne5e411512020-11-13 02:36:59 +00004463 private void enforceRebootPermission() {
4464 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
4465 }
4466
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00004467 /**
4468 * Make sure the caller has SATELLITE_COMMUNICATION permission.
4469 * @param message - log message to print.
4470 * @throws SecurityException if the caller does not have the required permission
4471 */
4472 private void enforceSatelliteCommunicationPermission(String message) {
4473 mApp.enforceCallingOrSelfPermission(permission.SATELLITE_COMMUNICATION, message);
4474 }
4475
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004476 private String createTelUrl(String number) {
4477 if (TextUtils.isEmpty(number)) {
4478 return null;
4479 }
4480
Jake Hambye994d462014-02-03 13:10:13 -08004481 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004482 }
4483
Ihab Awadf9e92732013-12-05 18:02:52 -08004484 private static void log(String msg) {
Ling Ma83dc5ea2023-01-12 15:06:04 -08004485 Log.d(LOG_TAG, msg);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004486 }
4487
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07004488 private static void logv(String msg) {
4489 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
4490 }
4491
Ihab Awadf9e92732013-12-05 18:02:52 -08004492 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004493 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
4494 }
4495
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004496 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004497 public int getActivePhoneType() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07004498 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07004499 }
4500
Sanket Padawe356d7632015-06-22 14:03:32 -07004501 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07004502 public int getActivePhoneTypeForSlot(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004503 final long identity = Binder.clearCallingIdentity();
4504 try {
4505 final Phone phone = PhoneFactory.getPhone(slotIndex);
4506 if (phone == null) {
4507 return PhoneConstants.PHONE_TYPE_NONE;
4508 } else {
4509 return phone.getPhoneType();
4510 }
4511 } finally {
4512 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004513 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004514 }
4515
4516 /**
4517 * Returns the CDMA ERI icon index to display
4518 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004519 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004520 public int getCdmaEriIconIndex(String callingPackage, String callingFeatureId) {
4521 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage,
4522 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07004523 }
4524
Sanket Padawe356d7632015-06-22 14:03:32 -07004525 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004526 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage,
4527 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004528 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004529 mApp, subId, callingPackage, callingFeatureId,
4530 "getCdmaEriIconIndexForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004531 return -1;
4532 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004533
4534 final long identity = Binder.clearCallingIdentity();
4535 try {
4536 final Phone phone = getPhone(subId);
4537 if (phone != null) {
4538 return phone.getCdmaEriIconIndex();
4539 } else {
4540 return -1;
4541 }
4542 } finally {
4543 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004544 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004545 }
4546
4547 /**
4548 * Returns the CDMA ERI icon mode,
4549 * 0 - ON
4550 * 1 - FLASHING
4551 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004552 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004553 public int getCdmaEriIconMode(String callingPackage, String callingFeatureId) {
4554 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage,
4555 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07004556 }
4557
Sanket Padawe356d7632015-06-22 14:03:32 -07004558 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004559 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage,
4560 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004561 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004562 mApp, subId, callingPackage, callingFeatureId,
4563 "getCdmaEriIconModeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004564 return -1;
4565 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004566
4567 final long identity = Binder.clearCallingIdentity();
4568 try {
4569 final Phone phone = getPhone(subId);
4570 if (phone != null) {
4571 return phone.getCdmaEriIconMode();
4572 } else {
4573 return -1;
4574 }
4575 } finally {
4576 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004577 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004578 }
4579
4580 /**
4581 * Returns the CDMA ERI text,
4582 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004583 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004584 public String getCdmaEriText(String callingPackage, String callingFeatureId) {
4585 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage,
4586 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07004587 }
4588
Sanket Padawe356d7632015-06-22 14:03:32 -07004589 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004590 public String getCdmaEriTextForSubscriber(int subId, String callingPackage,
4591 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004592 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004593 mApp, subId, callingPackage, callingFeatureId,
4594 "getCdmaEriIconTextForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004595 return null;
4596 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004597
4598 final long identity = Binder.clearCallingIdentity();
4599 try {
4600 final Phone phone = getPhone(subId);
4601 if (phone != null) {
4602 return phone.getCdmaEriText();
4603 } else {
4604 return null;
4605 }
4606 } finally {
4607 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004608 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004609 }
4610
4611 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07004612 * Returns the CDMA MDN.
4613 */
Sanket Padawe356d7632015-06-22 14:03:32 -07004614 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07004615 public String getCdmaMdn(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004616 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4617 mApp, subId, "getCdmaMdn");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004618
4619 final long identity = Binder.clearCallingIdentity();
4620 try {
4621 final Phone phone = getPhone(subId);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004622 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004623 return phone.getLine1Number();
4624 } else {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004625 loge("getCdmaMdn: no phone found. Invalid subId: " + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004626 return null;
4627 }
4628 } finally {
4629 Binder.restoreCallingIdentity(identity);
Junda Liuca05d5d2014-08-14 22:36:34 -07004630 }
4631 }
4632
4633 /**
4634 * Returns the CDMA MIN.
4635 */
Sanket Padawe356d7632015-06-22 14:03:32 -07004636 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07004637 public String getCdmaMin(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004638 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4639 mApp, subId, "getCdmaMin");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004640
4641 final long identity = Binder.clearCallingIdentity();
4642 try {
4643 final Phone phone = getPhone(subId);
4644 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
4645 return phone.getCdmaMin();
4646 } else {
4647 return null;
4648 }
4649 } finally {
4650 Binder.restoreCallingIdentity(identity);
Junda Liuca05d5d2014-08-14 22:36:34 -07004651 }
4652 }
4653
Hall Liud892bec2018-11-30 14:51:45 -08004654 @Override
4655 public void requestNumberVerification(PhoneNumberRange range, long timeoutMillis,
4656 INumberVerificationCallback callback, String callingPackage) {
4657 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
4658 != PERMISSION_GRANTED) {
4659 throw new SecurityException("Caller must hold the MODIFY_PHONE_STATE permission");
4660 }
4661 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4662
4663 String authorizedPackage = NumberVerificationManager.getAuthorizedPackage(mApp);
4664 if (!TextUtils.equals(callingPackage, authorizedPackage)) {
Hall Liub9d8feb2021-01-13 10:28:04 -08004665 throw new SecurityException("Calling package must be configured in the device config: "
4666 + "calling package: " + callingPackage
4667 + ", configured package: " + authorizedPackage);
Hall Liud892bec2018-11-30 14:51:45 -08004668 }
4669
4670 if (range == null) {
4671 throw new NullPointerException("Range must be non-null");
4672 }
4673
4674 timeoutMillis = Math.min(timeoutMillis,
Hall Liubd069e32019-02-28 18:56:30 -08004675 TelephonyManager.getMaxNumberVerificationTimeoutMillis());
Hall Liud892bec2018-11-30 14:51:45 -08004676
4677 NumberVerificationManager.getInstance().requestVerification(range, callback, timeoutMillis);
4678 }
4679
Junda Liuca05d5d2014-08-14 22:36:34 -07004680 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004681 * Returns true if CDMA provisioning needs to run.
4682 */
4683 public boolean needsOtaServiceProvisioning() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004684 final long identity = Binder.clearCallingIdentity();
4685 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004686 return getDefaultPhone().needsOtaServiceProvisioning();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004687 } finally {
4688 Binder.restoreCallingIdentity(identity);
4689 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004690 }
4691
4692 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08004693 * Sets the voice mail number of a given subId.
4694 */
4695 @Override
4696 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08004697 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
4698 mApp, subId, "setVoiceMailNumber");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004699
4700 final long identity = Binder.clearCallingIdentity();
4701 try {
4702 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
4703 new Pair<String, String>(alphaTag, number), new Integer(subId));
4704 return success;
4705 } finally {
4706 Binder.restoreCallingIdentity(identity);
4707 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08004708 }
4709
Ta-wei Yen87c49842016-05-13 21:19:52 -07004710 @Override
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004711 public Bundle getVisualVoicemailSettings(String callingPackage, int subId) {
4712 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07004713 TelecomManager tm = mApp.getSystemService(TelecomManager.class);
4714 String systemDialer = tm.getSystemDialerPackage();
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004715 if (!TextUtils.equals(callingPackage, systemDialer)) {
4716 throw new SecurityException("caller must be system dialer");
4717 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004718
4719 final long identity = Binder.clearCallingIdentity();
4720 try {
4721 PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(subId);
4722 if (phoneAccountHandle == null) {
4723 return null;
4724 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004725 return VisualVoicemailSettingsUtil.dump(mApp, phoneAccountHandle);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004726 } finally {
4727 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004728 }
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004729 }
4730
4731 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004732 public String getVisualVoicemailPackageName(String callingPackage, String callingFeatureId,
4733 int subId) {
Ta-wei Yendca928f2017-01-10 16:17:08 -08004734 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jeff Davidson7e17e312018-02-13 18:17:36 -08004735 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004736 mApp, subId, callingPackage, callingFeatureId,
4737 "getVisualVoicemailPackageName")) {
Ta-wei Yendca928f2017-01-10 16:17:08 -08004738 return null;
4739 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004740
Jeff Davidsona8e4e242018-03-15 17:16:18 -07004741 final long identity = Binder.clearCallingIdentity();
4742 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004743 return RemoteVvmTaskManager.getRemotePackage(mApp, subId).getPackageName();
Jeff Davidsona8e4e242018-03-15 17:16:18 -07004744 } finally {
4745 Binder.restoreCallingIdentity(identity);
4746 }
Ta-wei Yendca928f2017-01-10 16:17:08 -08004747 }
4748
4749 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07004750 public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
4751 VisualVoicemailSmsFilterSettings settings) {
4752 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004753
4754 final long identity = Binder.clearCallingIdentity();
4755 try {
4756 VisualVoicemailSmsFilterConfig.enableVisualVoicemailSmsFilter(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004757 mApp, callingPackage, subId, settings);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004758 } finally {
4759 Binder.restoreCallingIdentity(identity);
4760 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07004761 }
4762
4763 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07004764 public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
4765 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004766
4767 final long identity = Binder.clearCallingIdentity();
4768 try {
4769 VisualVoicemailSmsFilterConfig.disableVisualVoicemailSmsFilter(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004770 mApp, callingPackage, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004771 } finally {
4772 Binder.restoreCallingIdentity(identity);
4773 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07004774 }
4775
4776 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07004777 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
4778 String callingPackage, int subId) {
4779 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004780
4781 final long identity = Binder.clearCallingIdentity();
4782 try {
4783 return VisualVoicemailSmsFilterConfig.getVisualVoicemailSmsFilterSettings(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004784 mApp, callingPackage, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004785 } finally {
4786 Binder.restoreCallingIdentity(identity);
4787 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07004788 }
4789
4790 @Override
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004791 public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07004792 enforceReadPrivilegedPermission("getActiveVisualVoicemailSmsFilterSettings");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004793
4794 final long identity = Binder.clearCallingIdentity();
4795 try {
4796 return VisualVoicemailSmsFilterConfig.getActiveVisualVoicemailSmsFilterSettings(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004797 mApp, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004798 } finally {
4799 Binder.restoreCallingIdentity(identity);
4800 }
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004801 }
4802
4803 @Override
Philip P. Moltmann2f6f8ce2020-03-18 18:17:02 -07004804 public void sendVisualVoicemailSmsForSubscriber(String callingPackage,
4805 String callingAttributionTag, int subId, String number, int port, String text,
4806 PendingIntent sentIntent) {
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004807 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen527a9c02017-01-06 15:29:25 -08004808 enforceVisualVoicemailPackage(callingPackage, subId);
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004809 enforceSendSmsPermission();
Amit Mahajandccb3f12019-05-13 13:48:32 -07004810 SmsController smsController = PhoneFactory.getSmsController();
Philip P. Moltmann2f6f8ce2020-03-18 18:17:02 -07004811 smsController.sendVisualVoicemailSmsForSubscriber(callingPackage, callingAttributionTag,
4812 subId, number, port, text, sentIntent);
Ta-wei Yen87c49842016-05-13 21:19:52 -07004813 }
Amit Mahajandccb3f12019-05-13 13:48:32 -07004814
Shishir Agrawal76d5da92014-11-09 16:17:25 -08004815 /**
fionaxu0152e512016-11-14 13:36:14 -08004816 * Sets the voice activation state of a given subId.
4817 */
4818 @Override
4819 public void setVoiceActivationState(int subId, int activationState) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004820 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4821 mApp, subId, "setVoiceActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004822
4823 final long identity = Binder.clearCallingIdentity();
4824 try {
4825 final Phone phone = getPhone(subId);
4826 if (phone != null) {
4827 phone.setVoiceActivationState(activationState);
4828 } else {
4829 loge("setVoiceActivationState fails with invalid subId: " + subId);
4830 }
4831 } finally {
4832 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004833 }
4834 }
4835
4836 /**
4837 * Sets the data activation state of a given subId.
4838 */
4839 @Override
4840 public void setDataActivationState(int subId, int activationState) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004841 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4842 mApp, subId, "setDataActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004843
4844 final long identity = Binder.clearCallingIdentity();
4845 try {
4846 final Phone phone = getPhone(subId);
4847 if (phone != null) {
4848 phone.setDataActivationState(activationState);
4849 } else {
Taesu Leef8fbed92019-10-07 18:47:02 +09004850 loge("setDataActivationState fails with invalid subId: " + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004851 }
4852 } finally {
4853 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004854 }
4855 }
4856
4857 /**
4858 * Returns the voice activation state of a given subId.
4859 */
4860 @Override
4861 public int getVoiceActivationState(int subId, String callingPackage) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07004862 enforceReadPrivilegedPermission("getVoiceActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004863
fionaxu0152e512016-11-14 13:36:14 -08004864 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004865 final long identity = Binder.clearCallingIdentity();
4866 try {
4867 if (phone != null) {
4868 return phone.getVoiceActivationState();
4869 } else {
4870 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
4871 }
4872 } finally {
4873 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004874 }
4875 }
4876
4877 /**
4878 * Returns the data activation state of a given subId.
4879 */
4880 @Override
4881 public int getDataActivationState(int subId, String callingPackage) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07004882 enforceReadPrivilegedPermission("getDataActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004883
fionaxu0152e512016-11-14 13:36:14 -08004884 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004885 final long identity = Binder.clearCallingIdentity();
4886 try {
4887 if (phone != null) {
4888 return phone.getDataActivationState();
4889 } else {
4890 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
4891 }
4892 } finally {
4893 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004894 }
4895 }
4896
4897 /**
Wink Saville36469e72014-06-11 15:17:00 -07004898 * Returns the unread count of voicemails for a subId
4899 */
Sanket Padawe356d7632015-06-22 14:03:32 -07004900 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004901 public int getVoiceMessageCountForSubscriber(int subId, String callingPackage,
4902 String callingFeatureId) {
Brad Ebingerf7664ba2018-11-29 12:43:38 -08004903 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004904 mApp, subId, callingPackage, callingFeatureId,
4905 "getVoiceMessageCountForSubscriber")) {
Brad Ebingerf7664ba2018-11-29 12:43:38 -08004906 return 0;
4907 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004908 final long identity = Binder.clearCallingIdentity();
4909 try {
4910 final Phone phone = getPhone(subId);
4911 if (phone != null) {
4912 return phone.getVoiceMessageCount();
4913 } else {
4914 return 0;
4915 }
4916 } finally {
4917 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004918 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004919 }
4920
4921 /**
Thomas Nguyen8ee49682023-02-01 11:46:09 -08004922 * returns true, if the device is in a state where both voice and data
4923 * are supported simultaneously. This can change based on location or network condition.
pkanwar8a4dcfb2017-01-19 13:43:16 -08004924 */
4925 @Override
4926 public boolean isConcurrentVoiceAndDataAllowed(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004927 final long identity = Binder.clearCallingIdentity();
4928 try {
4929 final Phone phone = getPhone(subId);
4930 return (phone == null ? false : phone.isConcurrentVoiceAndDataAllowed());
4931 } finally {
4932 Binder.restoreCallingIdentity(identity);
4933 }
pkanwar8a4dcfb2017-01-19 13:43:16 -08004934 }
4935
4936 /**
fionaxu235cc5e2017-03-06 22:25:57 -08004937 * Send the dialer code if called from the current default dialer or the caller has
4938 * carrier privilege.
4939 * @param inputCode The dialer code to send
4940 */
4941 @Override
4942 public void sendDialerSpecialCode(String callingPackage, String inputCode) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004943 final Phone defaultPhone = getDefaultPhone();
fionaxu235cc5e2017-03-06 22:25:57 -08004944 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07004945 TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
4946 String defaultDialer = tm.getDefaultDialerPackage();
fionaxu235cc5e2017-03-06 22:25:57 -08004947 if (!TextUtils.equals(callingPackage, defaultDialer)) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08004948 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
Jeff Davidson7e17e312018-02-13 18:17:36 -08004949 getDefaultSubscription(), "sendDialerSpecialCode");
fionaxu235cc5e2017-03-06 22:25:57 -08004950 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004951
4952 final long identity = Binder.clearCallingIdentity();
4953 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004954 defaultPhone.sendDialerSpecialCode(inputCode);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004955 } finally {
4956 Binder.restoreCallingIdentity(identity);
4957 }
fionaxu235cc5e2017-03-06 22:25:57 -08004958 }
4959
Pengquan Menga1bb6272018-09-06 09:59:22 -07004960 @Override
4961 public int getNetworkSelectionMode(int subId) {
shilufc958392020-01-20 11:36:01 -08004962 TelephonyPermissions
Thomas Nguyen8ee49682023-02-01 11:46:09 -08004963 .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
4964 mApp, subId, "getNetworkSelectionMode");
shilufc958392020-01-20 11:36:01 -08004965 final long identity = Binder.clearCallingIdentity();
4966 try {
4967 if (!isActiveSubscription(subId)) {
4968 return TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
4969 }
4970 return (int) sendRequest(CMD_GET_NETWORK_SELECTION_MODE, null /* argument */, subId);
4971 } finally {
4972 Binder.restoreCallingIdentity(identity);
Pengquan Menge92a50d2018-09-21 15:54:48 -07004973 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07004974 }
4975
Brad Ebinger35c841c2018-10-01 10:40:55 -07004976 @Override
Brad Ebingerb2b65522019-03-15 13:48:47 -07004977 public boolean isInEmergencySmsMode() {
4978 enforceReadPrivilegedPermission("isInEmergencySmsMode");
4979 final long identity = Binder.clearCallingIdentity();
4980 try {
4981 for (Phone phone : PhoneFactory.getPhones()) {
4982 if (phone.isInEmergencySmsMode()) {
4983 return true;
4984 }
4985 }
4986 } finally {
4987 Binder.restoreCallingIdentity(identity);
4988 }
4989 return false;
4990 }
4991
shilu366312e2019-12-17 09:28:10 -08004992 /**
4993 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
4994 * @param subId The subscription to use to check the configuration.
4995 * @param c The callback that will be used to send the result.
4996 */
Brad Ebingerb2b65522019-03-15 13:48:47 -07004997 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08004998 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
4999 throws RemoteException {
Nathan Harold62c68512021-04-06 11:26:02 -07005000 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005001 mApp, subId, "registerImsRegistrationCallback");
Brad Ebingera2628302022-02-18 03:44:55 +00005002
5003 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5004 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5005 "IMS not available on device.");
5006 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005007 final long token = Binder.clearCallingIdentity();
5008 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005009 int slotId = getSlotIndexOrException(subId);
5010 verifyImsMmTelConfiguredOrThrow(slotId);
joonhunshin49f0aed2022-08-05 08:33:05 +00005011
5012 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5013 if (controller != null) {
5014 ImsManager imsManager = controller.getImsManager(subId);
5015 if (imsManager != null) {
5016 imsManager.addRegistrationCallbackForSubscription(c, subId);
5017 } else {
5018 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
5019 }
5020 } else {
5021 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5022 }
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005023 } catch (ImsException e) {
5024 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005025 } finally {
5026 Binder.restoreCallingIdentity(token);
5027 }
5028 }
5029
shilu366312e2019-12-17 09:28:10 -08005030 /**
5031 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5032 * @param subId The subscription to use to check the configuration.
5033 * @param c The callback that will be used to send the result.
5034 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005035 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005036 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c) {
Nathan Harold62c68512021-04-06 11:26:02 -07005037 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005038 mApp, subId, "unregisterImsRegistrationCallback");
Brad Ebinger4ae57f92019-01-09 16:51:30 -08005039 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5040 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5041 }
Meng Wangafbc5852019-09-19 17:37:13 -07005042 final long token = Binder.clearCallingIdentity();
joonhunshin49f0aed2022-08-05 08:33:05 +00005043
Meng Wangafbc5852019-09-19 17:37:13 -07005044 try {
joonhunshin49f0aed2022-08-05 08:33:05 +00005045 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5046 if (controller != null) {
5047 ImsManager imsManager = controller.getImsManager(subId);
5048 if (imsManager != null) {
5049 imsManager.removeRegistrationCallbackForSubscription(c, subId);
5050 } else {
5051 Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
5052 + "is inactive, ignoring unregister.");
5053 // If the ImsManager is not valid, just return, since the callback
5054 // will already have been removed internally.
5055 }
5056 }
Meng Wangafbc5852019-09-19 17:37:13 -07005057 } finally {
5058 Binder.restoreCallingIdentity(token);
5059 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005060 }
5061
Brad Ebingera34a6c22019-10-22 17:36:18 -07005062 /**
5063 * Get the IMS service registration state for the MmTelFeature associated with this sub id.
5064 */
5065 @Override
5066 public void getImsMmTelRegistrationState(int subId, IIntegerConsumer consumer) {
5067 enforceReadPrivilegedPermission("getImsMmTelRegistrationState");
5068 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5069 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5070 "IMS not available on device.");
5071 }
5072 final long token = Binder.clearCallingIdentity();
5073 try {
5074 Phone phone = getPhone(subId);
5075 if (phone == null) {
5076 Log.w(LOG_TAG, "getImsMmTelRegistrationState: called with an invalid subscription '"
5077 + subId + "'");
5078 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5079 }
5080 phone.getImsRegistrationState(regState -> {
5081 try {
5082 consumer.accept((regState == null)
5083 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
5084 } catch (RemoteException e) {
5085 // Ignore if the remote process is no longer available to call back.
5086 Log.w(LOG_TAG, "getImsMmTelRegistrationState: callback not available.");
5087 }
5088 });
5089 } finally {
5090 Binder.restoreCallingIdentity(token);
5091 }
5092 }
5093
5094 /**
5095 * Get the transport type for the IMS service registration state.
5096 */
5097 @Override
5098 public void getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold62c68512021-04-06 11:26:02 -07005099 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005100 mApp, subId, "getImsMmTelRegistrationTransportType");
Brad Ebingera34a6c22019-10-22 17:36:18 -07005101 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5102 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5103 "IMS not available on device.");
5104 }
5105 final long token = Binder.clearCallingIdentity();
5106 try {
5107 Phone phone = getPhone(subId);
5108 if (phone == null) {
5109 Log.w(LOG_TAG, "getImsMmTelRegistrationState: called with an invalid subscription '"
5110 + subId + "'");
5111 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5112 }
5113 phone.getImsRegistrationTech(regTech -> {
5114 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
5115 int regTechConverted = (regTech == null)
5116 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
5117 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
5118 regTechConverted);
5119 try {
5120 consumer.accept(regTechConverted);
5121 } catch (RemoteException e) {
5122 // Ignore if the remote process is no longer available to call back.
5123 Log.w(LOG_TAG, "getImsMmTelRegistrationState: callback not available.");
5124 }
5125 });
5126 } finally {
5127 Binder.restoreCallingIdentity(token);
5128 }
5129 }
5130
shilu366312e2019-12-17 09:28:10 -08005131 /**
5132 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5133 * @param subId The subscription to use to check the configuration.
5134 * @param c The callback that will be used to send the result.
5135 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005136 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005137 public void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)
5138 throws RemoteException {
Nathan Harold62c68512021-04-06 11:26:02 -07005139 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005140 mApp, subId, "registerMmTelCapabilityCallback");
Brad Ebingera2628302022-02-18 03:44:55 +00005141 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5142 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5143 "IMS not available on device.");
5144 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005145 final long token = Binder.clearCallingIdentity();
5146 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005147 int slotId = getSlotIndexOrException(subId);
5148 verifyImsMmTelConfiguredOrThrow(slotId);
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005149
5150 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5151 if (controller != null) {
5152 ImsManager imsManager = controller.getImsManager(subId);
5153 if (imsManager != null) {
5154 imsManager.addCapabilitiesCallbackForSubscription(c, subId);
5155 } else {
5156 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
5157 }
5158 } else {
5159 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5160 }
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005161 } catch (ImsException e) {
5162 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005163 } finally {
5164 Binder.restoreCallingIdentity(token);
5165 }
5166 }
5167
shilu366312e2019-12-17 09:28:10 -08005168 /**
5169 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5170 * @param subId The subscription to use to check the configuration.
5171 * @param c The callback that will be used to send the result.
5172 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005173 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005174 public void unregisterMmTelCapabilityCallback(int subId, IImsCapabilityCallback c) {
Nathan Harold62c68512021-04-06 11:26:02 -07005175 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005176 mApp, subId, "unregisterMmTelCapabilityCallback");
Brad Ebinger4ae57f92019-01-09 16:51:30 -08005177 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5178 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5179 }
Meng Wangafbc5852019-09-19 17:37:13 -07005180
5181 final long token = Binder.clearCallingIdentity();
5182 try {
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005183 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5184 if (controller != null) {
5185 ImsManager imsManager = controller.getImsManager(subId);
5186 if (imsManager != null) {
5187 imsManager.removeCapabilitiesCallbackForSubscription(c, subId);
5188 } else {
5189 Log.i(LOG_TAG, "unregisterMmTelCapabilityCallback: " + subId
5190 + " is inactive, ignoring unregister.");
5191 // If the ImsManager is not valid, just return, since the callback
5192 // will already have been removed internally.
5193 }
5194 }
Meng Wangafbc5852019-09-19 17:37:13 -07005195 } finally {
5196 Binder.restoreCallingIdentity(token);
5197 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005198 }
5199
5200 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005201 public boolean isCapable(int subId, int capability, int regTech) {
5202 enforceReadPrivilegedPermission("isCapable");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005203 final long token = Binder.clearCallingIdentity();
5204 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005205 int slotId = getSlotIndexOrException(subId);
5206 verifyImsMmTelConfiguredOrThrow(slotId);
5207 return ImsManager.getInstance(mApp, slotId).queryMmTelCapability(capability, regTech);
5208 } catch (com.android.ims.ImsException e) {
5209 Log.w(LOG_TAG, "IMS isCapable - service unavailable: " + e.getMessage());
5210 return false;
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005211 } catch (ImsException e) {
Brad Ebinger6b5ac222019-02-04 14:36:52 -08005212 Log.i(LOG_TAG, "isCapable: " + subId + " is inactive, returning false.");
5213 return false;
Brad Ebinger35c841c2018-10-01 10:40:55 -07005214 } finally {
5215 Binder.restoreCallingIdentity(token);
5216 }
5217 }
5218
5219 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005220 public boolean isAvailable(int subId, int capability, int regTech) {
5221 enforceReadPrivilegedPermission("isAvailable");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005222 final long token = Binder.clearCallingIdentity();
5223 try {
5224 Phone phone = getPhone(subId);
5225 if (phone == null) return false;
5226 return phone.isImsCapabilityAvailable(capability, regTech);
Daniel Bright5e40e4e2020-03-11 16:35:39 -07005227 } catch (com.android.ims.ImsException e) {
5228 Log.w(LOG_TAG, "IMS isAvailable - service unavailable: " + e.getMessage());
5229 return false;
Brad Ebinger35c841c2018-10-01 10:40:55 -07005230 } finally {
5231 Binder.restoreCallingIdentity(token);
5232 }
5233 }
5234
Brad Ebingerbc7dd582019-10-17 17:03:22 -07005235 /**
5236 * Determines if the MmTel feature capability is supported by the carrier configuration for this
5237 * subscription.
5238 * @param subId The subscription to use to check the configuration.
5239 * @param callback The callback that will be used to send the result.
5240 * @param capability The MmTelFeature capability that will be used to send the result.
5241 * @param transportType The transport type of the MmTelFeature capability.
5242 */
5243 @Override
5244 public void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability,
5245 int transportType) {
5246 enforceReadPrivilegedPermission("isMmTelCapabilitySupported");
Brad Ebingera2628302022-02-18 03:44:55 +00005247 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5248 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5249 "IMS not available on device.");
5250 }
Brad Ebingerbc7dd582019-10-17 17:03:22 -07005251 final long token = Binder.clearCallingIdentity();
5252 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005253 int slotId = getSlotIndex(subId);
5254 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5255 Log.w(LOG_TAG, "isMmTelCapabilitySupported: called with an inactive subscription '"
5256 + subId + "'");
5257 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5258 }
5259 verifyImsMmTelConfiguredOrThrow(slotId);
5260 ImsManager.getInstance(mApp, slotId).isSupported(capability,
5261 transportType, aBoolean -> {
5262 try {
5263 callback.accept((aBoolean == null) ? 0 : (aBoolean ? 1 : 0));
5264 } catch (RemoteException e) {
5265 Log.w(LOG_TAG, "isMmTelCapabilitySupported: remote caller is not "
5266 + "running. Ignore");
5267 }
5268 });
Brad Ebinger919631e2021-06-02 17:46:35 -07005269 } catch (ImsException e) {
5270 throw new ServiceSpecificException(e.getCode());
Brad Ebingerbc7dd582019-10-17 17:03:22 -07005271 } finally {
5272 Binder.restoreCallingIdentity(token);
5273 }
5274 }
5275
shilu366312e2019-12-17 09:28:10 -08005276 /**
5277 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5278 * @param subId The subscription to use to check the configuration.
5279 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005280 @Override
5281 public boolean isAdvancedCallingSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005282 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005283 mApp, subId, "isAdvancedCallingSettingEnabled");
shilu366312e2019-12-17 09:28:10 -08005284
Brad Ebinger35c841c2018-10-01 10:40:55 -07005285 final long token = Binder.clearCallingIdentity();
5286 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005287 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005288 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005289 return ImsManager.getInstance(mApp, slotId).isEnhanced4gLteModeSettingEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005290 } catch (ImsException e) {
5291 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005292 } finally {
5293 Binder.restoreCallingIdentity(token);
5294 }
5295 }
5296
5297 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005298 public void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005299 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005300 "setAdvancedCallingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005301 final long identity = Binder.clearCallingIdentity();
5302 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005303 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005304 // This setting doesn't require an active ImsService connection, so do not verify. The
5305 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005306 ImsManager.getInstance(mApp, slotId).setEnhanced4gLteModeSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005307 } catch (ImsException e) {
5308 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005309 } finally {
5310 Binder.restoreCallingIdentity(identity);
5311 }
5312 }
5313
shilu366312e2019-12-17 09:28:10 -08005314 /**
5315 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5316 * @param subId The subscription to use to check the configuration.
5317 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005318 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005319 public boolean isVtSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005320 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005321 mApp, subId, "isVtSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005322 final long identity = Binder.clearCallingIdentity();
5323 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005324 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005325 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005326 return ImsManager.getInstance(mApp, slotId).isVtEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005327 } catch (ImsException e) {
5328 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005329 } finally {
5330 Binder.restoreCallingIdentity(identity);
5331 }
5332 }
5333
5334 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005335 public void setVtSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005336 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005337 "setVtSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005338 final long identity = Binder.clearCallingIdentity();
5339 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005340 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005341 // This setting doesn't require an active ImsService connection, so do not verify. The
5342 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005343 ImsManager.getInstance(mApp, slotId).setVtSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005344 } catch (ImsException e) {
5345 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005346 } finally {
5347 Binder.restoreCallingIdentity(identity);
5348 }
5349 }
5350
shilu366312e2019-12-17 09:28:10 -08005351 /**
5352 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5353 * @param subId The subscription to use to check the configuration.
5354 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005355 @Override
5356 public boolean isVoWiFiSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005357 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005358 mApp, subId, "isVoWiFiSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005359 final long identity = Binder.clearCallingIdentity();
5360 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005361 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005362 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005363 return ImsManager.getInstance(mApp, slotId).isWfcEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005364 } catch (ImsException e) {
5365 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005366 } finally {
5367 Binder.restoreCallingIdentity(identity);
5368 }
5369 }
5370
5371 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005372 public void setVoWiFiSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005373 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005374 "setVoWiFiSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005375 final long identity = Binder.clearCallingIdentity();
5376 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005377 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005378 // This setting doesn't require an active ImsService connection, so do not verify. The
5379 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005380 ImsManager.getInstance(mApp, slotId).setWfcSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005381 } catch (ImsException e) {
5382 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005383 } finally {
5384 Binder.restoreCallingIdentity(identity);
5385 }
5386 }
5387
shilu366312e2019-12-17 09:28:10 -08005388 /**
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005389 * @return true if the user's setting for Voice over Cross SIM is enabled and false if it is not
5390 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5391 * @param subId The subscription to use to check the configuration.
5392 */
5393 @Override
5394 public boolean isCrossSimCallingEnabledByUser(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005395 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005396 mApp, subId, "isCrossSimCallingEnabledByUser");
5397 final long identity = Binder.clearCallingIdentity();
5398 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005399 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005400 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005401 return ImsManager.getInstance(mApp, slotId).isCrossSimCallingEnabledByUser();
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005402 } catch (ImsException e) {
5403 throw new ServiceSpecificException(e.getCode());
5404 } finally {
5405 Binder.restoreCallingIdentity(identity);
5406 }
5407 }
5408
5409 /**
5410 * Sets the user's setting for whether or not Voice over Cross SIM is enabled.
5411 * Requires MODIFY_PHONE_STATE permission.
5412 * @param subId The subscription to use to check the configuration.
5413 * @param isEnabled true if the user's setting for Voice over Cross SIM is enabled,
5414 * false otherwise
5415 */
5416 @Override
5417 public void setCrossSimCallingEnabled(int subId, boolean isEnabled) {
5418 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5419 "setCrossSimCallingEnabled");
5420 final long identity = Binder.clearCallingIdentity();
5421 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005422 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005423 // This setting doesn't require an active ImsService connection, so do not verify. The
5424 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005425 ImsManager.getInstance(mApp, slotId).setCrossSimCallingEnabled(isEnabled);
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005426 } catch (ImsException e) {
5427 throw new ServiceSpecificException(e.getCode());
5428 } finally {
5429 Binder.restoreCallingIdentity(identity);
5430 }
5431 }
5432
5433 /**
shilu366312e2019-12-17 09:28:10 -08005434 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5435 * @param subId The subscription to use to check the configuration.
5436 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005437 @Override
Nathan Harold62c68512021-04-06 11:26:02 -07005438
Brad Ebinger35c841c2018-10-01 10:40:55 -07005439 public boolean isVoWiFiRoamingSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005440 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005441 mApp, subId, "isVoWiFiRoamingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005442 final long identity = Binder.clearCallingIdentity();
5443 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005444 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005445 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005446 return ImsManager.getInstance(mApp, slotId).isWfcRoamingEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005447 } catch (ImsException e) {
5448 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005449 } finally {
5450 Binder.restoreCallingIdentity(identity);
5451 }
5452 }
5453
5454 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005455 public void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005456 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005457 "setVoWiFiRoamingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005458 final long identity = Binder.clearCallingIdentity();
5459 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005460 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005461 // This setting doesn't require an active ImsService connection, so do not verify. The
5462 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005463 ImsManager.getInstance(mApp, slotId).setWfcRoamingSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005464 } catch (ImsException e) {
5465 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005466 } finally {
5467 Binder.restoreCallingIdentity(identity);
5468 }
5469 }
5470
5471 @Override
5472 public void setVoWiFiNonPersistent(int subId, boolean isCapable, int mode) {
5473 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5474 "setVoWiFiNonPersistent");
5475 final long identity = Binder.clearCallingIdentity();
5476 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005477 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005478 // This setting will be ignored if the ImsService isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005479 ImsManager.getInstance(mApp, slotId).setWfcNonPersistent(isCapable, mode);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005480 } catch (ImsException e) {
5481 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005482 } finally {
5483 Binder.restoreCallingIdentity(identity);
5484 }
5485 }
5486
shilu366312e2019-12-17 09:28:10 -08005487 /**
5488 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5489 * @param subId The subscription to use to check the configuration.
5490 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005491 @Override
5492 public int getVoWiFiModeSetting(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005493 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005494 mApp, subId, "getVoWiFiModeSetting");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005495 final long identity = Binder.clearCallingIdentity();
5496 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005497 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005498 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005499 return ImsManager.getInstance(mApp, slotId).getWfcMode(false /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005500 } catch (ImsException e) {
5501 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005502 } finally {
5503 Binder.restoreCallingIdentity(identity);
5504 }
5505 }
5506
5507 @Override
5508 public void setVoWiFiModeSetting(int subId, int mode) {
5509 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5510 "setVoWiFiModeSetting");
5511 final long identity = Binder.clearCallingIdentity();
5512 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005513 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005514 // This setting doesn't require an active ImsService connection, so do not verify. The
5515 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005516 ImsManager.getInstance(mApp, slotId).setWfcMode(mode, false /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005517 } catch (ImsException e) {
5518 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005519 } finally {
5520 Binder.restoreCallingIdentity(identity);
5521 }
5522 }
5523
5524 @Override
5525 public int getVoWiFiRoamingModeSetting(int subId) {
5526 enforceReadPrivilegedPermission("getVoWiFiRoamingModeSetting");
5527 final long identity = Binder.clearCallingIdentity();
5528 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005529 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005530 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005531 return ImsManager.getInstance(mApp, slotId).getWfcMode(true /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005532 } catch (ImsException e) {
5533 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005534 } finally {
5535 Binder.restoreCallingIdentity(identity);
5536 }
5537 }
5538
5539 @Override
5540 public void setVoWiFiRoamingModeSetting(int subId, int mode) {
5541 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5542 "setVoWiFiRoamingModeSetting");
5543 final long identity = Binder.clearCallingIdentity();
5544 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005545 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005546 // This setting doesn't require an active ImsService connection, so do not verify. The
5547 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005548 ImsManager.getInstance(mApp, slotId).setWfcMode(mode, true /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005549 } catch (ImsException e) {
5550 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005551 } finally {
5552 Binder.restoreCallingIdentity(identity);
5553 }
5554 }
5555
5556 @Override
5557 public void setRttCapabilitySetting(int subId, boolean isEnabled) {
5558 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5559 "setRttCapabilityEnabled");
5560 final long identity = Binder.clearCallingIdentity();
5561 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005562 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005563 // This setting doesn't require an active ImsService connection, so do not verify. The
5564 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005565 ImsManager.getInstance(mApp, slotId).setRttEnabled(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005566 } catch (ImsException e) {
5567 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005568 } finally {
5569 Binder.restoreCallingIdentity(identity);
5570 }
5571 }
5572
shilu366312e2019-12-17 09:28:10 -08005573 /**
5574 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5575 * @param subId The subscription to use to check the configuration.
5576 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005577 @Override
5578 public boolean isTtyOverVolteEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005579 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005580 mApp, subId, "isTtyOverVolteEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005581 final long identity = Binder.clearCallingIdentity();
5582 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005583 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005584 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005585 return ImsManager.getInstance(mApp, slotId).isTtyOnVoLteCapable();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005586 } catch (ImsException e) {
5587 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005588 } finally {
5589 Binder.restoreCallingIdentity(identity);
5590 }
5591 }
5592
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005593 @Override
5594 public void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
5595 enforceReadPrivilegedPermission("registerImsProvisioningChangedCallback");
joonhunshincffb7fc2021-11-28 07:32:01 +00005596
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005597 final long identity = Binder.clearCallingIdentity();
5598 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005599 if (!isImsAvailableOnDevice()) {
5600 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5601 "IMS not available on device.");
5602 }
5603 int slotId = getSlotIndexOrException(subId);
5604 verifyImsMmTelConfiguredOrThrow(slotId);
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005605
5606 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5607 if (controller != null) {
5608 ImsManager imsManager = controller.getImsManager(subId);
5609 if (imsManager != null) {
5610 imsManager.addProvisioningCallbackForSubscription(callback, subId);
5611 } else {
5612 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
5613 }
5614 } else {
5615 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5616 }
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005617 } catch (ImsException e) {
5618 throw new ServiceSpecificException(e.getCode());
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005619 } finally {
5620 Binder.restoreCallingIdentity(identity);
5621 }
5622 }
5623
5624 @Override
5625 public void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
5626 enforceReadPrivilegedPermission("unregisterImsProvisioningChangedCallback");
joonhunshincffb7fc2021-11-28 07:32:01 +00005627
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005628 final long identity = Binder.clearCallingIdentity();
Brad Ebinger4ae57f92019-01-09 16:51:30 -08005629 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5630 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5631 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005632 try {
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005633 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5634 if (controller != null) {
5635 ImsManager imsManager = controller.getImsManager(subId);
5636 if (imsManager != null) {
5637 imsManager.removeProvisioningCallbackForSubscription(callback, subId);
5638 } else {
5639 Log.i(LOG_TAG, "unregisterImsProvisioningChangedCallback: " + subId
5640 + " is inactive, ignoring unregister.");
5641 // If the ImsManager is not valid, just return, since the callback will already
5642 // have been removed internally.
5643 }
5644 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005645 } finally {
5646 Binder.restoreCallingIdentity(identity);
5647 }
5648 }
5649
joonhunshincffb7fc2021-11-28 07:32:01 +00005650 @Override
5651 public void registerFeatureProvisioningChangedCallback(int subId,
5652 IFeatureProvisioningCallback callback) {
5653 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5654 mApp, subId, "registerFeatureProvisioningChangedCallback");
5655
5656 final long identity = Binder.clearCallingIdentity();
5657 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5658 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5659 }
5660
joonhunshin91bc1952022-04-29 08:47:15 +00005661 try {
5662 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5663 if (controller == null) {
5664 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5665 "Device does not support IMS");
5666 }
5667 controller.addFeatureProvisioningChangedCallback(subId, callback);
5668 } finally {
5669 Binder.restoreCallingIdentity(identity);
5670 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005671 }
5672
5673 @Override
5674 public void unregisterFeatureProvisioningChangedCallback(int subId,
5675 IFeatureProvisioningCallback callback) {
5676 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5677 mApp, subId, "unregisterFeatureProvisioningChangedCallback");
5678
5679 final long identity = Binder.clearCallingIdentity();
5680 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5681 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5682 }
5683
joonhunshin91bc1952022-04-29 08:47:15 +00005684 try {
5685 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5686 if (controller == null) {
5687 loge("unregisterFeatureProvisioningChangedCallback: Device does not support IMS");
5688 return;
5689 }
5690 controller.removeFeatureProvisioningChangedCallback(subId, callback);
5691 } finally {
5692 Binder.restoreCallingIdentity(identity);
5693 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005694 }
allenwtsu99c623b2020-01-03 18:24:23 +08005695
5696 private void checkModifyPhoneStatePermission(int subId, String message) {
5697 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5698 message);
5699 }
5700
allenwtsu99c623b2020-01-03 18:24:23 +08005701 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005702 public void setRcsProvisioningStatusForCapability(int subId, int capability, int tech,
allenwtsu99c623b2020-01-03 18:24:23 +08005703 boolean isProvisioned) {
5704 checkModifyPhoneStatePermission(subId, "setRcsProvisioningStatusForCapability");
5705
5706 final long identity = Binder.clearCallingIdentity();
5707 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005708 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5709 if (controller == null) {
5710 loge("setRcsProvisioningStatusForCapability: Device does not support IMS");
5711 return;
5712 }
5713 controller.setRcsProvisioningStatusForCapability(
5714 subId, capability, tech, isProvisioned);
allenwtsu99c623b2020-01-03 18:24:23 +08005715 } finally {
5716 Binder.restoreCallingIdentity(identity);
5717 }
allenwtsu99c623b2020-01-03 18:24:23 +08005718 }
5719
5720
5721 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005722 public boolean getRcsProvisioningStatusForCapability(int subId, int capability, int tech) {
5723 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5724 mApp, subId, "getRcsProvisioningStatusForCapability");
5725
allenwtsu99c623b2020-01-03 18:24:23 +08005726 final long identity = Binder.clearCallingIdentity();
5727 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005728 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5729 if (controller == null) {
5730 loge("getRcsProvisioningStatusForCapability: Device does not support IMS");
5731
5732 // device does not support IMS, this method will return true always.
5733 return true;
5734 }
5735 return controller.getRcsProvisioningStatusForCapability(subId, capability, tech);
allenwtsu99c623b2020-01-03 18:24:23 +08005736 } finally {
5737 Binder.restoreCallingIdentity(identity);
5738 }
5739 }
5740
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005741 @Override
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005742 public void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
5743 boolean isProvisioned) {
allenwtsu99c623b2020-01-03 18:24:23 +08005744 checkModifyPhoneStatePermission(subId, "setImsProvisioningStatusForCapability");
joonhunshincffb7fc2021-11-28 07:32:01 +00005745
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005746 final long identity = Binder.clearCallingIdentity();
5747 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005748 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5749 if (controller == null) {
5750 loge("setImsProvisioningStatusForCapability: Device does not support IMS");
5751 return;
5752 }
5753 controller.setImsProvisioningStatusForCapability(
5754 subId, capability, tech, isProvisioned);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005755 } finally {
5756 Binder.restoreCallingIdentity(identity);
5757 }
5758 }
5759
5760 @Override
5761 public boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech) {
joonhunshincffb7fc2021-11-28 07:32:01 +00005762 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5763 mApp, subId, "getProvisioningStatusForCapability");
5764
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005765 final long identity = Binder.clearCallingIdentity();
5766 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005767 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5768 if (controller == null) {
5769 loge("getImsProvisioningStatusForCapability: Device does not support IMS");
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005770
joonhunshin91bc1952022-04-29 08:47:15 +00005771 // device does not support IMS, this method will return true always.
5772 return true;
5773 }
5774 return controller.getImsProvisioningStatusForCapability(subId, capability, tech);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005775 } finally {
5776 Binder.restoreCallingIdentity(identity);
5777 }
5778 }
5779
5780 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005781 public boolean isProvisioningRequiredForCapability(int subId, int capability, int tech) {
5782 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5783 mApp, subId, "isProvisioningRequiredForCapability");
5784
5785 final long identity = Binder.clearCallingIdentity();
5786 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005787 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5788 if (controller == null) {
5789 loge("isProvisioningRequiredForCapability: Device does not support IMS");
5790
5791 // device does not support IMS, this method will return false
5792 return false;
5793 }
5794 return controller.isImsProvisioningRequiredForCapability(subId, capability, tech);
joonhunshincffb7fc2021-11-28 07:32:01 +00005795 } finally {
5796 Binder.restoreCallingIdentity(identity);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005797 }
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005798 }
5799
5800 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005801 public boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech) {
5802 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5803 mApp, subId, "isProvisioningRequiredForCapability");
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005804
joonhunshincffb7fc2021-11-28 07:32:01 +00005805 final long identity = Binder.clearCallingIdentity();
5806 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005807 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5808 if (controller == null) {
5809 loge("isRcsProvisioningRequiredForCapability: Device does not support IMS");
5810
5811 // device does not support IMS, this method will return false
5812 return false;
5813 }
5814 return controller.isRcsProvisioningRequiredForCapability(subId, capability, tech);
joonhunshincffb7fc2021-11-28 07:32:01 +00005815 } finally {
5816 Binder.restoreCallingIdentity(identity);
5817 }
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005818 }
5819
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005820 @Override
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005821 public int getImsProvisioningInt(int subId, int key) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005822 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5823 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5824 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005825 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5826 mApp, subId, "getImsProvisioningInt");
5827
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005828 final long identity = Binder.clearCallingIdentity();
5829 try {
5830 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005831 int slotId = getSlotIndex(subId);
5832 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5833 Log.w(LOG_TAG, "getImsProvisioningInt: called with an inactive subscription '"
5834 + subId + "' for key:" + key);
5835 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
5836 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005837
joonhunshin91bc1952022-04-29 08:47:15 +00005838 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5839 if (controller == null) {
5840 loge("getImsProvisioningInt: Device does not support IMS");
5841
5842 // device does not support IMS, this method will return CONFIG_RESULT_UNKNOWN.
5843 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
5844 }
5845 int retVal = controller.getProvisioningValue(subId, key);
joonhunshincffb7fc2021-11-28 07:32:01 +00005846 if (retVal != ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
5847 return retVal;
5848 }
5849
calvinpanb5a34062021-02-08 19:59:36 +08005850 return ImsManager.getInstance(mApp, slotId).getConfigInt(key);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005851 } catch (com.android.ims.ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005852 Log.w(LOG_TAG, "getImsProvisioningInt: ImsService is not available for subscription '"
5853 + subId + "' for key:" + key);
5854 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005855 } finally {
5856 Binder.restoreCallingIdentity(identity);
5857 }
5858 }
5859
5860 @Override
5861 public String getImsProvisioningString(int subId, int key) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005862 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5863 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5864 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005865 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5866 mApp, subId, "getImsProvisioningString");
5867
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005868 final long identity = Binder.clearCallingIdentity();
5869 try {
5870 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005871 int slotId = getSlotIndex(subId);
5872 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5873 Log.w(LOG_TAG, "getImsProvisioningString: called for an inactive subscription id '"
5874 + subId + "' for key:" + key);
5875 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_GENERIC;
5876 }
calvinpanb5a34062021-02-08 19:59:36 +08005877 return ImsManager.getInstance(mApp, slotId).getConfigString(key);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005878 } catch (com.android.ims.ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005879 Log.w(LOG_TAG, "getImsProvisioningString: ImsService is not available for sub '"
5880 + subId + "' for key:" + key);
5881 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_NOT_READY;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005882 } finally {
5883 Binder.restoreCallingIdentity(identity);
5884 }
5885 }
5886
5887 @Override
5888 public int setImsProvisioningInt(int subId, int key, int value) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005889 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5890 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5891 }
Brad Ebinger3d0b34e2018-11-15 14:13:12 -08005892 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5893 "setImsProvisioningInt");
joonhunshincffb7fc2021-11-28 07:32:01 +00005894
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005895 final long identity = Binder.clearCallingIdentity();
5896 try {
5897 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005898 int slotId = getSlotIndex(subId);
5899 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5900 Log.w(LOG_TAG, "setImsProvisioningInt: called with an inactive subscription id '"
5901 + subId + "' for key:" + key);
5902 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
5903 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005904
joonhunshin91bc1952022-04-29 08:47:15 +00005905 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5906 if (controller == null) {
5907 loge("setImsProvisioningInt: Device does not support IMS");
5908
5909 // device does not support IMS, this method will return CONFIG_RESULT_FAILED.
5910 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
5911 }
5912 int retVal = controller.setProvisioningValue(subId, key, value);
joonhunshincffb7fc2021-11-28 07:32:01 +00005913 if (retVal != ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
5914 return retVal;
5915 }
5916
calvinpanb5a34062021-02-08 19:59:36 +08005917 return ImsManager.getInstance(mApp, slotId).setConfig(key, value);
5918 } catch (com.android.ims.ImsException | RemoteException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005919 Log.w(LOG_TAG, "setImsProvisioningInt: ImsService unavailable for sub '" + subId
calvinpanb5a34062021-02-08 19:59:36 +08005920 + "' for key:" + key, e);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005921 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005922 } finally {
5923 Binder.restoreCallingIdentity(identity);
5924 }
5925 }
5926
5927 @Override
5928 public int setImsProvisioningString(int subId, int key, String value) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005929 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5930 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5931 }
Brad Ebinger3d0b34e2018-11-15 14:13:12 -08005932 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5933 "setImsProvisioningString");
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005934 final long identity = Binder.clearCallingIdentity();
5935 try {
5936 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005937 int slotId = getSlotIndex(subId);
5938 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5939 Log.w(LOG_TAG, "setImsProvisioningString: called with an inactive subscription id '"
5940 + subId + "' for key:" + key);
5941 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
5942 }
calvinpanb5a34062021-02-08 19:59:36 +08005943 return ImsManager.getInstance(mApp, slotId).setConfig(key, value);
5944 } catch (com.android.ims.ImsException | RemoteException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005945 Log.w(LOG_TAG, "setImsProvisioningString: ImsService unavailable for sub '" + subId
calvinpanb5a34062021-02-08 19:59:36 +08005946 + "' for key:" + key, e);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005947 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005948 } finally {
5949 Binder.restoreCallingIdentity(identity);
5950 }
5951 }
5952
Brad Ebinger919631e2021-06-02 17:46:35 -07005953 /**
5954 * Throw an ImsException if the IMS resolver does not have an ImsService configured for MMTEL
5955 * for the given slot ID or no ImsResolver instance has been created.
5956 * @param slotId The slot ID that the IMS service is created for.
5957 * @throws ImsException If there is no ImsService configured for this slot.
5958 */
5959 private void verifyImsMmTelConfiguredOrThrow(int slotId) throws ImsException {
5960 if (mImsResolver == null || !mImsResolver.isImsServiceConfiguredForFeature(slotId,
5961 ImsFeature.FEATURE_MMTEL)) {
5962 throw new ImsException("This subscription does not support MMTEL over IMS",
5963 ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5964 }
5965 }
5966
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005967 private int getSlotIndexOrException(int subId) throws ImsException {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005968 int slotId = SubscriptionManager.getSlotIndex(subId);
5969 if (!SubscriptionManager.isValidSlotIndex(slotId)) {
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005970 throw new ImsException("Invalid Subscription Id, subId=" + subId,
5971 ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
Brad Ebinger35c841c2018-10-01 10:40:55 -07005972 }
5973 return slotId;
5974 }
5975
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005976 private int getSlotIndex(int subId) {
5977 int slotId = SubscriptionManager.getSlotIndex(subId);
5978 if (!SubscriptionManager.isValidSlotIndex(slotId)) {
5979 return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
5980 }
5981 return slotId;
5982 }
5983
Wink Saville36469e72014-06-11 15:17:00 -07005984 /**
Nathan Harold9042f0b2019-05-21 15:51:27 -07005985 * Returns the data network type for a subId; does not throw SecurityException.
Wink Saville36469e72014-06-11 15:17:00 -07005986 */
5987 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07005988 public int getNetworkTypeForSubscriber(int subId, String callingPackage,
5989 String callingFeatureId) {
Shuo Qian13d89152021-05-10 23:58:11 -07005990 try {
5991 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
5992 } catch (SecurityException se) {
5993 EventLog.writeEvent(0x534e4554, "186776740", Binder.getCallingUid());
5994 throw new SecurityException("Package " + callingPackage + " does not belong to "
5995 + Binder.getCallingUid());
5996 }
Nathan Haroldf096d982020-11-18 17:18:06 -08005997 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Haroldef60dba2019-05-22 13:55:14 -07005998 if (targetSdk > android.os.Build.VERSION_CODES.Q) {
Philip P. Moltmann700a9592019-10-03 11:53:50 -07005999 return getDataNetworkTypeForSubscriber(subId, callingPackage, callingFeatureId);
Nathan Haroldef60dba2019-05-22 13:55:14 -07006000 } else if (targetSdk == android.os.Build.VERSION_CODES.Q
Nathan Harold9042f0b2019-05-21 15:51:27 -07006001 && !TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006002 mApp, subId, callingPackage, callingFeatureId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006003 "getNetworkTypeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006004 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6005 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07006006
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006007 final long identity = Binder.clearCallingIdentity();
6008 try {
6009 final Phone phone = getPhone(subId);
6010 if (phone != null) {
6011 return phone.getServiceState().getDataNetworkType();
6012 } else {
6013 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6014 }
6015 } finally {
6016 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006017 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006018 }
6019
6020 /**
6021 * Returns the data network type
6022 */
6023 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006024 public int getDataNetworkType(String callingPackage, String callingFeatureId) {
Jack Yu285100e2022-12-02 22:48:35 -08006025 return getDataNetworkTypeForSubscriber(SubscriptionManager.getDefaultDataSubscriptionId(),
Zoey Chenfd61f7f2021-04-21 13:42:10 +08006026 callingPackage, callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07006027 }
6028
6029 /**
6030 * Returns the data network type for a subId
6031 */
6032 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006033 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage,
6034 String callingFeatureId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07006035 String functionName = "getDataNetworkTypeForSubscriber";
6036 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
6037 mApp, functionName)) {
6038 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6039 mApp, subId, callingPackage, callingFeatureId, functionName)) {
6040 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6041 }
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006042 }
6043
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006044 final long identity = Binder.clearCallingIdentity();
6045 try {
6046 final Phone phone = getPhone(subId);
6047 if (phone != null) {
6048 return phone.getServiceState().getDataNetworkType();
6049 } else {
6050 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6051 }
6052 } finally {
6053 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006054 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006055 }
6056
6057 /**
Wink Saville36469e72014-06-11 15:17:00 -07006058 * Returns the Voice network type for a subId
6059 */
6060 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006061 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage,
6062 String callingFeatureId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07006063 String functionName = "getVoiceNetworkTypeForSubscriber";
6064 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
6065 mApp, functionName)) {
6066 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6067 mApp, subId, callingPackage, callingFeatureId, functionName)) {
6068 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6069 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07006070 }
6071
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006072 final long identity = Binder.clearCallingIdentity();
6073 try {
6074 final Phone phone = getPhone(subId);
6075 if (phone != null) {
6076 return phone.getServiceState().getVoiceNetworkType();
6077 } else {
6078 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6079 }
6080 } finally {
6081 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006082 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006083 }
6084
6085 /**
6086 * @return true if a ICC card is present
6087 */
6088 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07006089 // FIXME Make changes to pass defaultSimId of type int
Jack Yu285100e2022-12-02 22:48:35 -08006090 return hasIccCardUsingSlotIndex(SubscriptionManager.getSlotIndex(
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006091 getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -07006092 }
6093
6094 /**
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006095 * @return true if a ICC card is present for a slotIndex
Wink Saville36469e72014-06-11 15:17:00 -07006096 */
Sanket Padawe356d7632015-06-22 14:03:32 -07006097 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006098 public boolean hasIccCardUsingSlotIndex(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006099 final long identity = Binder.clearCallingIdentity();
6100 try {
6101 final Phone phone = PhoneFactory.getPhone(slotIndex);
6102 if (phone != null) {
6103 return phone.getIccCard().hasIccCard();
6104 } else {
6105 return false;
6106 }
6107 } finally {
6108 Binder.restoreCallingIdentity(identity);
Amit Mahajana6fc2a82015-01-06 11:53:51 -08006109 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006110 }
6111
6112 /**
6113 * Return if the current radio is LTE on CDMA. This
6114 * is a tri-state return value as for a period of time
6115 * the mode may be unknown.
6116 *
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006117 * @param callingPackage the name of the package making the call.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006118 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08006119 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006120 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006121 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006122 public int getLteOnCdmaMode(String callingPackage, String callingFeatureId) {
6123 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage,
6124 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07006125 }
6126
Sanket Padawe356d7632015-06-22 14:03:32 -07006127 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006128 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage,
6129 String callingFeatureId) {
Sarah Chin790d2922020-01-16 12:17:23 -08006130 try {
6131 enforceReadPrivilegedPermission("getLteOnCdmaModeForSubscriber");
6132 } catch (SecurityException e) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006133 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
6134 }
6135
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006136 final long identity = Binder.clearCallingIdentity();
6137 try {
6138 final Phone phone = getPhone(subId);
6139 if (phone == null) {
6140 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
6141 } else {
Nathan Harold05ad6332020-07-10 11:54:36 -07006142 return TelephonyProperties.lte_on_cdma_device()
6143 .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006144 }
6145 } finally {
6146 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006147 }
Wink Saville36469e72014-06-11 15:17:00 -07006148 }
6149
Wink Saville36469e72014-06-11 15:17:00 -07006150 /**
6151 * {@hide}
6152 * Returns Default subId, 0 in the case of single standby.
6153 */
Wink Savilleb564aae2014-10-23 10:18:09 -07006154 private int getDefaultSubscription() {
Jack Yu285100e2022-12-02 22:48:35 -08006155 return SubscriptionManager.getDefaultSubscriptionId();
Wink Saville36469e72014-06-11 15:17:00 -07006156 }
6157
Shishir Agrawala9f32182016-04-12 12:00:16 -07006158 private int getSlotForDefaultSubscription() {
Jack Yu285100e2022-12-02 22:48:35 -08006159 return SubscriptionManager.getPhoneId(getDefaultSubscription());
Shishir Agrawala9f32182016-04-12 12:00:16 -07006160 }
6161
Wink Savilleb564aae2014-10-23 10:18:09 -07006162 private int getPreferredVoiceSubscription() {
Jack Yu285100e2022-12-02 22:48:35 -08006163 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006164 }
Ihab Awadf2177b72013-11-25 13:33:23 -08006165
Pengquan Menge92a50d2018-09-21 15:54:48 -07006166 private boolean isActiveSubscription(int subId) {
Jack Yu285100e2022-12-02 22:48:35 -08006167 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08006168 return getSubscriptionManagerService().isActiveSubId(subId,
Jack Yu285100e2022-12-02 22:48:35 -08006169 mApp.getOpPackageName(), mApp.getFeatureId());
6170 }
Pengquan Menge92a50d2018-09-21 15:54:48 -07006171 return mSubscriptionController.isActiveSubId(subId);
6172 }
6173
Ihab Awadf2177b72013-11-25 13:33:23 -08006174 /**
6175 * @see android.telephony.TelephonyManager.WifiCallingChoices
6176 */
6177 public int getWhenToMakeWifiCalls() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006178 final long identity = Binder.clearCallingIdentity();
6179 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006180 return Settings.System.getInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006181 Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
6182 getWhenToMakeWifiCallsDefaultPreference());
6183 } finally {
6184 Binder.restoreCallingIdentity(identity);
6185 }
Ihab Awadf2177b72013-11-25 13:33:23 -08006186 }
6187
6188 /**
6189 * @see android.telephony.TelephonyManager.WifiCallingChoices
6190 */
6191 public void setWhenToMakeWifiCalls(int preference) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006192 final long identity = Binder.clearCallingIdentity();
6193 try {
6194 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006195 Settings.System.putInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006196 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
6197 } finally {
6198 Binder.restoreCallingIdentity(identity);
6199 }
Ihab Awadf9e92732013-12-05 18:02:52 -08006200 }
6201
Sailesh Nepald1e68152013-12-12 19:08:02 -08006202 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07006203 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08006204 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08006205 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08006206
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006207 private Phone getPhoneFromSlotPortIndexOrThrowException(int slotIndex, int portIndex) {
6208 int phoneId = UiccController.getInstance().getPhoneIdFromSlotPortIndex(slotIndex,
6209 portIndex);
Jordan Liu4c733742019-02-28 12:03:40 -08006210 if (phoneId == -1) {
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006211 throw new IllegalArgumentException("Given slot index: " + slotIndex + " port index: "
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006212 + portIndex + " does not correspond to an active phone");
Jordan Liu4c733742019-02-28 12:03:40 -08006213 }
6214 return PhoneFactory.getPhone(phoneId);
6215 }
6216
Shishir Agrawal566b7612013-10-28 14:41:00 -07006217 @Override
Derek Tan740e1672017-06-27 14:56:27 -07006218 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
Rambo Wanga1782702021-11-10 20:15:19 -08006219 @NonNull IccLogicalChannelRequest request) {
6220 Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
6221 /*message=*/ "iccOpenLogicalChannel");
6222
6223 if (DBG) log("iccOpenLogicalChannel: request=" + request);
6224 // Verify that the callingPackage in the request belongs to the calling UID
6225 mAppOps.checkPackage(Binder.getCallingUid(), request.callingPackage);
6226
6227 return iccOpenLogicalChannelWithPermission(phone, request);
Jordan Liu4c733742019-02-28 12:03:40 -08006228 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006229
Rambo Wanga1782702021-11-10 20:15:19 -08006230 private Phone getPhoneFromValidIccLogicalChannelRequest(
6231 @NonNull IccLogicalChannelRequest request, String message) {
6232 Phone phone;
6233 if (request.subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
6234 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6235 mApp, request.subId, message);
6236 phone = getPhoneFromSubId(request.subId);
6237 } else if (request.slotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
6238 enforceModifyPermission();
6239 phone = getPhoneFromSlotPortIndexOrThrowException(request.slotIndex, request.portIndex);
6240 } else {
6241 throw new IllegalArgumentException("Both subId and slotIndex in request are invalid.");
Jordan Liu4c733742019-02-28 12:03:40 -08006242 }
Rambo Wanga1782702021-11-10 20:15:19 -08006243 return phone;
Jordan Liu4c733742019-02-28 12:03:40 -08006244 }
6245
6246 private IccOpenLogicalChannelResponse iccOpenLogicalChannelWithPermission(Phone phone,
Rambo Wanga1782702021-11-10 20:15:19 -08006247 IccLogicalChannelRequest channelRequest) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006248 final long identity = Binder.clearCallingIdentity();
6249 try {
Rambo Wanga1782702021-11-10 20:15:19 -08006250 if (TextUtils.equals(ISDR_AID, channelRequest.aid)) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006251 // Only allows LPA to open logical channel to ISD-R.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006252 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
6253 .getContext().getPackageManager());
Rambo Wanga1782702021-11-10 20:15:19 -08006254 if (bestComponent == null || !TextUtils.equals(channelRequest.callingPackage,
6255 bestComponent.packageName)) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006256 loge("The calling package is not allowed to access ISD-R.");
6257 throw new SecurityException(
6258 "The calling package is not allowed to access ISD-R.");
6259 }
Derek Tan740e1672017-06-27 14:56:27 -07006260 }
Derek Tan740e1672017-06-27 14:56:27 -07006261
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006262 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse) sendRequest(
Rambo Wanga1782702021-11-10 20:15:19 -08006263 CMD_OPEN_CHANNEL, channelRequest, phone, null /* workSource */);
6264 if (DBG) log("iccOpenLogicalChannelWithPermission: response=" + response);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006265 return response;
6266 } finally {
6267 Binder.restoreCallingIdentity(identity);
6268 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006269 }
6270
6271 @Override
Rambo Wanga1782702021-11-10 20:15:19 -08006272 public boolean iccCloseLogicalChannel(@NonNull IccLogicalChannelRequest request) {
6273 Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
6274 /*message=*/"iccCloseLogicalChannel");
6275
6276 if (DBG) log("iccCloseLogicalChannel: request=" + request);
6277
6278 return iccCloseLogicalChannelWithPermission(phone, request);
Jordan Liu4c733742019-02-28 12:03:40 -08006279 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006280
Rambo Wanga1782702021-11-10 20:15:19 -08006281 private boolean iccCloseLogicalChannelWithPermission(Phone phone,
6282 IccLogicalChannelRequest request) {
Chen Xua8f0dff2022-02-12 00:34:15 -08006283 // before this feature is enabled, this API should only return false if
6284 // the operation fails instead of throwing runtime exception for
6285 // backward-compatibility.
6286 final boolean shouldThrowExceptionOnFailure = CompatChanges.isChangeEnabled(
6287 ICC_CLOSE_CHANNEL_EXCEPTION_ON_FAILURE, Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006288 final long identity = Binder.clearCallingIdentity();
6289 try {
Rambo Wanga1782702021-11-10 20:15:19 -08006290 if (request.channel < 0) {
Chen Xu540470b2021-12-14 17:15:47 -08006291 throw new IllegalArgumentException("request.channel is less than 0");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006292 }
Chen Xue9d737e2022-01-01 23:41:31 -08006293 Object result = sendRequest(CMD_CLOSE_CHANNEL, request.channel, phone,
Jordan Liu4c733742019-02-28 12:03:40 -08006294 null /* workSource */);
Chen Xue9d737e2022-01-01 23:41:31 -08006295 Boolean success = false;
6296 if (result instanceof RuntimeException) {
6297 // if there is an exception returned, throw from the binder thread here.
Chen Xua8f0dff2022-02-12 00:34:15 -08006298 if (shouldThrowExceptionOnFailure) {
6299 throw (RuntimeException) result;
6300 } else {
6301 return false;
6302 }
Chen Xue9d737e2022-01-01 23:41:31 -08006303 } else if (result instanceof Boolean) {
6304 success = (Boolean) result;
6305 } else {
6306 loge("iccCloseLogicalChannelWithPermission: supported return type " + result);
6307 }
Rambo Wanga1782702021-11-10 20:15:19 -08006308 if (DBG) log("iccCloseLogicalChannelWithPermission: success=" + success);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006309 return success;
6310 } finally {
6311 Binder.restoreCallingIdentity(identity);
Shishir Agrawal566b7612013-10-28 14:41:00 -07006312 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006313 }
6314
6315 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08006316 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
Shishir Agrawal566b7612013-10-28 14:41:00 -07006317 int command, int p1, int p2, int p3, String data) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006318 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6319 mApp, subId, "iccTransmitApduLogicalChannel");
Jordan Liu4c733742019-02-28 12:03:40 -08006320 if (DBG) {
6321 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
6322 + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
6323 + p3 + " data=" + data);
6324 }
6325 return iccTransmitApduLogicalChannelWithPermission(getPhoneFromSubId(subId), channel, cla,
6326 command, p1, p2, p3, data);
6327 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006328
Jordan Liu4c733742019-02-28 12:03:40 -08006329 @Override
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006330 public String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel,
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006331 int cla, int command, int p1, int p2, int p3, String data) {
Jordan Liu4c733742019-02-28 12:03:40 -08006332 enforceModifyPermission();
6333 if (DBG) {
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006334 log("iccTransmitApduLogicalChannelByPort: slotIndex=" + slotIndex + " portIndex="
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006335 + portIndex + " chnl=" + channel + " cla=" + cla + " cmd=" + command + " p1="
6336 + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
Jordan Liu4c733742019-02-28 12:03:40 -08006337 }
6338 return iccTransmitApduLogicalChannelWithPermission(
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006339 getPhoneFromSlotPortIndexOrThrowException(slotIndex, portIndex), channel, cla,
6340 command, p1, p2, p3, data);
Jordan Liu4c733742019-02-28 12:03:40 -08006341 }
6342
6343 private String iccTransmitApduLogicalChannelWithPermission(Phone phone, int channel, int cla,
6344 int command, int p1, int p2, int p3, String data) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006345 final long identity = Binder.clearCallingIdentity();
6346 try {
Hall Liu4fd771b2019-05-02 09:16:29 -07006347 if (channel <= 0) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006348 return "";
6349 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006350
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006351 IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Jordan Liu4c733742019-02-28 12:03:40 -08006352 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), phone,
6353 null /* workSource */);
6354 if (DBG) log("iccTransmitApduLogicalChannelWithPermission: " + response);
Shishir Agrawal566b7612013-10-28 14:41:00 -07006355
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006356 // Append the returned status code to the end of the response payload.
6357 String s = Integer.toHexString(
6358 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
6359 if (response.payload != null) {
6360 s = IccUtils.bytesToHexString(response.payload) + s;
6361 }
6362 return s;
6363 } finally {
6364 Binder.restoreCallingIdentity(identity);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07006365 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006366 }
Jake Hambye994d462014-02-03 13:10:13 -08006367
Evan Charltonc66da362014-05-16 14:06:40 -07006368 @Override
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08006369 public String iccTransmitApduBasicChannel(int subId, String callingPackage, int cla,
6370 int command, int p1, int p2, int p3, String data) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006371 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6372 mApp, subId, "iccTransmitApduBasicChannel");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006373 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jordan Liu4c733742019-02-28 12:03:40 -08006374 if (DBG) {
6375 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
6376 + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
6377 }
6378 return iccTransmitApduBasicChannelWithPermission(getPhoneFromSubId(subId), callingPackage,
6379 cla, command, p1, p2, p3, data);
6380 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006381
Jordan Liu4c733742019-02-28 12:03:40 -08006382 @Override
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006383 public String iccTransmitApduBasicChannelByPort(int slotIndex, int portIndex,
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006384 String callingPackage, int cla, int command, int p1, int p2, int p3, String data) {
Jordan Liu4c733742019-02-28 12:03:40 -08006385 enforceModifyPermission();
6386 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
6387 if (DBG) {
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006388 log("iccTransmitApduBasicChannelByPort: slotIndex=" + slotIndex + " portIndex="
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006389 + portIndex + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2="
6390 + p2 + " p3=" + p3 + " data=" + data);
Jordan Liu4c733742019-02-28 12:03:40 -08006391 }
6392
6393 return iccTransmitApduBasicChannelWithPermission(
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006394 getPhoneFromSlotPortIndexOrThrowException(slotIndex, portIndex), callingPackage,
6395 cla, command, p1, p2, p3, data);
Jordan Liu4c733742019-02-28 12:03:40 -08006396 }
6397
6398 // open APDU basic channel assuming the caller has sufficient permissions
6399 private String iccTransmitApduBasicChannelWithPermission(Phone phone, String callingPackage,
6400 int cla, int command, int p1, int p2, int p3, String data) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006401 final long identity = Binder.clearCallingIdentity();
6402 try {
6403 if (command == SELECT_COMMAND && p1 == SELECT_P1 && p2 == SELECT_P2 && p3 == SELECT_P3
6404 && TextUtils.equals(ISDR_AID, data)) {
6405 // Only allows LPA to select ISD-R.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006406 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
6407 .getContext().getPackageManager());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006408 if (bestComponent == null
6409 || !TextUtils.equals(callingPackage, bestComponent.packageName)) {
6410 loge("The calling package is not allowed to select ISD-R.");
6411 throw new SecurityException(
6412 "The calling package is not allowed to select ISD-R.");
6413 }
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08006414 }
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08006415
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006416 IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
Jordan Liu4c733742019-02-28 12:03:40 -08006417 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), phone,
6418 null /* workSource */);
6419 if (DBG) log("iccTransmitApduBasicChannelWithPermission: " + response);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006420
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006421 // Append the returned status code to the end of the response payload.
6422 String s = Integer.toHexString(
6423 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
6424 if (response.payload != null) {
6425 s = IccUtils.bytesToHexString(response.payload) + s;
6426 }
6427 return s;
6428 } finally {
6429 Binder.restoreCallingIdentity(identity);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07006430 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006431 }
6432
6433 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08006434 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006435 String filePath) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006436 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6437 mApp, subId, "iccExchangeSimIO");
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006438
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006439 final long identity = Binder.clearCallingIdentity();
6440 try {
6441 if (DBG) {
6442 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " "
6443 + p1 + " " + p2 + " " + p3 + ":" + filePath);
6444 }
6445
6446 IccIoResult response =
6447 (IccIoResult) sendRequest(CMD_EXCHANGE_SIM_IO,
6448 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
6449 subId);
6450
6451 if (DBG) {
6452 log("Exchange SIM_IO [R]" + response);
6453 }
6454
6455 byte[] result = null;
6456 int length = 2;
6457 if (response.payload != null) {
6458 length = 2 + response.payload.length;
6459 result = new byte[length];
6460 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
6461 } else {
6462 result = new byte[length];
6463 }
6464
6465 result[length - 1] = (byte) response.sw2;
6466 result[length - 2] = (byte) response.sw1;
6467 return result;
6468 } finally {
6469 Binder.restoreCallingIdentity(identity);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006470 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006471 }
6472
Nathan Haroldb3014052017-01-25 15:57:32 -08006473 /**
6474 * Get the forbidden PLMN List from the given app type (ex APPTYPE_USIM)
6475 * on a particular subscription
6476 */
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006477 public String[] getForbiddenPlmns(int subId, int appType, String callingPackage,
6478 String callingFeatureId) {
sqianb6e41952018-03-12 14:54:01 -07006479 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006480 mApp, subId, callingPackage, callingFeatureId, "getForbiddenPlmns")) {
sqianb6e41952018-03-12 14:54:01 -07006481 return null;
6482 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006483
6484 final long identity = Binder.clearCallingIdentity();
6485 try {
6486 if (appType != TelephonyManager.APPTYPE_USIM
6487 && appType != TelephonyManager.APPTYPE_SIM) {
6488 loge("getForbiddenPlmnList(): App Type must be USIM or SIM");
6489 return null;
6490 }
6491 Object response = sendRequest(
6492 CMD_GET_FORBIDDEN_PLMNS, new Integer(appType), subId);
6493 if (response instanceof String[]) {
6494 return (String[]) response;
6495 }
yincheng zhao2737e882019-09-06 17:06:54 -07006496 // Response is an Exception of some kind
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006497 // which is signalled to the user as a NULL retval
Nathan Haroldb3014052017-01-25 15:57:32 -08006498 return null;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006499 } finally {
6500 Binder.restoreCallingIdentity(identity);
Nathan Haroldb3014052017-01-25 15:57:32 -08006501 }
Nathan Haroldb3014052017-01-25 15:57:32 -08006502 }
6503
yincheng zhao2737e882019-09-06 17:06:54 -07006504 /**
6505 * Set the forbidden PLMN list from the given app type (ex APPTYPE_USIM) on a particular
6506 * subscription.
6507 *
6508 * @param subId the id of the subscription.
6509 * @param appType the uicc app type, must be USIM or SIM.
6510 * @param fplmns the Forbiden plmns list that needed to be written to the SIM.
6511 * @param callingPackage the op Package name.
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006512 * @param callingFeatureId the feature in the package.
yincheng zhao2737e882019-09-06 17:06:54 -07006513 * @return number of fplmns that is successfully written to the SIM.
6514 */
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006515 public int setForbiddenPlmns(int subId, int appType, List<String> fplmns, String callingPackage,
6516 String callingFeatureId) {
Jayachandran C5b0d75a2021-10-21 22:15:27 -07006517 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6518 mApp, subId, "setForbiddenPlmns");
6519
yincheng zhao2737e882019-09-06 17:06:54 -07006520 if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
6521 loge("setForbiddenPlmnList(): App Type must be USIM or SIM");
6522 throw new IllegalArgumentException("Invalid appType: App Type must be USIM or SIM");
6523 }
6524 if (fplmns == null) {
6525 throw new IllegalArgumentException("Fplmn List provided is null");
6526 }
6527 for (String fplmn : fplmns) {
6528 if (!CellIdentity.isValidPlmn(fplmn)) {
6529 throw new IllegalArgumentException("Invalid fplmn provided: " + fplmn);
6530 }
6531 }
6532 final long identity = Binder.clearCallingIdentity();
6533 try {
6534 Object response = sendRequest(
6535 CMD_SET_FORBIDDEN_PLMNS,
6536 new Pair<Integer, List<String>>(new Integer(appType), fplmns),
6537 subId);
6538 return (int) response;
6539 } finally {
6540 Binder.restoreCallingIdentity(identity);
6541 }
6542 }
6543
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006544 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08006545 public String sendEnvelopeWithStatus(int subId, String content) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006546 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6547 mApp, subId, "sendEnvelopeWithStatus");
Evan Charltonc66da362014-05-16 14:06:40 -07006548
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006549 final long identity = Binder.clearCallingIdentity();
6550 try {
6551 IccIoResult response = (IccIoResult) sendRequest(CMD_SEND_ENVELOPE, content, subId);
6552 if (response.payload == null) {
6553 return "";
6554 }
Evan Charltonc66da362014-05-16 14:06:40 -07006555
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006556 // Append the returned status code to the end of the response payload.
6557 String s = Integer.toHexString(
6558 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
6559 s = IccUtils.bytesToHexString(response.payload) + s;
6560 return s;
6561 } finally {
6562 Binder.restoreCallingIdentity(identity);
6563 }
Evan Charltonc66da362014-05-16 14:06:40 -07006564 }
6565
Jake Hambye994d462014-02-03 13:10:13 -08006566 /**
6567 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
6568 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
6569 *
6570 * @param itemID the ID of the item to read
6571 * @return the NV item as a String, or null on error.
6572 */
6573 @Override
6574 public String nvReadItem(int itemID) {
vagdeviaf9a5b92018-08-15 16:01:53 -07006575 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Jeff Davidson7e17e312018-02-13 18:17:36 -08006576 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6577 mApp, getDefaultSubscription(), "nvReadItem");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006578
6579 final long identity = Binder.clearCallingIdentity();
6580 try {
6581 if (DBG) log("nvReadItem: item " + itemID);
vagdeviaf9a5b92018-08-15 16:01:53 -07006582 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006583 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
6584 return value;
6585 } finally {
6586 Binder.restoreCallingIdentity(identity);
6587 }
Jake Hambye994d462014-02-03 13:10:13 -08006588 }
6589
6590 /**
6591 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
6592 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
6593 *
6594 * @param itemID the ID of the item to read
6595 * @param itemValue the value to write, as a String
6596 * @return true on success; false on any failure
6597 */
6598 @Override
6599 public boolean nvWriteItem(int itemID, String itemValue) {
vagdeviaf9a5b92018-08-15 16:01:53 -07006600 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Jeff Davidson7e17e312018-02-13 18:17:36 -08006601 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6602 mApp, getDefaultSubscription(), "nvWriteItem");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006603
6604 final long identity = Binder.clearCallingIdentity();
6605 try {
6606 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
6607 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
vagdeviaf9a5b92018-08-15 16:01:53 -07006608 new Pair<Integer, String>(itemID, itemValue), workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006609 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
6610 return success;
6611 } finally {
6612 Binder.restoreCallingIdentity(identity);
6613 }
Jake Hambye994d462014-02-03 13:10:13 -08006614 }
6615
6616 /**
6617 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
6618 * Used for device configuration by some CDMA operators.
6619 *
6620 * @param preferredRoamingList byte array containing the new PRL
6621 * @return true on success; false on any failure
6622 */
6623 @Override
6624 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006625 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6626 mApp, getDefaultSubscription(), "nvWriteCdmaPrl");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006627
6628 final long identity = Binder.clearCallingIdentity();
6629 try {
6630 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
6631 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
6632 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
6633 return success;
6634 } finally {
6635 Binder.restoreCallingIdentity(identity);
6636 }
Jake Hambye994d462014-02-03 13:10:13 -08006637 }
6638
6639 /**
chen xu6dac5ab2018-10-26 17:39:23 -07006640 * Rollback modem configurations to factory default except some config which are in whitelist.
Jake Hambye994d462014-02-03 13:10:13 -08006641 * Used for device configuration by some CDMA operators.
6642 *
chen xu6dac5ab2018-10-26 17:39:23 -07006643 * @param slotIndex - device slot.
6644 *
Jake Hambye994d462014-02-03 13:10:13 -08006645 * @return true on success; false on any failure
6646 */
6647 @Override
chen xu6dac5ab2018-10-26 17:39:23 -07006648 public boolean resetModemConfig(int slotIndex) {
6649 Phone phone = PhoneFactory.getPhone(slotIndex);
6650 if (phone != null) {
6651 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6652 mApp, phone.getSubId(), "resetModemConfig");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006653
chen xu6dac5ab2018-10-26 17:39:23 -07006654 final long identity = Binder.clearCallingIdentity();
6655 try {
6656 Boolean success = (Boolean) sendRequest(CMD_RESET_MODEM_CONFIG, null);
6657 if (DBG) log("resetModemConfig:" + ' ' + (success ? "ok" : "fail"));
6658 return success;
6659 } finally {
6660 Binder.restoreCallingIdentity(identity);
6661 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006662 }
chen xu6dac5ab2018-10-26 17:39:23 -07006663 return false;
6664 }
6665
6666 /**
6667 * Generate a radio modem reset. Used for device configuration by some CDMA operators.
6668 *
6669 * @param slotIndex - device slot.
6670 *
6671 * @return true on success; false on any failure
6672 */
6673 @Override
6674 public boolean rebootModem(int slotIndex) {
6675 Phone phone = PhoneFactory.getPhone(slotIndex);
6676 if (phone != null) {
6677 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6678 mApp, phone.getSubId(), "rebootModem");
6679
6680 final long identity = Binder.clearCallingIdentity();
6681 try {
6682 Boolean success = (Boolean) sendRequest(CMD_MODEM_REBOOT, null);
6683 if (DBG) log("rebootModem:" + ' ' + (success ? "ok" : "fail"));
6684 return success;
6685 } finally {
6686 Binder.restoreCallingIdentity(identity);
6687 }
6688 }
6689 return false;
Jake Hambye994d462014-02-03 13:10:13 -08006690 }
Jake Hamby7c27be32014-03-03 13:25:59 -08006691
Brad Ebinger51f743a2017-01-23 13:50:20 -08006692 /**
Grace Jiaaa2eb6b2020-01-09 16:26:08 -08006693 * Toggle IMS disable and enable for the framework to reset it. See {@link #enableIms(int)} and
6694 * {@link #disableIms(int)}.
6695 * @param slotIndex device slot.
6696 */
6697 public void resetIms(int slotIndex) {
6698 enforceModifyPermission();
6699
6700 final long identity = Binder.clearCallingIdentity();
6701 try {
6702 if (mImsResolver == null) {
6703 // may happen if the does not support IMS.
6704 return;
6705 }
Hyunhoa17ac7c2022-08-30 12:03:04 +00006706 mImsResolver.resetIms(slotIndex);
Grace Jiaaa2eb6b2020-01-09 16:26:08 -08006707 } finally {
6708 Binder.restoreCallingIdentity(identity);
6709 }
6710 }
6711
6712 /**
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006713 * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
6714 * status updates, if not already enabled.
Brad Ebinger51f743a2017-01-23 13:50:20 -08006715 */
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006716 public void enableIms(int slotId) {
Brad Ebinger51f743a2017-01-23 13:50:20 -08006717 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006718
6719 final long identity = Binder.clearCallingIdentity();
6720 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006721 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006722 // may happen if the device does not support IMS.
6723 return;
6724 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006725 mImsResolver.enableIms(slotId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006726 } finally {
6727 Binder.restoreCallingIdentity(identity);
6728 }
Brad Ebinger34bef922017-11-09 10:27:08 -08006729 }
6730
6731 /**
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006732 * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature
6733 * status updates to disabled.
Brad Ebinger34bef922017-11-09 10:27:08 -08006734 */
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006735 public void disableIms(int slotId) {
6736 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006737
6738 final long identity = Binder.clearCallingIdentity();
6739 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006740 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006741 // may happen if the device does not support IMS.
6742 return;
6743 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006744 mImsResolver.disableIms(slotId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006745 } finally {
6746 Binder.restoreCallingIdentity(identity);
6747 }
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006748 }
6749
6750 /**
Brad Ebinger67b3e042020-09-11 12:45:11 -07006751 * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
6752 * callback.
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006753 */
Brad Ebinger67b3e042020-09-11 12:45:11 -07006754 @Override
Brad Ebingerf6aca002020-10-01 13:51:05 -07006755 public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebinger34bef922017-11-09 10:27:08 -08006756 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006757
6758 final long identity = Binder.clearCallingIdentity();
6759 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006760 if (mImsResolver == null) {
Brad Ebinger67b3e042020-09-11 12:45:11 -07006761 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
6762 "Device does not support IMS");
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006763 }
Brad Ebingerf6aca002020-10-01 13:51:05 -07006764 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006765 } finally {
6766 Binder.restoreCallingIdentity(identity);
6767 }
Brad Ebinger34bef922017-11-09 10:27:08 -08006768 }
Brad Ebinger5f64b052017-12-14 14:26:15 -08006769 /**
Brad Ebinger075ff3a2020-05-18 17:52:58 -07006770 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
6771 */
Brad Ebinger67b3e042020-09-11 12:45:11 -07006772 @Override
6773 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
Brad Ebinger075ff3a2020-05-18 17:52:58 -07006774 enforceModifyPermission();
6775
6776 final long identity = Binder.clearCallingIdentity();
6777 try {
6778 if (mImsResolver == null) return;
Brad Ebinger67b3e042020-09-11 12:45:11 -07006779 mImsResolver.unregisterImsFeatureCallback(callback);
Brad Ebinger075ff3a2020-05-18 17:52:58 -07006780 } finally {
6781 Binder.restoreCallingIdentity(identity);
6782 }
6783 }
6784
6785 /**
Brad Ebinger5f64b052017-12-14 14:26:15 -08006786 * Returns the {@link IImsRegistration} structure associated with the slotId and feature
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006787 * specified or null if IMS is not supported on the slot specified.
Brad Ebinger5f64b052017-12-14 14:26:15 -08006788 */
6789 public IImsRegistration getImsRegistration(int slotId, int feature) throws RemoteException {
6790 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006791
6792 final long identity = Binder.clearCallingIdentity();
6793 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006794 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006795 // may happen if the device does not support IMS.
6796 return null;
6797 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006798 return mImsResolver.getImsRegistration(slotId, feature);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006799 } finally {
6800 Binder.restoreCallingIdentity(identity);
6801 }
Brad Ebinger5f64b052017-12-14 14:26:15 -08006802 }
6803
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006804 /**
6805 * Returns the {@link IImsConfig} structure associated with the slotId and feature
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006806 * specified or null if IMS is not supported on the slot specified.
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006807 */
6808 public IImsConfig getImsConfig(int slotId, int feature) throws RemoteException {
6809 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006810
6811 final long identity = Binder.clearCallingIdentity();
6812 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006813 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006814 // may happen if the device does not support IMS.
6815 return null;
6816 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006817 return mImsResolver.getImsConfig(slotId, feature);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006818 } finally {
6819 Binder.restoreCallingIdentity(identity);
6820 }
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006821 }
6822
Brad Ebinger884c07b2018-02-15 16:17:40 -08006823 /**
Brad Ebingerdac2f002018-04-03 15:17:52 -07006824 * Sets the ImsService Package Name that Telephony will bind to.
6825 *
Brad Ebinger24c29992019-12-05 13:03:21 -08006826 * @param slotIndex the slot ID that the ImsService should bind for.
6827 * @param isCarrierService true if the ImsService is the carrier override, false if the
Brad Ebingerdac2f002018-04-03 15:17:52 -07006828 * ImsService is the device default ImsService.
Brad Ebinger24c29992019-12-05 13:03:21 -08006829 * @param featureTypes An integer array of feature types associated with a packageName.
6830 * @param packageName The name of the package that the current configuration will be replaced
6831 * with.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006832 * @return true if setting the ImsService to bind to succeeded, false if it did not.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006833 */
Brad Ebinger24c29992019-12-05 13:03:21 -08006834 public boolean setBoundImsServiceOverride(int slotIndex, boolean isCarrierService,
6835 int[] featureTypes, String packageName) {
Brad Ebinger24c29992019-12-05 13:03:21 -08006836 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setBoundImsServiceOverride");
Brad Ebingerde696de2018-04-06 09:56:40 -07006837 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
Jack Yu00ece8c2022-11-19 22:29:12 -08006838 SubscriptionManager.getSubscriptionId(slotIndex), "setBoundImsServiceOverride");
Brad Ebingerde696de2018-04-06 09:56:40 -07006839
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006840 final long identity = Binder.clearCallingIdentity();
6841 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006842 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006843 // may happen if the device does not support IMS.
6844 return false;
6845 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006846 Map<Integer, String> featureConfig = new HashMap<>();
6847 for (int featureType : featureTypes) {
6848 featureConfig.put(featureType, packageName);
6849 }
6850 return mImsResolver.overrideImsServiceConfiguration(slotIndex, isCarrierService,
6851 featureConfig);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006852 } finally {
6853 Binder.restoreCallingIdentity(identity);
6854 }
Brad Ebingerdac2f002018-04-03 15:17:52 -07006855 }
6856
6857 /**
Brad Ebinger999d3302020-11-25 14:31:39 -08006858 * Clears any carrier ImsService overrides for the slot index specified that were previously
6859 * set with {@link #setBoundImsServiceOverride(int, boolean, int[], String)}.
6860 *
6861 * This should only be used for testing.
6862 *
6863 * @param slotIndex the slot ID that the ImsService should bind for.
6864 * @return true if clearing the carrier ImsService override succeeded or false if it did not.
6865 */
6866 @Override
6867 public boolean clearCarrierImsServiceOverride(int slotIndex) {
Brad Ebinger999d3302020-11-25 14:31:39 -08006868 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
6869 "clearCarrierImsServiceOverride");
6870 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
Jack Yu00ece8c2022-11-19 22:29:12 -08006871 SubscriptionManager.getSubscriptionId(slotIndex), "clearCarrierImsServiceOverride");
Brad Ebinger999d3302020-11-25 14:31:39 -08006872
6873 final long identity = Binder.clearCallingIdentity();
6874 try {
6875 if (mImsResolver == null) {
6876 // may happen if the device does not support IMS.
6877 return false;
6878 }
6879 return mImsResolver.clearCarrierImsServiceConfiguration(slotIndex);
6880 } finally {
6881 Binder.restoreCallingIdentity(identity);
6882 }
6883 }
6884
6885 /**
Brad Ebinger24c29992019-12-05 13:03:21 -08006886 * Return the package name of the currently bound ImsService.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006887 *
6888 * @param slotId The slot that the ImsService is associated with.
6889 * @param isCarrierImsService true, if the ImsService is a carrier override, false if it is
6890 * the device default.
Brad Ebinger24c29992019-12-05 13:03:21 -08006891 * @param featureType The feature associated with the queried configuration.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006892 * @return the package name of the ImsService configuration.
6893 */
Brad Ebinger24c29992019-12-05 13:03:21 -08006894 public String getBoundImsServicePackage(int slotId, boolean isCarrierImsService,
6895 @ImsFeature.FeatureType int featureType) {
Brad Ebinger24c29992019-12-05 13:03:21 -08006896 TelephonyPermissions
Jack Yu00ece8c2022-11-19 22:29:12 -08006897 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(mApp,
6898 SubscriptionManager.getSubscriptionId(slotId), "getBoundImsServicePackage");
Brad Ebingerde696de2018-04-06 09:56:40 -07006899
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006900 final long identity = Binder.clearCallingIdentity();
6901 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006902 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006903 // may happen if the device does not support IMS.
6904 return "";
6905 }
Brad Ebingera80c3312019-12-02 10:59:39 -08006906 // TODO: change API to query RCS separately.
Brad Ebinger24c29992019-12-05 13:03:21 -08006907 return mImsResolver.getImsServiceConfiguration(slotId, isCarrierImsService,
6908 featureType);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006909 } finally {
6910 Binder.restoreCallingIdentity(identity);
6911 }
Brad Ebingerdac2f002018-04-03 15:17:52 -07006912 }
6913
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006914 /**
6915 * Get the MmTelFeature state associated with the requested subscription id.
6916 * @param subId The subscription that the MmTelFeature is associated with.
6917 * @param callback A callback with an integer containing the
6918 * {@link android.telephony.ims.feature.ImsFeature.ImsState} associated with the MmTelFeature.
6919 */
6920 @Override
6921 public void getImsMmTelFeatureState(int subId, IIntegerConsumer callback) {
6922 enforceReadPrivilegedPermission("getImsMmTelFeatureState");
Brad Ebingera2628302022-02-18 03:44:55 +00006923 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
6924 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
6925 "IMS not available on device.");
6926 }
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006927 final long token = Binder.clearCallingIdentity();
6928 try {
Brad Ebingera2628302022-02-18 03:44:55 +00006929 int slotId = getSlotIndex(subId);
6930 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
6931 Log.w(LOG_TAG, "getImsMmTelFeatureState: called with an inactive subscription '"
6932 + subId + "'");
6933 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
6934 }
6935 verifyImsMmTelConfiguredOrThrow(slotId);
6936 ImsManager.getInstance(mApp, slotId).getImsServiceState(anInteger -> {
6937 try {
6938 callback.accept(anInteger == null ? ImsFeature.STATE_UNAVAILABLE : anInteger);
6939 } catch (RemoteException e) {
6940 Log.w(LOG_TAG, "getImsMmTelFeatureState: remote caller is no longer running. "
6941 + "Ignore");
6942 }
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006943 });
Brad Ebinger919631e2021-06-02 17:46:35 -07006944 } catch (ImsException e) {
6945 throw new ServiceSpecificException(e.getCode());
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006946 } finally {
6947 Binder.restoreCallingIdentity(token);
6948 }
6949 }
6950
Daniel Brightbb5840b2021-01-12 15:48:18 -08006951 /**
6952 * Sets the ims registration state on all valid {@link Phone}s.
6953 */
6954 public void setImsRegistrationState(final boolean registered) {
Wink Saville36469e72014-06-11 15:17:00 -07006955 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006956
6957 final long identity = Binder.clearCallingIdentity();
6958 try {
Daniel Brightbb5840b2021-01-12 15:48:18 -08006959 // NOTE: Before S, this method only set the default phone.
6960 for (final Phone phone : PhoneFactory.getPhones()) {
6961 if (SubscriptionManager.isValidSubscriptionId(phone.getSubId())) {
6962 phone.setImsRegistrationState(registered);
6963 }
6964 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006965 } finally {
6966 Binder.restoreCallingIdentity(identity);
6967 }
Wink Saville36469e72014-06-11 15:17:00 -07006968 }
6969
6970 /**
Stuart Scott54788802015-03-30 13:18:01 -07006971 * Set the network selection mode to automatic.
6972 *
6973 */
6974 @Override
6975 public void setNetworkSelectionModeAutomatic(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006976 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6977 mApp, subId, "setNetworkSelectionModeAutomatic");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006978
6979 final long identity = Binder.clearCallingIdentity();
6980 try {
shilufc958392020-01-20 11:36:01 -08006981 if (!isActiveSubscription(subId)) {
6982 return;
6983 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006984 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
Rambo Wang0f050d82021-02-12 11:43:36 -08006985 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId,
6986 SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006987 } finally {
6988 Binder.restoreCallingIdentity(identity);
6989 }
Stuart Scott54788802015-03-30 13:18:01 -07006990 }
6991
Jack Yud10cdd42020-09-28 20:28:01 -07006992 /**
Pengquan Mengea84e042018-09-20 14:57:26 -07006993 * Ask the radio to connect to the input network and change selection mode to manual.
6994 *
6995 * @param subId the id of the subscription.
6996 * @param operatorInfo the operator information, included the PLMN, long name and short name of
6997 * the operator to attach to.
6998 * @param persistSelection whether the selection will persist until reboot. If true, only allows
6999 * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
7000 * normal network selection next time.
7001 * @return {@code true} on success; {@code true} on any failure.
Shishir Agrawal302c8692015-06-19 13:49:39 -07007002 */
7003 @Override
Pengquan Mengea84e042018-09-20 14:57:26 -07007004 public boolean setNetworkSelectionModeManual(
7005 int subId, OperatorInfo operatorInfo, boolean persistSelection) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007006 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7007 mApp, subId, "setNetworkSelectionModeManual");
Pengquan Menge92a50d2018-09-21 15:54:48 -07007008
Jack Yu285100e2022-12-02 22:48:35 -08007009 final long identity = Binder.clearCallingIdentity();
Pengquan Menge92a50d2018-09-21 15:54:48 -07007010 if (!isActiveSubscription(subId)) {
7011 return false;
7012 }
7013
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007014 try {
Pengquan Mengea84e042018-09-20 14:57:26 -07007015 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operatorInfo,
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007016 persistSelection);
Pengquan Mengea84e042018-09-20 14:57:26 -07007017 if (DBG) {
7018 log("setNetworkSelectionModeManual: subId: " + subId
7019 + " operator: " + operatorInfo);
7020 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007021 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
7022 } finally {
7023 Binder.restoreCallingIdentity(identity);
7024 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07007025 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007026 /**
shilu84f6e8b2019-12-19 13:58:01 -08007027 * Get the manual network selection
7028 *
7029 * @param subId the id of the subscription.
7030 *
7031 * @return the previously saved user selected PLMN
7032 */
7033 @Override
7034 public String getManualNetworkSelectionPlmn(int subId) {
7035 TelephonyPermissions
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007036 .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
7037 mApp, subId, "getManualNetworkSelectionPlmn");
shilu84f6e8b2019-12-19 13:58:01 -08007038
7039 final long identity = Binder.clearCallingIdentity();
7040 try {
7041 if (!isActiveSubscription(subId)) {
shilufa1c2592020-03-10 10:59:43 -07007042 throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
shilu84f6e8b2019-12-19 13:58:01 -08007043 }
7044
7045 final Phone phone = getPhone(subId);
7046 if (phone == null) {
shilufa1c2592020-03-10 10:59:43 -07007047 throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
shilu84f6e8b2019-12-19 13:58:01 -08007048 }
7049 OperatorInfo networkSelection = phone.getSavedNetworkSelection();
7050 return TextUtils.isEmpty(networkSelection.getOperatorNumeric())
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007051 ? phone.getManualNetworkSelectionPlmn() : networkSelection.getOperatorNumeric();
shilu84f6e8b2019-12-19 13:58:01 -08007052 } finally {
7053 Binder.restoreCallingIdentity(identity);
7054 }
7055 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07007056
7057 /**
7058 * Scans for available networks.
7059 */
7060 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07007061 public CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage,
7062 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007063 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7064 mApp, subId, "getCellNetworkScanResults");
Hall Liuf19c44f2018-11-27 14:38:17 -08007065 LocationAccessPolicy.LocationPermissionResult locationResult =
7066 LocationAccessPolicy.checkLocationPermission(mApp,
7067 new LocationAccessPolicy.LocationPermissionQuery.Builder()
7068 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07007069 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08007070 .setCallingPid(Binder.getCallingPid())
7071 .setCallingUid(Binder.getCallingUid())
7072 .setMethod("getCellNetworkScanResults")
7073 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
Hall Liuc4a3e422020-05-26 17:18:03 -07007074 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
7075 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
Hall Liuf19c44f2018-11-27 14:38:17 -08007076 .build());
7077 switch (locationResult) {
7078 case DENIED_HARD:
7079 throw new SecurityException("Not allowed to access scan results -- location");
7080 case DENIED_SOFT:
7081 return null;
7082 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007083
Pengquan Menga1bb6272018-09-06 09:59:22 -07007084 long identity = Binder.clearCallingIdentity();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007085 try {
7086 if (DBG) log("getCellNetworkScanResults: subId " + subId);
Pengquan Menga1bb6272018-09-06 09:59:22 -07007087 return (CellNetworkScanResult) sendRequest(
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007088 CMD_PERFORM_NETWORK_SCAN, null, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007089 } finally {
7090 Binder.restoreCallingIdentity(identity);
7091 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07007092 }
7093
7094 /**
Shuo Qian4a594052020-01-23 11:59:30 -08007095 * Get the call forwarding info, given the call forwarding reason.
7096 */
7097 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007098 public void getCallForwarding(int subId, int callForwardingReason,
7099 ICallForwardingInfoCallback callback) {
Shuo Qian4a594052020-01-23 11:59:30 -08007100 enforceReadPrivilegedPermission("getCallForwarding");
7101 long identity = Binder.clearCallingIdentity();
7102 try {
7103 if (DBG) {
7104 log("getCallForwarding: subId " + subId
7105 + " callForwardingReason" + callForwardingReason);
7106 }
Hall Liu27d24262020-09-18 19:04:59 -07007107
7108 Phone phone = getPhone(subId);
7109 if (phone == null) {
7110 try {
Hall Liu940c4ca2020-09-29 17:10:18 -07007111 callback.onError(
7112 TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
Hall Liu27d24262020-09-18 19:04:59 -07007113 } catch (RemoteException e) {
7114 // ignore
7115 }
7116 return;
7117 }
7118
7119 Pair<Integer, TelephonyManager.CallForwardingInfoCallback> argument = Pair.create(
7120 callForwardingReason, new TelephonyManager.CallForwardingInfoCallback() {
7121 @Override
7122 public void onCallForwardingInfoAvailable(CallForwardingInfo info) {
7123 try {
7124 callback.onCallForwardingInfoAvailable(info);
7125 } catch (RemoteException e) {
7126 // ignore
7127 }
7128 }
7129
7130 @Override
7131 public void onError(int error) {
7132 try {
7133 callback.onError(error);
7134 } catch (RemoteException e) {
7135 // ignore
7136 }
7137 }
7138 });
7139 sendRequestAsync(CMD_GET_CALL_FORWARDING, argument, phone, null);
Shuo Qian4a594052020-01-23 11:59:30 -08007140 } finally {
7141 Binder.restoreCallingIdentity(identity);
7142 }
7143 }
7144
7145 /**
7146 * Sets the voice call forwarding info including status (enable/disable), call forwarding
7147 * reason, the number to forward, and the timeout before the forwarding is attempted.
7148 */
7149 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007150 public void setCallForwarding(int subId, CallForwardingInfo callForwardingInfo,
7151 IIntegerConsumer callback) {
Shuo Qian4a594052020-01-23 11:59:30 -08007152 enforceModifyPermission();
7153 long identity = Binder.clearCallingIdentity();
7154 try {
7155 if (DBG) {
7156 log("setCallForwarding: subId " + subId
7157 + " callForwardingInfo" + callForwardingInfo);
7158 }
Hall Liu27d24262020-09-18 19:04:59 -07007159
7160 Phone phone = getPhone(subId);
7161 if (phone == null) {
7162 try {
Hall Liu940c4ca2020-09-29 17:10:18 -07007163 callback.accept(
7164 TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
Hall Liu27d24262020-09-18 19:04:59 -07007165 } catch (RemoteException e) {
7166 // ignore
7167 }
7168 return;
7169 }
7170
7171 Pair<CallForwardingInfo, Consumer<Integer>> arguments = Pair.create(callForwardingInfo,
7172 FunctionalUtils.ignoreRemoteException(callback::accept));
7173
7174 sendRequestAsync(CMD_SET_CALL_FORWARDING, arguments, phone, null);
Shuo Qian4a594052020-01-23 11:59:30 -08007175 } finally {
7176 Binder.restoreCallingIdentity(identity);
7177 }
7178 }
7179
7180 /**
Hall Liu27d24262020-09-18 19:04:59 -07007181 * Get the call waiting status for a subId.
Shuo Qian4a594052020-01-23 11:59:30 -08007182 */
7183 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007184 public void getCallWaitingStatus(int subId, IIntegerConsumer callback) {
SongFerngWang0e767992021-03-31 22:08:45 +08007185 enforceReadPrivilegedPermission("getCallWaitingStatus");
Shuo Qian4a594052020-01-23 11:59:30 -08007186 long identity = Binder.clearCallingIdentity();
7187 try {
Hall Liu27d24262020-09-18 19:04:59 -07007188 Phone phone = getPhone(subId);
7189 if (phone == null) {
7190 try {
7191 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
7192 } catch (RemoteException e) {
7193 // ignore
7194 }
7195 return;
7196 }
SongFerngWang0e767992021-03-31 22:08:45 +08007197 CarrierConfigManager configManager = new CarrierConfigManager(phone.getContext());
7198 PersistableBundle c = configManager.getConfigForSubId(subId);
7199 boolean requireUssd = c.getBoolean(
7200 CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false);
Hall Liu27d24262020-09-18 19:04:59 -07007201
Shuo Qian4a594052020-01-23 11:59:30 -08007202 if (DBG) log("getCallWaitingStatus: subId " + subId);
SongFerngWang0e767992021-03-31 22:08:45 +08007203 if (requireUssd) {
7204 CarrierXmlParser carrierXmlParser = new CarrierXmlParser(phone.getContext(),
7205 getSubscriptionCarrierId(subId));
7206 String newUssdCommand = "";
7207 try {
7208 newUssdCommand = carrierXmlParser.getFeature(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007209 CarrierXmlParser.FEATURE_CALL_WAITING)
SongFerngWang0e767992021-03-31 22:08:45 +08007210 .makeCommand(CarrierXmlParser.SsEntry.SSAction.QUERY, null);
7211 } catch (NullPointerException e) {
7212 loge("Failed to generate USSD number" + e);
7213 }
7214 ResultReceiver wrappedCallback = new CallWaitingUssdResultReceiver(
7215 mMainThreadHandler, callback, carrierXmlParser,
7216 CarrierXmlParser.SsEntry.SSAction.QUERY);
7217 final String ussdCommand = newUssdCommand;
7218 Executors.newSingleThreadExecutor().execute(() -> {
7219 handleUssdRequest(subId, ussdCommand, wrappedCallback);
7220 });
7221 } else {
7222 Consumer<Integer> argument = FunctionalUtils.ignoreRemoteException(
7223 callback::accept);
7224 sendRequestAsync(CMD_GET_CALL_WAITING, argument, phone, null);
7225 }
Shuo Qian4a594052020-01-23 11:59:30 -08007226 } finally {
7227 Binder.restoreCallingIdentity(identity);
7228 }
7229 }
7230
7231 /**
Hall Liu27d24262020-09-18 19:04:59 -07007232 * Sets whether call waiting is enabled for a given subId.
Shuo Qian4a594052020-01-23 11:59:30 -08007233 */
7234 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007235 public void setCallWaitingStatus(int subId, boolean enable, IIntegerConsumer callback) {
Shuo Qian4a594052020-01-23 11:59:30 -08007236 enforceModifyPermission();
7237 long identity = Binder.clearCallingIdentity();
7238 try {
Hall Liu27d24262020-09-18 19:04:59 -07007239 if (DBG) log("setCallWaitingStatus: subId " + subId + " enable: " + enable);
7240
7241 Phone phone = getPhone(subId);
7242 if (phone == null) {
7243 try {
7244 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
7245 } catch (RemoteException e) {
7246 // ignore
7247 }
7248 return;
7249 }
7250
SongFerngWang0e767992021-03-31 22:08:45 +08007251 CarrierConfigManager configManager = new CarrierConfigManager(phone.getContext());
7252 PersistableBundle c = configManager.getConfigForSubId(subId);
7253 boolean requireUssd = c.getBoolean(
7254 CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false);
Hall Liu27d24262020-09-18 19:04:59 -07007255
SongFerngWang0e767992021-03-31 22:08:45 +08007256 if (DBG) log("getCallWaitingStatus: subId " + subId);
7257 if (requireUssd) {
7258 CarrierXmlParser carrierXmlParser = new CarrierXmlParser(phone.getContext(),
7259 getSubscriptionCarrierId(subId));
7260 CarrierXmlParser.SsEntry.SSAction ssAction =
7261 enable ? CarrierXmlParser.SsEntry.SSAction.UPDATE_ACTIVATE
7262 : CarrierXmlParser.SsEntry.SSAction.UPDATE_DEACTIVATE;
7263 String newUssdCommand = "";
7264 try {
7265 newUssdCommand = carrierXmlParser.getFeature(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007266 CarrierXmlParser.FEATURE_CALL_WAITING)
SongFerngWang0e767992021-03-31 22:08:45 +08007267 .makeCommand(ssAction, null);
7268 } catch (NullPointerException e) {
7269 loge("Failed to generate USSD number" + e);
7270 }
7271 ResultReceiver wrappedCallback = new CallWaitingUssdResultReceiver(
7272 mMainThreadHandler, callback, carrierXmlParser, ssAction);
7273 final String ussdCommand = newUssdCommand;
7274 Executors.newSingleThreadExecutor().execute(() -> {
7275 handleUssdRequest(subId, ussdCommand, wrappedCallback);
7276 });
7277 } else {
7278 Pair<Boolean, Consumer<Integer>> arguments = Pair.create(enable,
7279 FunctionalUtils.ignoreRemoteException(callback::accept));
7280
7281 sendRequestAsync(CMD_SET_CALL_WAITING, arguments, phone, null);
7282 }
Shuo Qian4a594052020-01-23 11:59:30 -08007283 } finally {
7284 Binder.restoreCallingIdentity(identity);
7285 }
7286 }
7287
7288 /**
yinxub1bed742017-04-17 11:45:04 -07007289 * Starts a new network scan and returns the id of this scan.
yinxu504e1392017-04-12 16:03:22 -07007290 *
yinxub1bed742017-04-17 11:45:04 -07007291 * @param subId id of the subscription
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007292 * @param renounceFineLocationAccess Set this to true if the caller would not like to receive
7293 * location related information which will be sent if the caller already possess
7294 * {@android.Manifest.permission.ACCESS_FINE_LOCATION} and do not renounce the permission
yinxub1bed742017-04-17 11:45:04 -07007295 * @param request contains the radio access networks with bands/channels to scan
7296 * @param messenger callback messenger for scan results or errors
7297 * @param binder for the purpose of auto clean when the user thread crashes
yinxu504e1392017-04-12 16:03:22 -07007298 * @return the id of the requested scan which can be used to stop the scan.
7299 */
7300 @Override
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007301 public int requestNetworkScan(int subId, boolean renounceFineLocationAccess,
7302 NetworkScanRequest request, Messenger messenger,
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07007303 IBinder binder, String callingPackage, String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007304 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7305 mApp, subId, "requestNetworkScan");
Hall Liuf19c44f2018-11-27 14:38:17 -08007306 LocationAccessPolicy.LocationPermissionResult locationResult =
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007307 LocationAccessPolicy.LocationPermissionResult.DENIED_HARD;
7308 if (!renounceFineLocationAccess) {
7309 locationResult = LocationAccessPolicy.checkLocationPermission(mApp,
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007310 new LocationAccessPolicy.LocationPermissionQuery.Builder()
7311 .setCallingPackage(callingPackage)
7312 .setCallingFeatureId(callingFeatureId)
7313 .setCallingPid(Binder.getCallingPid())
7314 .setCallingUid(Binder.getCallingUid())
7315 .setMethod("requestNetworkScan")
7316 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
7317 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
7318 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
7319 .build());
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007320 }
Hall Liub2ac8ef2019-02-28 15:56:23 -08007321 if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
Nathan Harold1c11dba2020-09-22 17:54:53 -07007322 SecurityException e = checkNetworkRequestForSanitizedLocationAccess(
7323 request, subId, callingPackage);
Hall Liub2ac8ef2019-02-28 15:56:23 -08007324 if (e != null) {
7325 if (locationResult == LocationAccessPolicy.LocationPermissionResult.DENIED_HARD) {
7326 throw e;
7327 } else {
Hall Liu0e5abaf2019-04-04 01:25:30 -07007328 loge(e.getMessage());
Hall Liub2ac8ef2019-02-28 15:56:23 -08007329 return TelephonyScanManager.INVALID_SCAN_ID;
7330 }
7331 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007332 }
Hall Liu912dfd32019-04-25 14:02:26 -07007333 int callingUid = Binder.getCallingUid();
7334 int callingPid = Binder.getCallingPid();
Ying Xu94a46582019-04-18 17:14:56 -07007335 final long identity = Binder.clearCallingIdentity();
7336 try {
7337 return mNetworkScanRequestTracker.startNetworkScan(
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007338 renounceFineLocationAccess, request, messenger, binder, getPhone(subId),
Hall Liu912dfd32019-04-25 14:02:26 -07007339 callingUid, callingPid, callingPackage);
Ying Xu94a46582019-04-18 17:14:56 -07007340 } finally {
7341 Binder.restoreCallingIdentity(identity);
7342 }
yinxu504e1392017-04-12 16:03:22 -07007343 }
7344
Hall Liub2ac8ef2019-02-28 15:56:23 -08007345 private SecurityException checkNetworkRequestForSanitizedLocationAccess(
Nathan Harold1c11dba2020-09-22 17:54:53 -07007346 NetworkScanRequest request, int subId, String callingPackage) {
Rambo Wang3dee30a2022-10-20 16:52:29 +00007347 boolean hasCarrierPriv;
7348 final long identity = Binder.clearCallingIdentity();
7349 try {
7350 hasCarrierPriv = checkCarrierPrivilegesForPackage(subId, callingPackage)
7351 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
7352 } finally {
7353 Binder.restoreCallingIdentity(identity);
7354 }
Hall Liu558027f2019-05-15 19:14:05 -07007355 boolean hasNetworkScanPermission =
7356 mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007357 == PERMISSION_GRANTED;
Hall Liu558027f2019-05-15 19:14:05 -07007358
7359 if (!hasCarrierPriv && !hasNetworkScanPermission) {
7360 return new SecurityException("permission.NETWORK_SCAN or carrier privileges is needed"
7361 + " for network scans without location access.");
Hall Liub2ac8ef2019-02-28 15:56:23 -08007362 }
7363
7364 if (request.getSpecifiers() != null && request.getSpecifiers().length > 0) {
7365 for (RadioAccessSpecifier ras : request.getSpecifiers()) {
Hall Liub2ac8ef2019-02-28 15:56:23 -08007366 if (ras.getChannels() != null && ras.getChannels().length > 0) {
7367 return new SecurityException("Specific channels must not be"
7368 + " scanned without location access.");
7369 }
7370 }
7371 }
7372
Hall Liub2ac8ef2019-02-28 15:56:23 -08007373 return null;
7374 }
7375
yinxu504e1392017-04-12 16:03:22 -07007376 /**
7377 * Stops an existing network scan with the given scanId.
yinxub1bed742017-04-17 11:45:04 -07007378 *
7379 * @param subId id of the subscription
7380 * @param scanId id of the scan that needs to be stopped
yinxu504e1392017-04-12 16:03:22 -07007381 */
7382 @Override
7383 public void stopNetworkScan(int subId, int scanId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007384 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7385 mApp, subId, "stopNetworkScan");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007386
Hall Liu912dfd32019-04-25 14:02:26 -07007387 int callingUid = Binder.getCallingUid();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007388 final long identity = Binder.clearCallingIdentity();
7389 try {
Hall Liu912dfd32019-04-25 14:02:26 -07007390 mNetworkScanRequestTracker.stopNetworkScan(scanId, callingUid);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007391 } finally {
7392 Binder.restoreCallingIdentity(identity);
7393 }
yinxu504e1392017-04-12 16:03:22 -07007394 }
7395
7396 /**
SongFerngWang3ef3e072020-12-21 16:41:52 +08007397 * Get the allowed network types bitmask.
Junda Liu84d15a22014-07-02 11:21:04 -07007398 *
SongFerngWang3ef3e072020-12-21 16:41:52 +08007399 * @return the allowed network types bitmask, defined in RILConstants.java.
Junda Liu84d15a22014-07-02 11:21:04 -07007400 */
7401 @Override
SongFerngWang3ef3e072020-12-21 16:41:52 +08007402 public int getAllowedNetworkTypesBitmask(int subId) {
Pengquan Menga4009cb2018-12-20 11:00:24 -08007403 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07007404 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
SongFerngWang3ef3e072020-12-21 16:41:52 +08007405 mApp, subId, "getAllowedNetworkTypesBitmask");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007406
7407 final long identity = Binder.clearCallingIdentity();
7408 try {
SongFerngWang3ef3e072020-12-21 16:41:52 +08007409 if (DBG) log("getAllowedNetworkTypesBitmask");
7410 int[] result = (int[]) sendRequest(CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK, null, subId);
7411 int networkTypesBitmask = (result != null ? result[0] : -1);
7412 if (DBG) log("getAllowedNetworkTypesBitmask: " + networkTypesBitmask);
7413 return networkTypesBitmask;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007414 } finally {
7415 Binder.restoreCallingIdentity(identity);
7416 }
Jake Hamby7c27be32014-03-03 13:25:59 -08007417 }
7418
7419 /**
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007420 * Get the allowed network types for certain reason.
7421 *
7422 * @param subId the id of the subscription.
7423 * @param reason the reason the allowed network type change is taking place
7424 * @return the allowed network types.
7425 */
7426 @Override
7427 public long getAllowedNetworkTypesForReason(int subId,
7428 @TelephonyManager.AllowedNetworkTypesReason int reason) {
Nathan Harold62c68512021-04-06 11:26:02 -07007429 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007430 mApp, subId, "getAllowedNetworkTypesForReason");
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007431 final long identity = Binder.clearCallingIdentity();
7432 try {
7433 return getPhoneFromSubId(subId).getAllowedNetworkTypes(reason);
7434 } finally {
7435 Binder.restoreCallingIdentity(identity);
7436 }
7437 }
7438
7439 /**
Sooraj Sasindran37444802020-08-11 10:40:43 -07007440 * Enable/Disable E-UTRA-NR Dual Connectivity
7441 * @param subId subscription id of the sim card
7442 * @param nrDualConnectivityState expected NR dual connectivity state
7443 * This can be passed following states
7444 * <ol>
7445 * <li>Enable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_ENABLE}
7446 * <li>Disable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE}
7447 * <li>Disable NR dual connectivity and force secondary cell to be released
7448 * {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE}
7449 * </ol>
7450 * @return operation result.
7451 */
7452 @Override
7453 public int setNrDualConnectivityState(int subId,
7454 @TelephonyManager.NrDualConnectivityState int nrDualConnectivityState) {
7455 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7456 mApp, subId, "enableNRDualConnectivity");
Sooraj Sasindran0e4e00a2021-03-16 18:02:32 -07007457 if (!isRadioInterfaceCapabilitySupported(
Sooraj Sasindrandfd595b2021-03-11 17:38:13 -08007458 TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE)) {
7459 return TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED;
7460 }
7461
Sooraj Sasindran37444802020-08-11 10:40:43 -07007462 WorkSource workSource = getWorkSource(Binder.getCallingUid());
7463 final long identity = Binder.clearCallingIdentity();
7464 try {
7465 int result = (int) sendRequest(CMD_ENABLE_NR_DUAL_CONNECTIVITY,
7466 nrDualConnectivityState, subId,
7467 workSource);
7468 if (DBG) log("enableNRDualConnectivity result: " + result);
7469 return result;
7470 } finally {
7471 Binder.restoreCallingIdentity(identity);
7472 }
7473 }
7474
7475 /**
7476 * Is E-UTRA-NR Dual Connectivity enabled
7477 * @return true if dual connectivity is enabled else false
7478 */
7479 @Override
7480 public boolean isNrDualConnectivityEnabled(int subId) {
7481 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07007482 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Sooraj Sasindran37444802020-08-11 10:40:43 -07007483 mApp, subId, "isNRDualConnectivityEnabled");
Sooraj Sasindran0e4e00a2021-03-16 18:02:32 -07007484 if (!isRadioInterfaceCapabilitySupported(
Sooraj Sasindrandfd595b2021-03-11 17:38:13 -08007485 TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE)) {
7486 return false;
7487 }
Sooraj Sasindran37444802020-08-11 10:40:43 -07007488 WorkSource workSource = getWorkSource(Binder.getCallingUid());
7489 final long identity = Binder.clearCallingIdentity();
7490 try {
7491 boolean isEnabled = (boolean) sendRequest(CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED,
7492 null, subId, workSource);
7493 if (DBG) log("isNRDualConnectivityEnabled: " + isEnabled);
7494 return isEnabled;
7495 } finally {
7496 Binder.restoreCallingIdentity(identity);
7497 }
7498 }
7499
7500 /**
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007501 * Set the allowed network types of the device and
7502 * provide the reason triggering the allowed network change.
7503 *
7504 * @param subId the id of the subscription.
7505 * @param reason the reason the allowed network type change is taking place
7506 * @param allowedNetworkTypes the allowed network types.
7507 * @return true on success; false on any failure.
7508 */
7509 @Override
7510 public boolean setAllowedNetworkTypesForReason(int subId,
SongFerngWang3ef3e072020-12-21 16:41:52 +08007511 @TelephonyManager.AllowedNetworkTypesReason int reason,
7512 @TelephonyManager.NetworkTypeBitMask long allowedNetworkTypes) {
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007513 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7514 mApp, subId, "setAllowedNetworkTypesForReason");
Gil Cukierman1d3d3752022-10-03 21:31:33 +00007515 // If the caller only has carrier privileges, then they should not be able to override
7516 // any network types which were set for security reasons.
7517 if (mApp.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE)
7518 != PERMISSION_GRANTED
Gil Cukierman2a8f48b2023-01-26 20:26:20 +00007519 && reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G) {
Gil Cukierman1d3d3752022-10-03 21:31:33 +00007520 throw new SecurityException(
7521 "setAllowedNetworkTypesForReason cannot be called with carrier privileges for"
Gil Cukierman2a8f48b2023-01-26 20:26:20 +00007522 + " reason " + reason);
Gil Cukierman1d3d3752022-10-03 21:31:33 +00007523 }
SongFerngWang3ef3e072020-12-21 16:41:52 +08007524 if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
Jack Yu5b494332023-01-23 18:18:04 +00007525 loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
SongFerngWang7ffc2732021-04-15 19:46:33 +08007526 return false;
7527 }
7528 if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
7529 loge("setAllowedNetworkTypesForReason: Invalid subscriptionId:" + subId);
SongFerngWang3ef3e072020-12-21 16:41:52 +08007530 return false;
7531 }
7532
Jack Yu5b494332023-01-23 18:18:04 +00007533 log("setAllowedNetworkTypesForReason: subId=" + subId + ", reason=" + reason + " value: "
7534 + TelephonyManager.convertNetworkTypeBitmaskToString(allowedNetworkTypes));
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007535
Jack Yue37dd262022-12-16 11:53:37 -08007536 Phone phone = getPhone(subId);
7537 if (phone == null) {
7538 return false;
7539 }
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007540
Jack Yue37dd262022-12-16 11:53:37 -08007541 if (allowedNetworkTypes == phone.getAllowedNetworkTypes(reason)) {
Jack Yu5b494332023-01-23 18:18:04 +00007542 log("setAllowedNetworkTypesForReason: " + reason + "does not change value");
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007543 return true;
SongFerngWang3ef3e072020-12-21 16:41:52 +08007544 }
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007545
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007546 final long identity = Binder.clearCallingIdentity();
7547 try {
SongFerngWang3ef3e072020-12-21 16:41:52 +08007548 Boolean success = (Boolean) sendRequest(
7549 CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON,
7550 new Pair<Integer, Long>(reason, allowedNetworkTypes), subId);
7551
7552 if (DBG) log("setAllowedNetworkTypesForReason: " + (success ? "ok" : "fail"));
7553 return success;
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007554 } finally {
7555 Binder.restoreCallingIdentity(identity);
7556 }
7557 }
7558
7559 /**
Miaoa84611c2019-03-15 09:21:10 +08007560 * Check whether DUN APN is required for tethering with subId.
Junda Liu475951f2014-11-07 16:45:03 -08007561 *
Miaoa84611c2019-03-15 09:21:10 +08007562 * @param subId the id of the subscription to require tethering.
Amit Mahajanfe58cdf2017-07-11 12:01:53 -07007563 * @return {@code true} if DUN APN is required for tethering.
Junda Liu475951f2014-11-07 16:45:03 -08007564 * @hide
7565 */
7566 @Override
SongFerngWangf08d8122019-11-15 14:58:44 +08007567 public boolean isTetheringApnRequiredForSubscriber(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08007568 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007569 final long identity = Binder.clearCallingIdentity();
Miaoa84611c2019-03-15 09:21:10 +08007570 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007571 try {
Miaoa84611c2019-03-15 09:21:10 +08007572 if (phone != null) {
7573 return phone.hasMatchedTetherApnSetting();
7574 } else {
7575 return false;
7576 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007577 } finally {
7578 Binder.restoreCallingIdentity(identity);
Junda Liu475951f2014-11-07 16:45:03 -08007579 }
Junda Liu475951f2014-11-07 16:45:03 -08007580 }
7581
7582 /**
Malcolm Chen964682d2017-11-28 16:20:07 -08007583 * Get the user enabled state of Mobile Data.
7584 *
7585 * TODO: remove and use isUserDataEnabled.
7586 * This can't be removed now because some vendor codes
7587 * calls through ITelephony directly while they should
7588 * use TelephonyManager.
7589 *
7590 * @return true on enabled
7591 */
7592 @Override
7593 public boolean getDataEnabled(int subId) {
7594 return isUserDataEnabled(subId);
7595 }
7596
7597 /**
7598 * Get whether mobile data is enabled per user setting.
7599 *
7600 * There are other factors deciding whether mobile data is actually enabled, but they are
7601 * not considered here. See {@link #isDataEnabled(int)} for more details.
Robert Greenwalt646120a2014-05-23 11:54:03 -07007602 *
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007603 * Accepts either READ_BASIC_PHONE_STATE, ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE
7604 * or carrier privileges.
Robert Greenwalted86e582014-05-21 20:03:20 -07007605 *
7606 * @return {@code true} if data is enabled else {@code false}
7607 */
7608 @Override
Malcolm Chen964682d2017-11-28 16:20:07 -08007609 public boolean isUserDataEnabled(int subId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007610 String functionName = "isUserDataEnabled";
Robert Greenwalt646120a2014-05-23 11:54:03 -07007611 try {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007612 try {
7613 mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
7614 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007615 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007616 mApp.enforceCallingOrSelfPermission(permission.ACCESS_NETWORK_STATE, functionName);
7617 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007618 } catch (SecurityException e) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007619 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007620 mApp, subId, functionName);
7621
Robert Greenwalt646120a2014-05-23 11:54:03 -07007622 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007623
7624 final long identity = Binder.clearCallingIdentity();
7625 try {
Jack Yu285100e2022-12-02 22:48:35 -08007626 int phoneId = SubscriptionManager.getPhoneId(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007627 if (DBG) log("isUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
7628 Phone phone = PhoneFactory.getPhone(phoneId);
7629 if (phone != null) {
7630 boolean retVal = phone.isUserDataEnabled();
7631 if (DBG) log("isUserDataEnabled: subId=" + subId + " retVal=" + retVal);
7632 return retVal;
7633 } else {
7634 if (DBG) loge("isUserDataEnabled: no phone subId=" + subId + " retVal=false");
7635 return false;
7636 }
7637 } finally {
7638 Binder.restoreCallingIdentity(identity);
Malcolm Chen964682d2017-11-28 16:20:07 -08007639 }
7640 }
7641
7642 /**
Shuo Qian8ee4e882020-01-08 14:30:06 -08007643 * Checks if the device is capable of mobile data by considering whether whether the
7644 * user has enabled mobile data, whether the carrier has enabled mobile data, and
7645 * whether the network policy allows data connections.
Malcolm Chen964682d2017-11-28 16:20:07 -08007646 *
Shuo Qian8ee4e882020-01-08 14:30:06 -08007647 * @return {@code true} if the overall data connection is capable; {@code false} if not.
Malcolm Chen964682d2017-11-28 16:20:07 -08007648 */
7649 @Override
7650 public boolean isDataEnabled(int subId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007651 String functionName = "isDataEnabled";
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007652 try {
7653 try {
7654 mApp.enforceCallingOrSelfPermission(
7655 android.Manifest.permission.ACCESS_NETWORK_STATE,
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007656 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007657 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007658 try {
7659 mApp.enforceCallingOrSelfPermission(
7660 android.Manifest.permission.READ_PHONE_STATE,
7661 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007662 } catch (SecurityException e2) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007663 mApp.enforceCallingOrSelfPermission(
7664 permission.READ_BASIC_PHONE_STATE, functionName);
7665 }
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007666 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007667 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007668 enforceReadPrivilegedPermission(functionName);
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007669 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007670
7671 final long identity = Binder.clearCallingIdentity();
7672 try {
Jack Yu285100e2022-12-02 22:48:35 -08007673 int phoneId = SubscriptionManager.getPhoneId(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007674 Phone phone = PhoneFactory.getPhone(phoneId);
7675 if (phone != null) {
Sarah Chine04784a2022-10-31 20:32:34 -07007676 boolean retVal = phone.getDataSettingsManager().isDataEnabled();
Jack Yu4ad64e52021-12-03 14:23:53 -08007677 if (DBG) log("isDataEnabled: " + retVal + ", subId=" + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007678 return retVal;
7679 } else {
7680 if (DBG) loge("isDataEnabled: no phone subId=" + subId + " retVal=false");
7681 return false;
7682 }
7683 } finally {
7684 Binder.restoreCallingIdentity(identity);
Wink Savillee7353bb2014-12-05 14:21:41 -08007685 }
Robert Greenwalted86e582014-05-21 20:03:20 -07007686 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07007687
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007688 /**
7689 * Check if data is enabled for a specific reason
7690 * @param subId Subscription index
7691 * @param reason the reason the data enable change is taking place
7692 * @return {@code true} if the overall data is enabled; {@code false} if not.
7693 */
7694 @Override
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007695 public boolean isDataEnabledForReason(int subId,
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007696 @TelephonyManager.DataEnabledReason int reason) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007697 String functionName = "isDataEnabledForReason";
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007698 try {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007699 try {
7700 mApp.enforceCallingOrSelfPermission(
7701 android.Manifest.permission.ACCESS_NETWORK_STATE,
7702 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007703 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007704 mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
7705 functionName);
7706 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007707 } catch (SecurityException e) {
Sooraj Sasindran0d909a02021-11-08 12:01:16 -08007708 try {
7709 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007710 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007711 } catch (SecurityException e2) {
Sooraj Sasindran0d909a02021-11-08 12:01:16 -08007712 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007713 mApp, subId, functionName);
Sooraj Sasindran0d909a02021-11-08 12:01:16 -08007714 }
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007715 }
7716
7717
7718 final long identity = Binder.clearCallingIdentity();
7719 try {
Jack Yu285100e2022-12-02 22:48:35 -08007720 int phoneId = SubscriptionManager.getPhoneId(subId);
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007721 if (DBG) {
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007722 log("isDataEnabledForReason: subId=" + subId + " phoneId=" + phoneId
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007723 + " reason=" + reason);
7724 }
7725 Phone phone = PhoneFactory.getPhone(phoneId);
7726 if (phone != null) {
7727 boolean retVal;
Jack Yu7968c6d2022-07-31 00:43:21 -07007728 retVal = phone.getDataSettingsManager().isDataEnabledForReason(reason);
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007729 if (DBG) log("isDataEnabledForReason: retVal=" + retVal);
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007730 return retVal;
7731 } else {
7732 if (DBG) {
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007733 loge("isDataEnabledForReason: no phone subId="
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007734 + subId + " retVal=false");
7735 }
7736 return false;
7737 }
7738 } finally {
7739 Binder.restoreCallingIdentity(identity);
7740 }
7741 }
7742
Shishir Agrawal60f9c952014-06-23 12:00:43 -07007743 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08007744 public int getCarrierPrivilegeStatus(int subId) {
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007745 // No permission needed; this only lets the caller inspect their own status.
7746 return getCarrierPrivilegeStatusForUidWithPermission(subId, Binder.getCallingUid());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07007747 }
Junda Liu29340342014-07-10 15:23:27 -07007748
7749 @Override
Jeff Davidson7e17e312018-02-13 18:17:36 -08007750 public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08007751 enforceReadPrivilegedPermission("getCarrierPrivilegeStatusForUid");
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007752 return getCarrierPrivilegeStatusForUidWithPermission(subId, uid);
7753 }
7754
7755 private int getCarrierPrivilegeStatusForUidWithPermission(int subId, int uid) {
7756 Phone phone = getPhone(subId);
Jeff Davidson7e17e312018-02-13 18:17:36 -08007757 if (phone == null) {
Taesu Leef8fbed92019-10-07 18:47:02 +09007758 loge("getCarrierPrivilegeStatusForUid: Invalid subId");
Jeff Davidson7e17e312018-02-13 18:17:36 -08007759 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
7760 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007761 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7762 if (cpt == null) {
7763 loge("getCarrierPrivilegeStatusForUid: No CarrierPrivilegesTracker");
Jeff Davidson7e17e312018-02-13 18:17:36 -08007764 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
7765 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007766 return cpt.getCarrierPrivilegeStatusForUid(uid);
Jeff Davidson7e17e312018-02-13 18:17:36 -08007767 }
7768
7769 @Override
chen xuf7e9fe82019-05-09 19:31:02 -07007770 public int checkCarrierPrivilegesForPackage(int subId, String pkgName) {
Nazanin1adf4562021-03-29 15:35:30 -07007771 enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackage");
chen xuf7e9fe82019-05-09 19:31:02 -07007772 if (TextUtils.isEmpty(pkgName)) {
Junda Liu317d70b2016-03-08 09:33:53 -08007773 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
chen xuf7e9fe82019-05-09 19:31:02 -07007774 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007775 Phone phone = getPhone(subId);
7776 if (phone == null) {
7777 loge("checkCarrierPrivilegesForPackage: Invalid subId");
7778 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
7779 }
7780 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7781 if (cpt == null) {
7782 loge("checkCarrierPrivilegesForPackage: No CarrierPrivilegesTracker");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07007783 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
7784 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007785 return cpt.getCarrierPrivilegeStatusForPackage(pkgName);
Zach Johnson50ecba32015-05-19 00:24:21 -07007786 }
7787
7788 @Override
7789 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007790 enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackageAnyPhone");
Rambo Wange7209ce2022-02-23 13:41:02 -08007791 return checkCarrierPrivilegesForPackageAnyPhoneWithPermission(pkgName);
7792 }
7793
7794 private int checkCarrierPrivilegesForPackageAnyPhoneWithPermission(String pkgName) {
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007795 if (TextUtils.isEmpty(pkgName)) {
Junda Liu317d70b2016-03-08 09:33:53 -08007796 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007797 }
Zach Johnson50ecba32015-05-19 00:24:21 -07007798 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007799 for (int phoneId = 0; phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) {
7800 Phone phone = PhoneFactory.getPhone(phoneId);
7801 if (phone == null) {
7802 continue;
Zach Johnson50ecba32015-05-19 00:24:21 -07007803 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007804 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7805 if (cpt == null) {
7806 continue;
7807 }
7808 result = cpt.getCarrierPrivilegeStatusForPackage(pkgName);
Zach Johnson50ecba32015-05-19 00:24:21 -07007809 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
7810 break;
7811 }
7812 }
Zach Johnson50ecba32015-05-19 00:24:21 -07007813 return result;
Junda Liu29340342014-07-10 15:23:27 -07007814 }
Derek Tan89e89d42014-07-08 17:00:10 -07007815
7816 @Override
Junda Liue64de782015-04-16 17:19:16 -07007817 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
Nazanin1adf4562021-03-29 15:35:30 -07007818 enforceReadPrivilegedPermission("getCarrierPackageNamesForIntentAndPhone");
Rambo Wang8a247eb2022-02-08 21:11:18 +00007819 Phone phone = PhoneFactory.getPhone(phoneId);
7820 if (phone == null) {
7821 return Collections.emptyList();
Junda Liue64de782015-04-16 17:19:16 -07007822 }
Rambo Wang8a247eb2022-02-08 21:11:18 +00007823 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7824 if (cpt == null) {
7825 return Collections.emptyList();
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07007826 }
Rambo Wang8a247eb2022-02-08 21:11:18 +00007827 return cpt.getCarrierPackageNamesForIntent(intent);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07007828 }
7829
Amith Yamasani6e118872016-02-19 12:53:51 -08007830 @Override
chen xuf7e9fe82019-05-09 19:31:02 -07007831 public List<String> getPackagesWithCarrierPrivileges(int phoneId) {
Nazanin1adf4562021-03-29 15:35:30 -07007832 enforceReadPrivilegedPermission("getPackagesWithCarrierPrivileges");
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007833 Phone phone = PhoneFactory.getPhone(phoneId);
7834 if (phone == null) {
7835 return Collections.emptyList();
Amith Yamasani6e118872016-02-19 12:53:51 -08007836 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007837 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7838 if (cpt == null) {
7839 return Collections.emptyList();
7840 }
7841 return new ArrayList<>(cpt.getPackagesWithCarrierPrivileges());
Amith Yamasani6e118872016-02-19 12:53:51 -08007842 }
7843
chen xuf7e9fe82019-05-09 19:31:02 -07007844 @Override
7845 public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
Shuo Qian067a06d2019-12-03 23:40:18 +00007846 enforceReadPrivilegedPermission("getPackagesWithCarrierPrivilegesForAllPhones");
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007847 Set<String> privilegedPackages = new ArraySet<>();
Shuo Qian067a06d2019-12-03 23:40:18 +00007848 final long identity = Binder.clearCallingIdentity();
Shuo Qian067a06d2019-12-03 23:40:18 +00007849 try {
7850 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
7851 privilegedPackages.addAll(getPackagesWithCarrierPrivileges(i));
7852 }
7853 } finally {
7854 Binder.restoreCallingIdentity(identity);
chen xuf7e9fe82019-05-09 19:31:02 -07007855 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007856 return new ArrayList<>(privilegedPackages);
chen xuf7e9fe82019-05-09 19:31:02 -07007857 }
7858
Rambo Wang6812ffb2022-03-15 16:54:17 -07007859 @Override
7860 public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
7861 enforceReadPrivilegedPermission("getCarrierServicePackageNameForLogicalSlot");
7862
7863 final Phone phone = PhoneFactory.getPhone(logicalSlotIndex);
7864 if (phone == null) {
7865 return null;
7866 }
7867 final CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7868 if (cpt == null) {
7869 return null;
7870 }
7871 return cpt.getCarrierServicePackageName();
7872 }
7873
Wink Savilleb564aae2014-10-23 10:18:09 -07007874 private String getIccId(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07007875 final Phone phone = getPhone(subId);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00007876 UiccPort port = phone == null ? null : phone.getUiccPort();
7877 if (port == null) {
Derek Tan97ebb422014-09-05 16:55:38 -07007878 return null;
7879 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00007880 String iccId = port.getIccId();
Derek Tan97ebb422014-09-05 16:55:38 -07007881 if (TextUtils.isEmpty(iccId)) {
Derek Tan97ebb422014-09-05 16:55:38 -07007882 return null;
7883 }
7884 return iccId;
7885 }
7886
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07007887 @Override
Shuo Qiane4e11672020-12-15 22:15:33 -08007888 public void setCallComposerStatus(int subId, int status) {
7889 enforceModifyPermission();
7890
7891 final long identity = Binder.clearCallingIdentity();
7892 try {
7893 Phone phone = getPhone(subId);
7894 if (phone != null) {
7895 Phone defaultPhone = phone.getImsPhone();
7896 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
7897 ImsPhone imsPhone = (ImsPhone) defaultPhone;
7898 imsPhone.setCallComposerStatus(status);
Shuo Qian284ae752020-12-22 19:10:14 -08007899 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
7900 .updateImsServiceConfig();
Shuo Qiane4e11672020-12-15 22:15:33 -08007901 }
7902 }
Shuo Qian284ae752020-12-22 19:10:14 -08007903 } catch (ImsException e) {
7904 throw new ServiceSpecificException(e.getCode());
7905 } finally {
Shuo Qiane4e11672020-12-15 22:15:33 -08007906 Binder.restoreCallingIdentity(identity);
7907 }
7908 }
7909
7910 @Override
7911 public int getCallComposerStatus(int subId) {
7912 enforceReadPrivilegedPermission("getCallComposerStatus");
7913
7914 final long identity = Binder.clearCallingIdentity();
7915 try {
7916 Phone phone = getPhone(subId);
7917 if (phone != null) {
7918 Phone defaultPhone = phone.getImsPhone();
7919 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
7920 ImsPhone imsPhone = (ImsPhone) defaultPhone;
7921 return imsPhone.getCallComposerStatus();
7922 }
7923 }
7924 } finally {
7925 Binder.restoreCallingIdentity(identity);
7926 }
7927 return TelephonyManager.CALL_COMPOSER_STATUS_OFF;
7928 }
7929
7930 @Override
Jeff Sharkey85190e62014-12-05 09:40:12 -08007931 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
7932 String number) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08007933 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
Jeff Davidson7e17e312018-02-13 18:17:36 -08007934 subId, "setLine1NumberForDisplayForSubscriber");
Derek Tan97ebb422014-09-05 16:55:38 -07007935
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007936 final long identity = Binder.clearCallingIdentity();
7937 try {
7938 final String iccId = getIccId(subId);
7939 final Phone phone = getPhone(subId);
7940 if (phone == null) {
7941 return false;
7942 }
7943 final String subscriberId = phone.getSubscriberId();
7944
7945 if (DBG_MERGE) {
Amit Mahajanb8f13202020-01-27 18:16:07 -08007946 Rlog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007947 + subscriberId + " to " + number);
7948 }
7949
7950 if (TextUtils.isEmpty(iccId)) {
7951 return false;
7952 }
7953
7954 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
7955
7956 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
7957 if (alphaTag == null) {
7958 editor.remove(alphaTagPrefKey);
7959 } else {
7960 editor.putString(alphaTagPrefKey, alphaTag);
7961 }
7962
7963 // Record both the line number and IMSI for this ICCID, since we need to
7964 // track all merged IMSIs based on line number
7965 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
7966 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
7967 if (number == null) {
7968 editor.remove(numberPrefKey);
7969 editor.remove(subscriberPrefKey);
7970 } else {
7971 editor.putString(numberPrefKey, number);
7972 editor.putString(subscriberPrefKey, subscriberId);
7973 }
7974
7975 editor.commit();
7976 return true;
7977 } finally {
7978 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07007979 }
Derek Tan7226c842014-07-02 17:42:23 -07007980 }
7981
7982 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07007983 public String getLine1NumberForDisplay(int subId, String callingPackage,
7984 String callingFeatureId) {
Makoto Onukifee69342015-06-29 14:44:50 -07007985 // This is open to apps with WRITE_SMS.
Jeff Davidson7e17e312018-02-13 18:17:36 -08007986 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07007987 mApp, subId, callingPackage, callingFeatureId, "getLine1NumberForDisplay")) {
Amit Mahajan9cf11512015-11-09 11:40:48 -08007988 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
Svet Ganovb320e182015-04-16 12:30:10 -07007989 return null;
7990 }
Derek Tan97ebb422014-09-05 16:55:38 -07007991
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007992 final long identity = Binder.clearCallingIdentity();
7993 try {
7994 String iccId = getIccId(subId);
7995 if (iccId != null) {
7996 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
7997 if (DBG_MERGE) {
7998 log("getLine1NumberForDisplay returning "
7999 + mTelephonySharedPreferences.getString(numberPrefKey, null));
8000 }
8001 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Amit Mahajan9cf11512015-11-09 11:40:48 -08008002 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008003 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
8004 return null;
8005 } finally {
8006 Binder.restoreCallingIdentity(identity);
Derek Tan7226c842014-07-02 17:42:23 -07008007 }
Derek Tan7226c842014-07-02 17:42:23 -07008008 }
8009
8010 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008011 public String getLine1AlphaTagForDisplay(int subId, String callingPackage,
8012 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08008013 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008014 mApp, subId, callingPackage, callingFeatureId, "getLine1AlphaTagForDisplay")) {
Svet Ganovb320e182015-04-16 12:30:10 -07008015 return null;
8016 }
Derek Tan97ebb422014-09-05 16:55:38 -07008017
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008018 final long identity = Binder.clearCallingIdentity();
8019 try {
8020 String iccId = getIccId(subId);
8021 if (iccId != null) {
8022 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
8023 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
8024 }
8025 return null;
8026 } finally {
8027 Binder.restoreCallingIdentity(identity);
Derek Tan7226c842014-07-02 17:42:23 -07008028 }
Derek Tan7226c842014-07-02 17:42:23 -07008029 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07008030
8031 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008032 public String[] getMergedSubscriberIds(int subId, String callingPackage,
8033 String callingFeatureId) {
Jeff Davidson913390f2018-02-23 17:11:49 -08008034 // This API isn't public, so no need to provide a valid subscription ID - we're not worried
8035 // about carrier-privileged callers not having access.
Jeff Davidson7e17e312018-02-13 18:17:36 -08008036 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08008037 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008038 callingFeatureId, "getMergedSubscriberIds")) {
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008039 return null;
8040 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08008041
Jordan Liub49b04b2019-05-06 14:45:15 -07008042 // Clear calling identity, when calling TelephonyManager, because callerUid must be
8043 // the process, where TelephonyManager was instantiated.
8044 // Otherwise AppOps check will fail.
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008045 final long identity = Binder.clearCallingIdentity();
8046 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008047 final Context context = mApp;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008048 final TelephonyManager tele = TelephonyManager.from(context);
8049 final SubscriptionManager sub = SubscriptionManager.from(context);
8050
8051 // Figure out what subscribers are currently active
8052 final ArraySet<String> activeSubscriberIds = new ArraySet<>();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008053
Jordan Liub49b04b2019-05-06 14:45:15 -07008054 // Only consider subs which match the current subId
8055 // This logic can be simplified. See b/131189269 for progress.
8056 if (isActiveSubscription(subId)) {
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008057 activeSubscriberIds.add(tele.getSubscriberId(subId));
8058 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008059
8060 // First pass, find a number override for an active subscriber
8061 String mergeNumber = null;
8062 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
8063 for (String key : prefs.keySet()) {
8064 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
8065 final String subscriberId = (String) prefs.get(key);
8066 if (activeSubscriberIds.contains(subscriberId)) {
8067 final String iccId = key.substring(
8068 PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
8069 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
8070 mergeNumber = (String) prefs.get(numberKey);
8071 if (DBG_MERGE) {
Amit Mahajanb8f13202020-01-27 18:16:07 -08008072 Rlog.d(LOG_TAG, "Found line number " + mergeNumber
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008073 + " for active subscriber " + subscriberId);
8074 }
8075 if (!TextUtils.isEmpty(mergeNumber)) {
8076 break;
8077 }
8078 }
8079 }
8080 }
8081
8082 // Shortcut when no active merged subscribers
8083 if (TextUtils.isEmpty(mergeNumber)) {
8084 return null;
8085 }
8086
8087 // Second pass, find all subscribers under that line override
8088 final ArraySet<String> result = new ArraySet<>();
8089 for (String key : prefs.keySet()) {
8090 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
8091 final String number = (String) prefs.get(key);
8092 if (mergeNumber.equals(number)) {
8093 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
8094 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
8095 final String subscriberId = (String) prefs.get(subscriberKey);
8096 if (!TextUtils.isEmpty(subscriberId)) {
8097 result.add(subscriberId);
8098 }
8099 }
8100 }
8101 }
8102
8103 final String[] resultArray = result.toArray(new String[result.size()]);
8104 Arrays.sort(resultArray);
8105 if (DBG_MERGE) {
Amit Mahajanb8f13202020-01-27 18:16:07 -08008106 Rlog.d(LOG_TAG,
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008107 "Found subscribers " + Arrays.toString(resultArray) + " after merge");
8108 }
8109 return resultArray;
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008110 } finally {
8111 Binder.restoreCallingIdentity(identity);
Jeff Sharkey85190e62014-12-05 09:40:12 -08008112 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08008113 }
8114
8115 @Override
zoey chen38003472019-12-13 17:16:31 +08008116 public String[] getMergedImsisFromGroup(int subId, String callingPackage) {
8117 enforceReadPrivilegedPermission("getMergedImsisFromGroup");
Malcolm Chen6ca97372019-07-01 16:28:21 -07008118
8119 final long identity = Binder.clearCallingIdentity();
8120 try {
8121 final TelephonyManager telephonyManager = mApp.getSystemService(
8122 TelephonyManager.class);
8123 String subscriberId = telephonyManager.getSubscriberId(subId);
8124 if (subscriberId == null) {
8125 if (DBG) {
zoey chen38003472019-12-13 17:16:31 +08008126 log("getMergedImsisFromGroup can't find subscriberId for subId "
Malcolm Chen6ca97372019-07-01 16:28:21 -07008127 + subId);
8128 }
8129 return null;
8130 }
8131
Jack Yu285100e2022-12-02 22:48:35 -08008132 ParcelUuid groupUuid;
8133 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008134 final SubscriptionInfo info = getSubscriptionManagerService()
Jack Yu285100e2022-12-02 22:48:35 -08008135 .getSubscriptionInfo(subId);
8136 groupUuid = info.getGroupUuid();
8137 } else {
8138 final SubscriptionInfo info = mSubscriptionController
8139 .getSubscriptionInfo(subId);
8140 groupUuid = info.getGroupUuid();
8141 }
Malcolm Chen6ca97372019-07-01 16:28:21 -07008142 // If it doesn't belong to any group, return just subscriberId of itself.
8143 if (groupUuid == null) {
8144 return new String[]{subscriberId};
8145 }
8146
8147 // Get all subscriberIds from the group.
8148 final List<String> mergedSubscriberIds = new ArrayList<>();
Jack Yu285100e2022-12-02 22:48:35 -08008149 List<SubscriptionInfo> groupInfos;
8150 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008151 groupInfos = getSubscriptionManagerService()
Jack Yu285100e2022-12-02 22:48:35 -08008152 .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
8153 mApp.getAttributionTag());
8154 } else {
8155 groupInfos = mSubscriptionController
8156 .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
8157 mApp.getAttributionTag());
8158 }
Malcolm Chen6ca97372019-07-01 16:28:21 -07008159 for (SubscriptionInfo subInfo : groupInfos) {
8160 subscriberId = telephonyManager.getSubscriberId(subInfo.getSubscriptionId());
8161 if (subscriberId != null) {
8162 mergedSubscriberIds.add(subscriberId);
8163 }
8164 }
8165
8166 return mergedSubscriberIds.toArray(new String[mergedSubscriberIds.size()]);
8167 } finally {
8168 Binder.restoreCallingIdentity(identity);
8169
8170 }
8171 }
8172
8173 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08008174 public boolean setOperatorBrandOverride(int subId, String brand) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08008175 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
Jeff Davidson7e17e312018-02-13 18:17:36 -08008176 subId, "setOperatorBrandOverride");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008177
8178 final long identity = Binder.clearCallingIdentity();
8179 try {
8180 final Phone phone = getPhone(subId);
8181 return phone == null ? false : phone.setOperatorBrandOverride(brand);
8182 } finally {
8183 Binder.restoreCallingIdentity(identity);
8184 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07008185 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05008186
8187 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08008188 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08008189 List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
8190 List<String> cdmaNonRoamingList) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08008191 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
8192 mApp, subId, "setRoamingOverride");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008193
8194 final long identity = Binder.clearCallingIdentity();
8195 try {
8196 final Phone phone = getPhone(subId);
8197 if (phone == null) {
8198 return false;
8199 }
8200 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
8201 cdmaNonRoamingList);
8202 } finally {
8203 Binder.restoreCallingIdentity(identity);
Shishir Agrawalc04d9752016-02-19 10:41:00 -08008204 }
Shishir Agrawal621a47c2014-12-01 10:25:09 -08008205 }
8206
8207 @Override
Shuo Qian850e4d6a2018-04-25 21:02:08 +00008208 @Deprecated
8209 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
8210 enforceModifyPermission();
8211
8212 int returnValue = 0;
8213 try {
vagdeviaf9a5b92018-08-15 16:01:53 -07008214 AsyncResult result = (AsyncResult) sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00008215 if(result.exception == null) {
8216 if (result.result != null) {
8217 byte[] responseData = (byte[])(result.result);
8218 if(responseData.length > oemResp.length) {
8219 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
8220 responseData.length + "bytes. Buffer Size is " +
8221 oemResp.length + "bytes.");
8222 }
8223 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
8224 returnValue = responseData.length;
8225 }
8226 } else {
8227 CommandException ex = (CommandException) result.exception;
8228 returnValue = ex.getCommandError().ordinal();
8229 if(returnValue > 0) returnValue *= -1;
8230 }
8231 } catch (RuntimeException e) {
8232 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
8233 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
8234 if(returnValue > 0) returnValue *= -1;
8235 }
8236
8237 return returnValue;
8238 }
8239
8240 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07008241 public int getRadioAccessFamily(int phoneId, String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08008242 Phone phone = PhoneFactory.getPhone(phoneId);
Shuo Qiandee53402020-05-29 14:08:15 -07008243 try {
8244 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07008245 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Shuo Qiandee53402020-05-29 14:08:15 -07008246 mApp, phone.getSubId(), "getRadioAccessFamily");
8247 } catch (SecurityException e) {
8248 EventLog.writeEvent(0x534e4554, "150857259", -1, "Missing Permission");
8249 throw e;
8250 }
chen xub97461a2018-10-26 14:17:57 -07008251 int raf = RadioAccessFamily.RAF_UNKNOWN;
Jeff Davidson913390f2018-02-23 17:11:49 -08008252 if (phone == null) {
chen xub97461a2018-10-26 14:17:57 -07008253 return raf;
Jeff Davidson913390f2018-02-23 17:11:49 -08008254 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008255 final long identity = Binder.clearCallingIdentity();
8256 try {
chen xub97461a2018-10-26 14:17:57 -07008257 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07008258 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
chen xub97461a2018-10-26 14:17:57 -07008259 mApp, phone.getSubId(), "getRadioAccessFamily");
8260 raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008261 } finally {
8262 Binder.restoreCallingIdentity(identity);
8263 }
chen xub97461a2018-10-26 14:17:57 -07008264 return raf;
Wink Saville5d475dd2014-10-17 15:00:58 -07008265 }
Andrew Leedf14ead2014-10-17 14:22:52 -07008266
8267 @Override
Hall Liu82694d52020-12-11 18:22:04 -08008268 public void uploadCallComposerPicture(int subscriptionId, String callingPackage,
Hall Liue31bac62020-12-23 19:16:10 -08008269 String contentType, ParcelFileDescriptor fd, ResultReceiver callback) {
Hall Liu82694d52020-12-11 18:22:04 -08008270 try {
8271 if (!Objects.equals(mApp.getPackageManager().getPackageUid(callingPackage, 0),
8272 Binder.getCallingUid())) {
Tyler Gunnb87925a2021-06-10 14:54:27 -07008273 throw new SecurityException("Invalid package:" + callingPackage);
Hall Liu82694d52020-12-11 18:22:04 -08008274 }
8275 } catch (PackageManager.NameNotFoundException e) {
Tyler Gunnb87925a2021-06-10 14:54:27 -07008276 throw new SecurityException("Invalid package:" + callingPackage);
Hall Liu82694d52020-12-11 18:22:04 -08008277 }
8278 RoleManager rm = mApp.getSystemService(RoleManager.class);
8279 List<String> dialerRoleHolders = rm.getRoleHolders(RoleManager.ROLE_DIALER);
8280 if (!dialerRoleHolders.contains(callingPackage)) {
8281 throw new SecurityException("App must be the dialer role holder to"
8282 + " upload a call composer pic");
8283 }
8284
8285 Executors.newSingleThreadExecutor().execute(() -> {
8286 ByteArrayOutputStream output = new ByteArrayOutputStream(
8287 (int) TelephonyManager.getMaximumCallComposerPictureSize());
8288 InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(fd);
8289 boolean readUntilEnd = false;
8290 int totalBytesRead = 0;
8291 byte[] buffer = new byte[16 * 1024];
8292 while (true) {
8293 int numRead;
8294 try {
8295 numRead = input.read(buffer);
8296 } catch (IOException e) {
8297 try {
8298 fd.checkError();
8299 callback.send(TelephonyManager.CallComposerException.ERROR_INPUT_CLOSED,
8300 null);
8301 } catch (IOException e1) {
8302 // This means that the other side closed explicitly with an error. If this
8303 // happens, log and ignore.
8304 loge("Remote end of call composer picture pipe closed: " + e1);
8305 }
8306 break;
8307 }
8308 if (numRead == -1) {
8309 readUntilEnd = true;
8310 break;
8311 }
8312 totalBytesRead += numRead;
8313 if (totalBytesRead > TelephonyManager.getMaximumCallComposerPictureSize()) {
8314 loge("Too many bytes read for call composer picture: " + totalBytesRead);
8315 try {
8316 input.close();
8317 } catch (IOException e) {
8318 // ignore
8319 }
8320 break;
8321 }
8322 output.write(buffer, 0, numRead);
8323 }
8324 // Generally, the remote end will close the file descriptors. The only case where we
8325 // close is above, where the picture size is too big.
8326
8327 try {
8328 fd.checkError();
8329 } catch (IOException e) {
8330 loge("Remote end for call composer closed with an error: " + e);
8331 return;
8332 }
8333
Hall Liuaa4211e2021-01-20 15:43:39 -08008334 if (!readUntilEnd) {
8335 loge("Did not finish reading entire image; aborting");
8336 return;
8337 }
Hall Liu82694d52020-12-11 18:22:04 -08008338
Hall Liuaa4211e2021-01-20 15:43:39 -08008339 ImageData imageData = new ImageData(output.toByteArray(), contentType, null);
8340 CallComposerPictureManager.getInstance(mApp, subscriptionId).handleUploadToServer(
8341 new CallComposerPictureTransfer.Factory() {},
8342 imageData,
8343 (result) -> {
8344 if (result.first != null) {
8345 ParcelUuid parcelUuid = new ParcelUuid(result.first);
8346 Bundle outputResult = new Bundle();
8347 outputResult.putParcelable(
8348 TelephonyManager.KEY_CALL_COMPOSER_PICTURE_HANDLE, parcelUuid);
8349 callback.send(TelephonyManager.CallComposerException.SUCCESS,
8350 outputResult);
8351 } else {
8352 callback.send(result.second, null);
8353 }
8354 }
8355 );
Hall Liu82694d52020-12-11 18:22:04 -08008356 });
8357 }
8358
8359 @Override
Andrew Leedf14ead2014-10-17 14:22:52 -07008360 public void enableVideoCalling(boolean enable) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008361 final Phone defaultPhone = getDefaultPhone();
Andrew Leedf14ead2014-10-17 14:22:52 -07008362 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008363
8364 final long identity = Binder.clearCallingIdentity();
8365 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008366 ImsManager.getInstance(defaultPhone.getContext(),
8367 defaultPhone.getPhoneId()).setVtSetting(enable);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008368 } finally {
8369 Binder.restoreCallingIdentity(identity);
8370 }
Andrew Leedf14ead2014-10-17 14:22:52 -07008371 }
8372
8373 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008374 public boolean isVideoCallingEnabled(String callingPackage, String callingFeatureId) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008375 final Phone defaultPhone = getDefaultPhone();
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008376 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
8377 callingPackage, callingFeatureId, "isVideoCallingEnabled")) {
Amit Mahajan578e53d2018-03-20 16:18:38 +00008378 return false;
8379 }
Svet Ganovb320e182015-04-16 12:30:10 -07008380
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008381 final long identity = Binder.clearCallingIdentity();
8382 try {
8383 // Check the user preference and the system-level IMS setting. Even if the user has
8384 // enabled video calling, if IMS is disabled we aren't able to support video calling.
8385 // In the long run, we may instead need to check if there exists a connection service
8386 // which can support video calling.
8387 ImsManager imsManager =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008388 ImsManager.getInstance(defaultPhone.getContext(), defaultPhone.getPhoneId());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008389 return imsManager.isVtEnabledByPlatform()
8390 && imsManager.isEnhanced4gLteModeSettingEnabledByUser()
8391 && imsManager.isVtEnabledByUser();
8392 } finally {
8393 Binder.restoreCallingIdentity(identity);
8394 }
Andrew Leedf14ead2014-10-17 14:22:52 -07008395 }
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06008396
Andrew Leea1239f22015-03-02 17:44:07 -08008397 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008398 public boolean canChangeDtmfToneLength(int subId, String callingPackage,
8399 String callingFeatureId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008400 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008401 mApp, subId, callingPackage, callingFeatureId,
8402 "isVideoCallingEnabled")) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008403 return false;
8404 }
8405
8406 final long identity = Binder.clearCallingIdentity();
8407 try {
8408 CarrierConfigManager configManager =
8409 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008410 return configManager.getConfigForSubId(subId)
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008411 .getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
8412 } finally {
8413 Binder.restoreCallingIdentity(identity);
8414 }
Andrew Leea1239f22015-03-02 17:44:07 -08008415 }
8416
8417 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008418 public boolean isWorldPhone(int subId, String callingPackage, String callingFeatureId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008419 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008420 mApp, subId, callingPackage, callingFeatureId, "isVideoCallingEnabled")) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008421 return false;
8422 }
8423
8424 final long identity = Binder.clearCallingIdentity();
8425 try {
8426 CarrierConfigManager configManager =
8427 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008428 return configManager.getConfigForSubId(subId)
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008429 .getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
8430 } finally {
8431 Binder.restoreCallingIdentity(identity);
8432 }
Andrew Leea1239f22015-03-02 17:44:07 -08008433 }
8434
Andrew Lee9431b832015-03-09 18:46:45 -07008435 @Override
8436 public boolean isTtyModeSupported() {
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07008437 TelecomManager telecomManager = mApp.getSystemService(TelecomManager.class);
Wooki Wu1f82f7a2016-02-15 15:59:58 +08008438 return telecomManager.isTtySupported();
Andrew Lee9431b832015-03-09 18:46:45 -07008439 }
8440
8441 @Override
8442 public boolean isHearingAidCompatibilitySupported() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008443 final long identity = Binder.clearCallingIdentity();
8444 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008445 return mApp.getResources().getBoolean(R.bool.hac_enabled);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008446 } finally {
8447 Binder.restoreCallingIdentity(identity);
8448 }
Andrew Lee9431b832015-03-09 18:46:45 -07008449 }
8450
Hall Liuf6668912018-10-31 17:05:23 -07008451 /**
8452 * Determines whether the device currently supports RTT (Real-time text). Based both on carrier
8453 * support for the feature and device firmware support.
8454 *
8455 * @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
8456 */
8457 @Override
8458 public boolean isRttSupported(int subscriptionId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008459 final long identity = Binder.clearCallingIdentity();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008460 final Phone phone = getPhone(subscriptionId);
8461 if (phone == null) {
8462 loge("isRttSupported: no Phone found. Invalid subId:" + subscriptionId);
8463 return false;
8464 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008465 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008466 boolean isCarrierSupported = mApp.getCarrierConfigForSubId(subscriptionId).getBoolean(
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008467 CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
8468 boolean isDeviceSupported =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008469 phone.getContext().getResources().getBoolean(R.bool.config_support_rtt);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008470 return isCarrierSupported && isDeviceSupported;
8471 } finally {
8472 Binder.restoreCallingIdentity(identity);
8473 }
Hall Liu98187582018-01-22 19:15:32 -08008474 }
8475
Hall Liuf6668912018-10-31 17:05:23 -07008476 /**
Hall Liuf2daa022019-07-23 18:39:00 -07008477 * Determines whether the user has turned on RTT. If the carrier wants to ignore the user-set
8478 * RTT setting, will return true if the device and carrier both support RTT.
8479 * Otherwise. only returns true if the device and carrier both also support RTT.
Hall Liuf6668912018-10-31 17:05:23 -07008480 */
8481 public boolean isRttEnabled(int subscriptionId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008482 final long identity = Binder.clearCallingIdentity();
8483 try {
Hall Liu5bab75c2019-12-11 23:58:20 +00008484 boolean isRttSupported = isRttSupported(subscriptionId);
8485 boolean isUserRttSettingOn = Settings.Secure.getInt(
8486 mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
8487 boolean shouldIgnoreUserRttSetting = mApp.getCarrierConfigForSubId(subscriptionId)
8488 .getBoolean(CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL);
8489 return isRttSupported && (isUserRttSettingOn || shouldIgnoreUserRttSetting);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008490 } finally {
8491 Binder.restoreCallingIdentity(identity);
8492 }
Hall Liu3ad5f012018-04-06 16:23:39 -07008493 }
8494
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008495 @Deprecated
8496 @Override
8497 public String getDeviceId(String callingPackage) {
8498 return getDeviceIdWithFeature(callingPackage, null);
8499 }
8500
Sanket Padawe7310cc72015-01-14 09:53:20 -08008501 /**
8502 * Returns the unique device ID of phone, for example, the IMEI for
8503 * GSM and the MEID for CDMA phones. Return null if device ID is not available.
8504 *
8505 * <p>Requires Permission:
8506 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
8507 */
8508 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008509 public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) {
Shuo Qian13d89152021-05-10 23:58:11 -07008510 try {
8511 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
8512 } catch (SecurityException se) {
8513 EventLog.writeEvent(0x534e4554, "186530889", Binder.getCallingUid());
8514 throw new SecurityException("Package " + callingPackage + " does not belong to "
8515 + Binder.getCallingUid());
8516 }
Sanket Padawe7310cc72015-01-14 09:53:20 -08008517 final Phone phone = PhoneFactory.getPhone(0);
Jeff Davidson913390f2018-02-23 17:11:49 -08008518 if (phone == null) {
Sanket Padawe7310cc72015-01-14 09:53:20 -08008519 return null;
8520 }
Jeff Davidson913390f2018-02-23 17:11:49 -08008521 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07008522 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008523 callingPackage, callingFeatureId, "getDeviceId")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08008524 return null;
8525 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008526
8527 final long identity = Binder.clearCallingIdentity();
8528 try {
8529 return phone.getDeviceId();
8530 } finally {
8531 Binder.restoreCallingIdentity(identity);
8532 }
Sanket Padawe7310cc72015-01-14 09:53:20 -08008533 }
8534
Ping Sunc67b7c22016-03-02 19:16:45 +08008535 /**
8536 * {@hide}
8537 * Returns the IMS Registration Status on a particular subid
8538 *
8539 * @param subId
8540 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008541 public boolean isImsRegistered(int subId) {
Ping Sunc67b7c22016-03-02 19:16:45 +08008542 Phone phone = getPhone(subId);
8543 if (phone != null) {
8544 return phone.isImsRegistered();
8545 } else {
8546 return false;
8547 }
8548 }
8549
Santos Cordon7a1885b2015-02-03 11:15:19 -08008550 @Override
Shuo Qian6e6137d2019-10-30 16:33:31 -07008551 public int getSubIdForPhoneAccountHandle(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008552 PhoneAccountHandle phoneAccountHandle, String callingPackage, String callingFeatureId) {
Shuo Qian6e6137d2019-10-30 16:33:31 -07008553 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, getDefaultSubscription(),
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008554 callingPackage, callingFeatureId, "getSubIdForPhoneAccountHandle")) {
Shuo Qian6e6137d2019-10-30 16:33:31 -07008555 throw new SecurityException("Requires READ_PHONE_STATE permission.");
8556 }
8557 final long identity = Binder.clearCallingIdentity();
8558 try {
8559 return PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle);
8560 } finally {
8561 Binder.restoreCallingIdentity(identity);
8562 }
8563 }
8564
8565 @Override
Tyler Gunnf70ed162019-04-03 15:28:53 -07008566 public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
Alireza Forouzan4ac4f982021-03-16 22:18:52 -07008567 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07008568 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008569 mApp,
8570 subscriptionId,
8571 "getPhoneAccountHandleForSubscriptionId, " + "subscriptionId: "
8572 + subscriptionId);
Tyler Gunnf70ed162019-04-03 15:28:53 -07008573 final long identity = Binder.clearCallingIdentity();
8574 try {
8575 Phone phone = getPhone(subscriptionId);
8576 if (phone == null) {
8577 return null;
8578 }
8579 return PhoneUtils.makePstnPhoneAccountHandle(phone);
8580 } finally {
8581 Binder.restoreCallingIdentity(identity);
8582 }
8583 }
8584
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008585 /**
8586 * @return the VoWiFi calling availability.
Nathan Haroldc55097a2015-03-11 18:14:50 -07008587 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008588 public boolean isWifiCallingAvailable(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008589 final long identity = Binder.clearCallingIdentity();
8590 try {
8591 Phone phone = getPhone(subId);
8592 if (phone != null) {
8593 return phone.isWifiCallingEnabled();
8594 } else {
8595 return false;
8596 }
8597 } finally {
8598 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008599 }
Nathan Haroldc55097a2015-03-11 18:14:50 -07008600 }
8601
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008602 /**
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008603 * @return the VT calling availability.
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07008604 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008605 public boolean isVideoTelephonyAvailable(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008606 final long identity = Binder.clearCallingIdentity();
8607 try {
8608 Phone phone = getPhone(subId);
8609 if (phone != null) {
8610 return phone.isVideoEnabled();
8611 } else {
8612 return false;
8613 }
8614 } finally {
8615 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008616 }
8617 }
8618
8619 /**
8620 * @return the IMS registration technology for the MMTEL feature. Valid return values are
8621 * defined in {@link ImsRegistrationImplBase}.
8622 */
8623 public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008624 final long identity = Binder.clearCallingIdentity();
8625 try {
8626 Phone phone = getPhone(subId);
8627 if (phone != null) {
8628 return phone.getImsRegistrationTech();
8629 } else {
8630 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
8631 }
8632 } finally {
8633 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008634 }
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07008635 }
8636
Stuart Scott8eef64f2015-04-08 15:13:54 -07008637 @Override
Sarah Chinecc78c42022-03-31 21:16:48 -07008638 public void factoryReset(int subId, String callingPackage) {
paulhu5a773602019-08-23 19:17:33 +08008639 enforceSettingsPermission();
Stuart Scott981d8582015-04-21 14:09:50 -07008640 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
8641 return;
8642 }
Kai Shif70f46f2021-03-03 13:59:46 -08008643 Phone defaultPhone = getDefaultPhone();
8644 if (defaultPhone != null) {
8645 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
8646 mApp, getDefaultPhone().getSubId(), "factoryReset");
8647 }
Svet Ganovcc087f82015-05-12 20:35:54 -07008648 final long identity = Binder.clearCallingIdentity();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008649
Svet Ganovcc087f82015-05-12 20:35:54 -07008650 try {
Stuart Scott981d8582015-04-21 14:09:50 -07008651 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
8652 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07008653 setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_USER,
Sarah Chinecc78c42022-03-31 21:16:48 -07008654 getDefaultDataEnabled(), callingPackage);
Svet Ganovcc087f82015-05-12 20:35:54 -07008655 setNetworkSelectionModeAutomatic(subId);
SongFerngWang8c6e82e2021-03-02 22:09:29 +08008656 Phone phone = getPhone(subId);
SongFerngWangfd89b102021-05-27 22:44:54 +08008657 cleanUpAllowedNetworkTypes(phone, subId);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008658 setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
Jordan Liu857e73a2021-03-05 16:24:04 -08008659 getPhone(subId).resetCarrierKeysForImsiEncryption();
Svet Ganovcc087f82015-05-12 20:35:54 -07008660 }
Amit Mahajan7dbbd822019-03-13 17:33:47 -07008661 // There has been issues when Sms raw table somehow stores orphan
8662 // fragments. They lead to garbled message when new fragments come
8663 // in and combined with those stale ones. In case this happens again,
8664 // user can reset all network settings which will clean up this table.
8665 cleanUpSmsRawTable(getDefaultPhone().getContext());
Brad Ebingerbc7dd582019-10-17 17:03:22 -07008666 // Clean up IMS settings as well here.
8667 int slotId = getSlotIndex(subId);
8668 if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
8669 ImsManager.getInstance(mApp, slotId).factoryReset();
8670 }
Naina Nallurid63128d2019-09-17 14:10:30 -07008671
Kai Shif70f46f2021-03-03 13:59:46 -08008672 if (defaultPhone == null) {
8673 return;
8674 }
Naina Nallurid63128d2019-09-17 14:10:30 -07008675 // Erase modem config if erase modem on network setting is enabled.
8676 String configValue = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_TELEPHONY,
8677 RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED);
8678 if (configValue != null && Boolean.parseBoolean(configValue)) {
Kai Shif70f46f2021-03-03 13:59:46 -08008679 sendEraseModemConfig(defaultPhone);
Naina Nallurid63128d2019-09-17 14:10:30 -07008680 }
Kai Shif70f46f2021-03-03 13:59:46 -08008681
8682 sendEraseDataInSharedPreferences(defaultPhone);
Svet Ganovcc087f82015-05-12 20:35:54 -07008683 } finally {
8684 Binder.restoreCallingIdentity(identity);
Stuart Scott8eef64f2015-04-08 15:13:54 -07008685 }
8686 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01008687
SongFerngWangfd89b102021-05-27 22:44:54 +08008688 @VisibleForTesting
8689 void cleanUpAllowedNetworkTypes(Phone phone, int subId) {
8690 if (phone == null || !SubscriptionManager.isUsableSubscriptionId(subId)) {
8691 return;
8692 }
8693 long defaultNetworkType = RadioAccessFamily.getRafFromNetworkType(
8694 RILConstants.PREFERRED_NETWORK_MODE);
8695 SubscriptionManager.setSubscriptionProperty(subId,
8696 SubscriptionManager.ALLOWED_NETWORK_TYPES,
8697 "user=" + defaultNetworkType);
8698 phone.loadAllowedNetworksFromSubscriptionDatabase();
8699 phone.setAllowedNetworkTypes(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
8700 defaultNetworkType, null);
8701 }
8702
Amit Mahajan7dbbd822019-03-13 17:33:47 -07008703 private void cleanUpSmsRawTable(Context context) {
8704 ContentResolver resolver = context.getContentResolver();
8705 Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
8706 resolver.delete(uri, null, null);
8707 }
8708
Narayan Kamath1c496c22015-04-16 14:40:19 +01008709 @Override
chen xu5d3637b2019-01-21 23:31:38 -08008710 public String getSimLocaleForSubscriber(int subId) {
8711 enforceReadPrivilegedPermission("getSimLocaleForSubscriber, subId: " + subId);
8712 final Phone phone = getPhone(subId);
8713 if (phone == null) {
8714 log("getSimLocaleForSubscriber, invalid subId");
chen xu2bb91e42019-01-24 14:35:54 -08008715 return null;
chen xu5d3637b2019-01-21 23:31:38 -08008716 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008717 final long identity = Binder.clearCallingIdentity();
8718 try {
Jack Yu285100e2022-12-02 22:48:35 -08008719 SubscriptionInfo info;
8720 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008721 info = getSubscriptionManagerService().getActiveSubscriptionInfo(subId,
Jack Yu285100e2022-12-02 22:48:35 -08008722 phone.getContext().getOpPackageName(),
8723 phone.getContext().getAttributionTag());
8724 if (info == null) {
8725 log("getSimLocaleForSubscriber, inactive subId: " + subId);
8726 return null;
8727 }
8728 } else {
8729 info = mSubscriptionController.getActiveSubscriptionInfo(subId,
8730 phone.getContext().getOpPackageName(),
8731 phone.getContext().getAttributionTag());
8732 if (info == null) {
8733 log("getSimLocaleForSubscriber, inactive subId: " + subId);
8734 return null;
8735 }
chen xu6291c472019-02-04 12:55:53 -08008736 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008737 // Try and fetch the locale from the carrier properties or from the SIM language
8738 // preferences (EF-PL and EF-LI)...
8739 final int mcc = info.getMcc();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008740 String simLanguage = null;
chen xu5d3637b2019-01-21 23:31:38 -08008741 final Locale localeFromDefaultSim = phone.getLocaleFromSimAndCarrierPrefs();
8742 if (localeFromDefaultSim != null) {
8743 if (!localeFromDefaultSim.getCountry().isEmpty()) {
8744 if (DBG) log("Using locale from subId: " + subId + " locale: "
8745 + localeFromDefaultSim);
tom hsu60a8dc52022-10-27 00:10:04 +08008746 return matchLocaleFromSupportedLocaleList(phone, localeFromDefaultSim);
chen xu5d3637b2019-01-21 23:31:38 -08008747 } else {
8748 simLanguage = localeFromDefaultSim.getLanguage();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008749 }
8750 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01008751
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008752 // The SIM language preferences only store a language (e.g. fr = French), not an
8753 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
8754 // the SIM and carrier preferences does not include a country we add the country
8755 // determined from the SIM MCC to provide an exact locale.
zoey chenc730df82019-12-18 17:07:20 +08008756 final Locale mccLocale = LocaleUtils.getLocaleFromMcc(mApp, mcc, simLanguage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008757 if (mccLocale != null) {
chen xu5d3637b2019-01-21 23:31:38 -08008758 if (DBG) log("No locale from SIM, using mcc locale:" + mccLocale);
tom hsu60a8dc52022-10-27 00:10:04 +08008759 return matchLocaleFromSupportedLocaleList(phone, mccLocale);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008760 }
8761
8762 if (DBG) log("No locale found - returning null");
8763 return null;
8764 } finally {
8765 Binder.restoreCallingIdentity(identity);
8766 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01008767 }
8768
tom hsu0b59d292022-09-29 23:49:21 +08008769 @VisibleForTesting
tom hsu60a8dc52022-10-27 00:10:04 +08008770 String matchLocaleFromSupportedLocaleList(Phone phone, @NonNull Locale inputLocale) {
tom hsu0b59d292022-09-29 23:49:21 +08008771 String[] supportedLocale = com.android.internal.app.LocalePicker.getSupportedLocales(
tom hsu60a8dc52022-10-27 00:10:04 +08008772 phone.getContext());
tom hsu0b59d292022-09-29 23:49:21 +08008773 for (String localeTag : supportedLocale) {
tom hsu60a8dc52022-10-27 00:10:04 +08008774 if (LocaleList.matchesLanguageAndScript(inputLocale, Locale.forLanguageTag(localeTag))
8775 && TextUtils.equals(inputLocale.getCountry(),
tom hsu0b59d292022-09-29 23:49:21 +08008776 Locale.forLanguageTag(localeTag).getCountry())) {
8777 return localeTag;
8778 }
8779 }
8780 return inputLocale.toLanguageTag();
8781 }
8782
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008783 /**
8784 * NOTE: this method assumes permission checks are done and caller identity has been cleared.
8785 */
8786 private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
Jack Yu285100e2022-12-02 22:48:35 -08008787 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008788 return getSubscriptionManagerService().getActiveSubscriptionInfoList(
Jack Yu285100e2022-12-02 22:48:35 -08008789 mApp.getOpPackageName(), mApp.getAttributionTag());
8790 }
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008791 return mSubscriptionController.getActiveSubscriptionInfoList(mApp.getOpPackageName(),
Philip P. Moltmann8d34f0c2020-03-05 16:24:02 -08008792 mApp.getAttributionTag());
Narayan Kamath1c496c22015-04-16 14:40:19 +01008793 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008794
Gary Jian3aa9a762022-01-24 16:41:19 +08008795 private ActivityStatsTechSpecificInfo[] mLastModemActivitySpecificInfo = null;
8796 private ModemActivityInfo mLastModemActivityInfo = null;
Chenjie Yu1ba97252018-01-11 18:16:20 -08008797
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008798 /**
Adam Lesinski903a54c2016-04-11 14:49:52 -07008799 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
8800 * representing the state of the modem.
8801 *
Chenjie Yu1ba97252018-01-11 18:16:20 -08008802 * NOTE: The underlying implementation clears the modem state, so there should only ever be one
8803 * caller to it. Everyone should call this class to get cumulative data.
Adam Lesinski903a54c2016-04-11 14:49:52 -07008804 * @hide
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008805 */
8806 @Override
Adam Lesinski903a54c2016-04-11 14:49:52 -07008807 public void requestModemActivityInfo(ResultReceiver result) {
8808 enforceModifyPermission();
vagdeviaf9a5b92018-08-15 16:01:53 -07008809 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008810
8811 final long identity = Binder.clearCallingIdentity();
8812 try {
Shuo Qian8f4750a2020-02-20 17:12:10 -08008813 sendRequestAsync(CMD_GET_MODEM_ACTIVITY_INFO, result, null, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008814 } finally {
8815 Binder.restoreCallingIdentity(identity);
Chenjie Yu1ba97252018-01-11 18:16:20 -08008816 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008817 }
Jack Yu85bd38a2015-11-09 11:34:32 -08008818
Gary Jian76280a42022-12-07 16:18:33 +08008819 // Checks that ModemActivityInfo is valid. Sleep time and Idle time should be
Siddharth Rayb8114062018-06-17 15:02:38 -07008820 // less than total activity duration.
8821 private boolean isModemActivityInfoValid(ModemActivityInfo info) {
8822 if (info == null) {
8823 return false;
8824 }
8825 int activityDurationMs =
Hall Liu49656c02020-10-09 19:00:11 -07008826 (int) (info.getTimestampMillis() - mLastModemActivityInfo.getTimestampMillis());
Gary Jian76280a42022-12-07 16:18:33 +08008827 activityDurationMs += MODEM_ACTIVITY_TIME_OFFSET_CORRECTION_MS;
8828
Hall Liu49656c02020-10-09 19:00:11 -07008829 int totalTxTimeMs = Arrays.stream(info.getTransmitTimeMillis()).sum();
8830
Siddharth Rayb8114062018-06-17 15:02:38 -07008831 return (info.isValid()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008832 && (info.getSleepTimeMillis() <= activityDurationMs)
8833 && (info.getIdleTimeMillis() <= activityDurationMs));
Siddharth Rayb8114062018-06-17 15:02:38 -07008834 }
8835
Gary Jian3aa9a762022-01-24 16:41:19 +08008836 private void updateLastModemActivityInfo(ModemActivityInfo info, int rat, int freq) {
8837 int[] mergedTxTimeMs = new int [ModemActivityInfo.getNumTxPowerLevels()];
8838 int[] txTimeMs = info.getTransmitTimeMillis(rat, freq);
8839 int[] lastModemTxTimeMs = mLastModemActivityInfo.getTransmitTimeMillis(rat, freq);
8840
8841 for (int lvl = 0; lvl < mergedTxTimeMs.length; lvl++) {
8842 mergedTxTimeMs[lvl] = txTimeMs[lvl] + lastModemTxTimeMs[lvl];
8843 }
8844
8845 mLastModemActivityInfo.setTransmitTimeMillis(rat, freq, mergedTxTimeMs);
8846 mLastModemActivityInfo.setReceiveTimeMillis(
8847 rat,
8848 freq,
8849 info.getReceiveTimeMillis(rat, freq)
8850 + mLastModemActivityInfo.getReceiveTimeMillis(rat, freq));
8851 }
8852
8853 private void updateLastModemActivityInfo(ModemActivityInfo info, int rat) {
8854 int[] mergedTxTimeMs = new int [ModemActivityInfo.getNumTxPowerLevels()];
8855 int[] txTimeMs = info.getTransmitTimeMillis(rat);
8856 int[] lastModemTxTimeMs = mLastModemActivityInfo.getTransmitTimeMillis(rat);
8857
8858 for (int lvl = 0; lvl < mergedTxTimeMs.length; lvl++) {
8859 mergedTxTimeMs[lvl] = txTimeMs[lvl] + lastModemTxTimeMs[lvl];
8860 }
8861 mLastModemActivityInfo.setTransmitTimeMillis(rat, mergedTxTimeMs);
8862 mLastModemActivityInfo.setReceiveTimeMillis(
8863 rat,
8864 info.getReceiveTimeMillis(rat) + mLastModemActivityInfo.getReceiveTimeMillis(rat));
8865 }
8866
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008867 /**
8868 * Merge this ModemActivityInfo with mLastModemActivitySpecificInfo
8869 * @param info recent ModemActivityInfo
8870 */
Gary Jian3aa9a762022-01-24 16:41:19 +08008871 private void mergeModemActivityInfo(ModemActivityInfo info) {
8872 List<ActivityStatsTechSpecificInfo> merged = new ArrayList<>();
Kai Shi917fdc62022-11-28 14:01:02 -08008873 ActivityStatsTechSpecificInfo deltaSpecificInfo;
Gary Jian3aa9a762022-01-24 16:41:19 +08008874 boolean matched;
8875 for (int i = 0; i < info.getSpecificInfoLength(); i++) {
8876 matched = false;
8877 int rat = info.getSpecificInfoRat(i);
8878 int freq = info.getSpecificInfoFrequencyRange(i);
8879 //Check each ActivityStatsTechSpecificInfo in this ModemActivityInfo for new rat returns
8880 //Add a new ActivityStatsTechSpecificInfo if is a new rat, and merge with the original
8881 //if it already exists
8882 for (int j = 0; j < mLastModemActivitySpecificInfo.length; j++) {
8883 if (rat == mLastModemActivityInfo.getSpecificInfoRat(j) && !matched) {
8884 //Merged based on frequency range (MMWAVE vs SUB6) for 5G
8885 if (rat == AccessNetworkConstants.AccessNetworkType.NGRAN) {
8886 if (freq == mLastModemActivityInfo.getSpecificInfoFrequencyRange(j)) {
8887 updateLastModemActivityInfo(info, rat, freq);
8888 matched = true;
8889 }
8890 } else {
8891 updateLastModemActivityInfo(info, rat);
8892 matched = true;
8893 }
8894 }
8895 }
8896
8897 if (!matched) {
Kai Shi917fdc62022-11-28 14:01:02 -08008898 deltaSpecificInfo =
Gary Jian3aa9a762022-01-24 16:41:19 +08008899 new ActivityStatsTechSpecificInfo(
8900 rat,
8901 freq,
8902 info.getTransmitTimeMillis(rat, freq),
8903 (int) info.getReceiveTimeMillis(rat, freq));
Kai Shi917fdc62022-11-28 14:01:02 -08008904 merged.addAll(Arrays.asList(deltaSpecificInfo));
Gary Jian3aa9a762022-01-24 16:41:19 +08008905 }
8906 }
8907 merged.addAll(Arrays.asList(mLastModemActivitySpecificInfo));
8908 mLastModemActivitySpecificInfo =
8909 new ActivityStatsTechSpecificInfo[merged.size()];
8910 merged.toArray(mLastModemActivitySpecificInfo);
8911
8912 mLastModemActivityInfo.setTimestamp(info.getTimestampMillis());
8913 mLastModemActivityInfo.setSleepTimeMillis(
8914 info.getSleepTimeMillis()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008915 + mLastModemActivityInfo.getSleepTimeMillis());
Gary Jian3aa9a762022-01-24 16:41:19 +08008916 mLastModemActivityInfo.setIdleTimeMillis(
8917 info.getIdleTimeMillis()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008918 + mLastModemActivityInfo.getIdleTimeMillis());
Kai Shi917fdc62022-11-28 14:01:02 -08008919
8920 mLastModemActivityInfo =
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008921 new ModemActivityInfo(
8922 mLastModemActivityInfo.getTimestampMillis(),
8923 mLastModemActivityInfo.getSleepTimeMillis(),
8924 mLastModemActivityInfo.getIdleTimeMillis(),
8925 mLastModemActivitySpecificInfo);
Kai Shi917fdc62022-11-28 14:01:02 -08008926 }
8927
8928 private ActivityStatsTechSpecificInfo[] deepCopyModemActivitySpecificInfo(
8929 ActivityStatsTechSpecificInfo[] info) {
8930 int infoSize = info.length;
8931 ActivityStatsTechSpecificInfo[] ret = new ActivityStatsTechSpecificInfo[infoSize];
8932 for (int i = 0; i < infoSize; i++) {
8933 ret[i] = new ActivityStatsTechSpecificInfo(
8934 info[i].getRat(), info[i].getFrequencyRange(),
8935 info[i].getTransmitTimeMillis(),
8936 (int) info[i].getReceiveTimeMillis());
8937 }
8938 return ret;
Gary Jian3aa9a762022-01-24 16:41:19 +08008939 }
8940
Jack Yu85bd38a2015-11-09 11:34:32 -08008941 /**
Jack Yu85bd38a2015-11-09 11:34:32 -08008942 * Returns the service state information on specified subscription.
8943 */
8944 @Override
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08008945 public ServiceState getServiceStateForSubscriber(int subId,
8946 boolean renounceFineLocationAccess, boolean renounceCoarseLocationAccess,
8947 String callingPackage, String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08008948 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008949 mApp, subId, callingPackage, callingFeatureId, "getServiceStateForSubscriber")) {
Jack Yu85bd38a2015-11-09 11:34:32 -08008950 return null;
8951 }
8952
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08008953 boolean hasFinePermission = false;
8954 boolean hasCoarsePermission = false;
8955 if (!renounceFineLocationAccess) {
8956 LocationAccessPolicy.LocationPermissionResult fineLocationResult =
8957 LocationAccessPolicy.checkLocationPermission(mApp,
8958 new LocationAccessPolicy.LocationPermissionQuery.Builder()
8959 .setCallingPackage(callingPackage)
8960 .setCallingFeatureId(callingFeatureId)
8961 .setCallingPid(Binder.getCallingPid())
8962 .setCallingUid(Binder.getCallingUid())
8963 .setMethod("getServiceStateForSubscriber")
8964 .setLogAsInfo(true)
8965 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
8966 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
8967 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
8968 .build());
8969 hasFinePermission =
8970 fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
8971 }
Hall Liuf19c44f2018-11-27 14:38:17 -08008972
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08008973 if (!renounceCoarseLocationAccess) {
8974 LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
8975 LocationAccessPolicy.checkLocationPermission(mApp,
8976 new LocationAccessPolicy.LocationPermissionQuery.Builder()
8977 .setCallingPackage(callingPackage)
8978 .setCallingFeatureId(callingFeatureId)
8979 .setCallingPid(Binder.getCallingPid())
8980 .setCallingUid(Binder.getCallingUid())
8981 .setMethod("getServiceStateForSubscriber")
8982 .setLogAsInfo(true)
8983 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
8984 .setMinSdkVersionForFine(Integer.MAX_VALUE)
8985 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
8986 .build());
8987 hasCoarsePermission =
8988 coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
8989 }
Hall Liuf19c44f2018-11-27 14:38:17 -08008990
Jack Yu479f40e2020-10-27 21:29:25 -07008991 final Phone phone = getPhone(subId);
8992 if (phone == null) {
8993 return null;
8994 }
8995
Jordan Liu0f2bc442020-11-18 16:47:37 -08008996 final long identity = Binder.clearCallingIdentity();
8997
Jack Yu479f40e2020-10-27 21:29:25 -07008998 boolean isCallingPackageDataService = phone.getDataServicePackages()
8999 .contains(callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009000 try {
Jordan Liuc437b192020-08-17 10:59:12 -07009001 // isActiveSubId requires READ_PHONE_STATE, which we already check for above
Jack Yu285100e2022-12-02 22:48:35 -08009002 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08009003 SubscriptionInfoInternal subInfo = getSubscriptionManagerService()
Jack Yu285100e2022-12-02 22:48:35 -08009004 .getSubscriptionInfoInternal(subId);
9005 if (subInfo == null || !subInfo.isActive()) {
9006 Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
9007 + "subId=" + subId);
9008 return null;
9009 }
9010 } else {
9011 if (!mSubscriptionController.isActiveSubId(subId, callingPackage,
9012 callingFeatureId)) {
9013 Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
9014 + "subId=" + subId);
9015 return null;
9016 }
Jordan Liuc437b192020-08-17 10:59:12 -07009017 }
9018
Hall Liuf19c44f2018-11-27 14:38:17 -08009019 ServiceState ss = phone.getServiceState();
9020
9021 // Scrub out the location info in ServiceState depending on what level of access
9022 // the caller has.
Jack Yu479f40e2020-10-27 21:29:25 -07009023 if (hasFinePermission || isCallingPackageDataService) return ss;
Malcolm Chen5052de62019-12-30 13:56:38 -08009024 if (hasCoarsePermission) return ss.createLocationInfoSanitizedCopy(false);
9025 return ss.createLocationInfoSanitizedCopy(true);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009026 } finally {
9027 Binder.restoreCallingIdentity(identity);
9028 }
Jack Yu85bd38a2015-11-09 11:34:32 -08009029 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009030
9031 /**
9032 * Returns the URI for the per-account voicemail ringtone set in Phone settings.
9033 *
9034 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
9035 * voicemail ringtone.
9036 * @return The URI for the ringtone to play when receiving a voicemail from a specific
9037 * PhoneAccount.
9038 */
9039 @Override
9040 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009041 final long identity = Binder.clearCallingIdentity();
9042 try {
9043 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
9044 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009045 phone = getDefaultPhone();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009046 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009047
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009048 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone.getContext());
9049 } finally {
9050 Binder.restoreCallingIdentity(identity);
9051 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009052 }
9053
9054 /**
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009055 * Sets the per-account voicemail ringtone.
9056 *
9057 * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
9058 * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
9059 *
9060 * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
9061 * voicemail ringtone.
9062 * @param uri The URI for the ringtone to play when receiving a voicemail from a specific
9063 * PhoneAccount.
9064 */
9065 @Override
9066 public void setVoicemailRingtoneUri(String callingPackage,
9067 PhoneAccountHandle phoneAccountHandle, Uri uri) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009068 final Phone defaultPhone = getDefaultPhone();
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009069 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07009070 TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
9071 if (!TextUtils.equals(callingPackage, tm.getDefaultDialerPackage())) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009072 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9073 mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
9074 "setVoicemailRingtoneUri");
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009075 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009076
9077 final long identity = Binder.clearCallingIdentity();
9078 try {
9079 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
9080 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009081 phone = defaultPhone;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009082 }
9083 VoicemailNotificationSettingsUtil.setRingtoneUri(phone.getContext(), uri);
9084 } finally {
9085 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009086 }
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009087 }
9088
9089 /**
Nancy Chen31f9ba12016-01-06 11:42:12 -08009090 * Returns whether vibration is set for voicemail notification in Phone settings.
9091 *
9092 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
9093 * voicemail vibration setting.
9094 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
9095 */
9096 @Override
9097 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009098 final long identity = Binder.clearCallingIdentity();
9099 try {
9100 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
9101 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009102 phone = getDefaultPhone();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009103 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009104
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009105 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone.getContext());
9106 } finally {
9107 Binder.restoreCallingIdentity(identity);
9108 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009109 }
9110
Youhan Wange64578a2016-05-02 15:32:42 -07009111 /**
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009112 * Sets the per-account voicemail vibration.
9113 *
9114 * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
9115 * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
9116 *
9117 * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
9118 * voicemail vibration setting.
9119 * @param enabled Whether to enable or disable vibration for voicemail notifications from a
9120 * specific PhoneAccount.
9121 */
9122 @Override
9123 public void setVoicemailVibrationEnabled(String callingPackage,
9124 PhoneAccountHandle phoneAccountHandle, boolean enabled) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009125 final Phone defaultPhone = getDefaultPhone();
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009126 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07009127 TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
9128 if (!TextUtils.equals(callingPackage, tm.getDefaultDialerPackage())) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009129 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9130 mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
9131 "setVoicemailVibrationEnabled");
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009132 }
9133
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009134 final long identity = Binder.clearCallingIdentity();
9135 try {
9136 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
9137 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009138 phone = defaultPhone;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009139 }
9140 VoicemailNotificationSettingsUtil.setVibrationEnabled(phone.getContext(), enabled);
9141 } finally {
9142 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009143 }
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009144 }
9145
9146 /**
Youhan Wange64578a2016-05-02 15:32:42 -07009147 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
9148 *
9149 * @throws SecurityException if the caller does not have the required permission
9150 */
arunvoddud7401012022-12-15 16:08:12 +00009151 @VisibleForTesting
9152 public void enforceReadPrivilegedPermission(String message) {
Youhan Wange64578a2016-05-02 15:32:42 -07009153 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Brad Ebinger35c841c2018-10-01 10:40:55 -07009154 message);
Youhan Wange64578a2016-05-02 15:32:42 -07009155 }
9156
9157 /**
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009158 * Make sure either called from same process as self (phone) or IPC caller has send SMS
9159 * permission.
9160 *
9161 * @throws SecurityException if the caller does not have the required permission
9162 */
9163 private void enforceSendSmsPermission() {
9164 mApp.enforceCallingOrSelfPermission(permission.SEND_SMS, null);
9165 }
9166
9167 /**
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +00009168 * Make sure either called from same process as self (phone) or IPC caller has interact across
9169 * users permission.
9170 *
9171 * @throws SecurityException if the caller does not have the required permission
9172 */
9173 private void enforceInteractAcrossUsersPermission(String message) {
9174 mApp.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, message);
9175 }
9176
9177 /**
Ta-wei Yen527a9c02017-01-06 15:29:25 -08009178 * Make sure called from the package in charge of visual voicemail.
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009179 *
Ta-wei Yen527a9c02017-01-06 15:29:25 -08009180 * @throws SecurityException if the caller is not the visual voicemail package.
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009181 */
Ta-wei Yen527a9c02017-01-06 15:29:25 -08009182 private void enforceVisualVoicemailPackage(String callingPackage, int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009183 final long identity = Binder.clearCallingIdentity();
9184 try {
9185 ComponentName componentName =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009186 RemoteVvmTaskManager.getRemotePackage(mApp, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009187 if (componentName == null) {
9188 throw new SecurityException(
9189 "Caller not current active visual voicemail package[null]");
9190 }
9191 String vvmPackage = componentName.getPackageName();
9192 if (!callingPackage.equals(vvmPackage)) {
Hui Wang7f657552022-08-16 16:58:25 +00009193 throw new SecurityException("Caller not current active visual voicemail package");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009194 }
9195 } finally {
9196 Binder.restoreCallingIdentity(identity);
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009197 }
9198 }
9199
9200 /**
Youhan Wange64578a2016-05-02 15:32:42 -07009201 * Return the application ID for the app type.
9202 *
9203 * @param subId the subscription ID that this request applies to.
9204 * @param appType the uicc app type.
9205 * @return Application ID for specificied app type, or null if no uicc.
9206 */
9207 @Override
9208 public String getAidForAppType(int subId, int appType) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009209 enforceReadPrivilegedPermission("getAidForAppType");
Youhan Wange64578a2016-05-02 15:32:42 -07009210 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009211
9212 final long identity = Binder.clearCallingIdentity();
Youhan Wange64578a2016-05-02 15:32:42 -07009213 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009214 if (phone == null) {
9215 return null;
9216 }
9217 String aid = null;
9218 try {
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00009219 aid = UiccController.getInstance().getUiccPort(phone.getPhoneId())
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009220 .getApplicationByType(appType).getAid();
9221 } catch (Exception e) {
9222 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
9223 }
9224 return aid;
9225 } finally {
9226 Binder.restoreCallingIdentity(identity);
Youhan Wange64578a2016-05-02 15:32:42 -07009227 }
Youhan Wange64578a2016-05-02 15:32:42 -07009228 }
9229
Youhan Wang4001d252016-05-11 10:29:41 -07009230 /**
9231 * Return the Electronic Serial Number.
9232 *
9233 * @param subId the subscription ID that this request applies to.
9234 * @return ESN or null if error.
9235 */
9236 @Override
9237 public String getEsn(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009238 enforceReadPrivilegedPermission("getEsn");
Youhan Wang4001d252016-05-11 10:29:41 -07009239 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009240
9241 final long identity = Binder.clearCallingIdentity();
Youhan Wang4001d252016-05-11 10:29:41 -07009242 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009243 if (phone == null) {
9244 return null;
9245 }
9246 String esn = null;
9247 try {
9248 esn = phone.getEsn();
9249 } catch (Exception e) {
9250 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
9251 }
9252 return esn;
9253 } finally {
9254 Binder.restoreCallingIdentity(identity);
Youhan Wang4001d252016-05-11 10:29:41 -07009255 }
Youhan Wang4001d252016-05-11 10:29:41 -07009256 }
9257
Sanket Padawe99ef1e32016-05-18 16:12:33 -07009258 /**
Youhan Wang66ad5d72016-07-18 17:56:58 -07009259 * Return the Preferred Roaming List Version.
9260 *
9261 * @param subId the subscription ID that this request applies to.
9262 * @return PRLVersion or null if error.
9263 */
9264 @Override
9265 public String getCdmaPrlVersion(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009266 enforceReadPrivilegedPermission("getCdmaPrlVersion");
Youhan Wang66ad5d72016-07-18 17:56:58 -07009267 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009268
9269 final long identity = Binder.clearCallingIdentity();
Youhan Wang66ad5d72016-07-18 17:56:58 -07009270 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009271 if (phone == null) {
9272 return null;
9273 }
9274 String cdmaPrlVersion = null;
9275 try {
9276 cdmaPrlVersion = phone.getCdmaPrlVersion();
9277 } catch (Exception e) {
9278 Log.e(LOG_TAG, "Not getting PRLVersion", e);
9279 }
9280 return cdmaPrlVersion;
9281 } finally {
9282 Binder.restoreCallingIdentity(identity);
Youhan Wang66ad5d72016-07-18 17:56:58 -07009283 }
Youhan Wang66ad5d72016-07-18 17:56:58 -07009284 }
9285
9286 /**
Sanket Padawe99ef1e32016-05-18 16:12:33 -07009287 * Get snapshot of Telephony histograms
9288 * @return List of Telephony histograms
9289 * @hide
9290 */
9291 @Override
9292 public List<TelephonyHistogram> getTelephonyHistograms() {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009293 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9294 mApp, getDefaultSubscription(), "getTelephonyHistograms");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009295
9296 final long identity = Binder.clearCallingIdentity();
9297 try {
9298 return RIL.getTelephonyRILTimingHistograms();
9299 } finally {
9300 Binder.restoreCallingIdentity(identity);
9301 }
Sanket Padawe99ef1e32016-05-18 16:12:33 -07009302 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07009303
9304 /**
9305 * {@hide}
Michele Berionne482f8202018-11-27 18:57:59 -08009306 * Set the allowed carrier list and the excluded carrier list, indicating the priority between
9307 * the two lists.
Meng Wang1a7c35a2016-05-05 20:56:15 -07009308 * Require system privileges. In the future we may add this to carrier APIs.
9309 *
Michele Berionne482f8202018-11-27 18:57:59 -08009310 * @return Integer with the result of the operation, as defined in {@link TelephonyManager}.
Meng Wang1a7c35a2016-05-05 20:56:15 -07009311 */
9312 @Override
Michele Berionne482f8202018-11-27 18:57:59 -08009313 @TelephonyManager.SetCarrierRestrictionResult
9314 public int setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules) {
Meng Wang1a7c35a2016-05-05 20:56:15 -07009315 enforceModifyPermission();
vagdeviaf9a5b92018-08-15 16:01:53 -07009316 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009317
Michele Berionne482f8202018-11-27 18:57:59 -08009318 if (carrierRestrictionRules == null) {
9319 throw new NullPointerException("carrier restriction cannot be null");
Meng Wang9b7c4e92017-02-17 11:41:27 -08009320 }
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009321
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009322 final long identity = Binder.clearCallingIdentity();
9323 try {
Michele Berionne482f8202018-11-27 18:57:59 -08009324 return (int) sendRequest(CMD_SET_ALLOWED_CARRIERS, carrierRestrictionRules,
vagdeviaf9a5b92018-08-15 16:01:53 -07009325 workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009326 } finally {
9327 Binder.restoreCallingIdentity(identity);
9328 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07009329 }
9330
9331 /**
9332 * {@hide}
Michele Berionne482f8202018-11-27 18:57:59 -08009333 * Get the allowed carrier list and the excluded carrier list, including the priority between
9334 * the two lists.
Meng Wang1a7c35a2016-05-05 20:56:15 -07009335 * Require system privileges. In the future we may add this to carrier APIs.
9336 *
Michele Berionne482f8202018-11-27 18:57:59 -08009337 * @return {@link android.telephony.CarrierRestrictionRules}
Meng Wang1a7c35a2016-05-05 20:56:15 -07009338 */
9339 @Override
Michele Berionne482f8202018-11-27 18:57:59 -08009340 public CarrierRestrictionRules getAllowedCarriers() {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009341 enforceReadPrivilegedPermission("getAllowedCarriers");
vagdeviaf9a5b92018-08-15 16:01:53 -07009342 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009343
9344 final long identity = Binder.clearCallingIdentity();
9345 try {
Michele Berionne482f8202018-11-27 18:57:59 -08009346 Object response = sendRequest(CMD_GET_ALLOWED_CARRIERS, null, workSource);
9347 if (response instanceof CarrierRestrictionRules) {
9348 return (CarrierRestrictionRules) response;
9349 }
9350 // Response is an Exception of some kind,
9351 // which is signalled to the user as a NULL retval
9352 return null;
9353 } catch (Exception e) {
9354 Log.e(LOG_TAG, "getAllowedCarriers. Exception ex=" + e);
9355 return null;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009356 } finally {
9357 Binder.restoreCallingIdentity(identity);
9358 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07009359 }
9360
fionaxu59545b42016-05-25 15:53:37 -07009361 /**
arunvoddud7401012022-12-15 16:08:12 +00009362 * Fetches the carrier restriction status of the device and sends the status to the caller
9363 * through the callback.
9364 *
9365 * @param callback The callback that will be used to send the result.
9366 * @throws SecurityException if the caller does not have the required permission/privileges or
9367 * the caller is not allowlisted.
9368 */
9369 @Override
9370 public void getCarrierRestrictionStatus(IIntegerConsumer callback, String packageName) {
9371 enforceReadPermission("getCarrierRestrictionStatus");
9372 int carrierId = validateCallerAndGetCarrierId(packageName);
9373 if (carrierId == CarrierAllowListInfo.INVALID_CARRIER_ID) {
9374 Rlog.e(LOG_TAG, "getCarrierRestrictionStatus: caller is not registered");
9375 throw new SecurityException("Not an authorized caller");
9376 }
9377 final long identity = Binder.clearCallingIdentity();
9378 try {
9379 Consumer<Integer> consumer = FunctionalUtils.ignoreRemoteException(callback::accept);
9380 CallerCallbackInfo callbackInfo = new CallerCallbackInfo(consumer, carrierId);
9381 sendRequestAsync(CMD_GET_ALLOWED_CARRIERS, callbackInfo);
9382 } finally {
9383 Binder.restoreCallingIdentity(identity);
9384 }
9385 }
9386
9387 @VisibleForTesting
9388 public int validateCallerAndGetCarrierId(String packageName) {
9389 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mApp);
9390 return allowListInfo.validateCallerAndGetCarrierId(packageName);
9391 }
9392
9393 /**
fionaxu59545b42016-05-25 15:53:37 -07009394 * Action set from carrier signalling broadcast receivers to enable/disable radio
9395 * @param subId the subscription ID that this action applies to.
9396 * @param enabled control enable or disable radio.
9397 * {@hide}
9398 */
9399 @Override
9400 public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
9401 enforceModifyPermission();
9402 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009403
9404 final long identity = Binder.clearCallingIdentity();
fionaxu59545b42016-05-25 15:53:37 -07009405 if (phone == null) {
9406 loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
9407 return;
9408 }
9409 try {
9410 phone.carrierActionSetRadioEnabled(enabled);
9411 } catch (Exception e) {
9412 Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009413 } finally {
9414 Binder.restoreCallingIdentity(identity);
fionaxu59545b42016-05-25 15:53:37 -07009415 }
9416 }
9417
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07009418 /**
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07009419 * Enable or disable Voice over NR (VoNR)
9420 * @param subId the subscription ID that this action applies to.
9421 * @param enabled enable or disable VoNR.
9422 * @return operation result.
9423 */
9424 @Override
9425 public int setVoNrEnabled(int subId, boolean enabled) {
9426 enforceModifyPermission();
9427 final Phone phone = getPhone(subId);
9428
9429 final long identity = Binder.clearCallingIdentity();
9430 if (phone == null) {
9431 loge("setVoNrEnabled fails with no phone object for subId: " + subId);
9432 return TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
9433 }
9434
9435 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9436 try {
9437 int result = (int) sendRequest(CMD_ENABLE_VONR, enabled, subId,
9438 workSource);
9439 if (DBG) log("setVoNrEnabled result: " + result);
Gary Jian8dd305f2021-10-14 16:31:35 +08009440
9441 if (result == TelephonyManager.ENABLE_VONR_SUCCESS) {
9442 if (DBG) {
9443 log("Set VoNR settings in siminfo db; subId=" + subId + ", value:" + enabled);
9444 }
9445 SubscriptionManager.setSubscriptionProperty(
9446 subId, SubscriptionManager.NR_ADVANCED_CALLING_ENABLED,
9447 (enabled ? "1" : "0"));
9448 }
9449
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07009450 return result;
9451 } finally {
9452 Binder.restoreCallingIdentity(identity);
9453 }
9454 }
9455
9456 /**
9457 * Is voice over NR enabled
9458 * @return true if VoNR is enabled else false
9459 */
9460 @Override
9461 public boolean isVoNrEnabled(int subId) {
9462 enforceReadPrivilegedPermission("isVoNrEnabled");
9463 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9464 final long identity = Binder.clearCallingIdentity();
9465 try {
9466 boolean isEnabled = (boolean) sendRequest(CMD_IS_VONR_ENABLED,
9467 null, subId, workSource);
9468 if (DBG) log("isVoNrEnabled: " + isEnabled);
9469 return isEnabled;
9470 } finally {
9471 Binder.restoreCallingIdentity(identity);
9472 }
9473 }
9474
9475 /**
fionaxu8da9cb12017-05-23 15:02:46 -07009476 * Action set from carrier signalling broadcast receivers to start/stop reporting the default
9477 * network status based on which carrier apps could apply actions accordingly,
9478 * enable/disable default url handler for example.
9479 *
9480 * @param subId the subscription ID that this action applies to.
9481 * @param report control start/stop reporting the default network status.
9482 * {@hide}
9483 */
9484 @Override
9485 public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
9486 enforceModifyPermission();
9487 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009488
9489 final long identity = Binder.clearCallingIdentity();
fionaxu8da9cb12017-05-23 15:02:46 -07009490 if (phone == null) {
9491 loge("carrierAction: ReportDefaultNetworkStatus fails with invalid sibId: " + subId);
9492 return;
9493 }
9494 try {
9495 phone.carrierActionReportDefaultNetworkStatus(report);
9496 } catch (Exception e) {
9497 Log.e(LOG_TAG, "carrierAction: ReportDefaultNetworkStatus fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009498 } finally {
9499 Binder.restoreCallingIdentity(identity);
fionaxu8da9cb12017-05-23 15:02:46 -07009500 }
9501 }
9502
9503 /**
fionaxud9622282017-07-17 17:51:30 -07009504 * Action set from carrier signalling broadcast receivers to reset all carrier actions
9505 * @param subId the subscription ID that this action applies to.
9506 * {@hide}
9507 */
9508 @Override
9509 public void carrierActionResetAll(int subId) {
9510 enforceModifyPermission();
9511 final Phone phone = getPhone(subId);
9512 if (phone == null) {
9513 loge("carrierAction: ResetAll fails with invalid sibId: " + subId);
9514 return;
9515 }
9516 try {
9517 phone.carrierActionResetAll();
9518 } catch (Exception e) {
9519 Log.e(LOG_TAG, "carrierAction: ResetAll fails. Exception ex=" + e);
9520 }
9521 }
9522
9523 /**
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07009524 * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
9525 * bug report is being generated.
9526 */
9527 @Override
Ta-wei Yen99282e02016-06-21 18:19:35 -07009528 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009529 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
9530 != PackageManager.PERMISSION_GRANTED) {
dcashman22b950d2016-06-27 11:39:02 -07009531 writer.println("Permission Denial: can't dump Phone from pid="
9532 + Binder.getCallingPid()
9533 + ", uid=" + Binder.getCallingUid()
9534 + "without permission "
9535 + android.Manifest.permission.DUMP);
9536 return;
9537 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009538 DumpsysHandler.dump(mApp, fd, writer, args);
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07009539 }
Jack Yueb89b242016-06-22 13:27:47 -07009540
Brad Ebingerdac2f002018-04-03 15:17:52 -07009541 @Override
Hall Liua1548bd2019-12-24 14:14:12 -08009542 public int handleShellCommand(@NonNull ParcelFileDescriptor in,
9543 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
9544 @NonNull String[] args) {
9545 return new TelephonyShellCommand(this, getDefaultPhone().getContext()).exec(
9546 this, in.getFileDescriptor(), out.getFileDescriptor(),
Thomas Nguyen8ee49682023-02-01 11:46:09 -08009547 err.getFileDescriptor(), args);
Brad Ebingerdac2f002018-04-03 15:17:52 -07009548 }
9549
Jack Yueb89b242016-06-22 13:27:47 -07009550 /**
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009551 * Policy control of data connection with reason {@@TelephonyManager.DataEnabledReason}
Greg Kaiser17f41752020-05-05 16:47:47 +00009552 * @param subId Subscription index
Sarah Chinecc78c42022-03-31 21:16:48 -07009553 * @param reason The reason the data enable change is taking place.
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009554 * @param enabled True if enabling the data, otherwise disabling.
Sarah Chinecc78c42022-03-31 21:16:48 -07009555 * @param callingPackage The package that changed the data enabled state.
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009556 * @hide
Jack Yu75ab2952016-07-08 14:29:33 -07009557 */
9558 @Override
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07009559 public void setDataEnabledForReason(int subId, @TelephonyManager.DataEnabledReason int reason,
Sarah Chinecc78c42022-03-31 21:16:48 -07009560 boolean enabled, String callingPackage) {
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009561 if (reason == TelephonyManager.DATA_ENABLED_REASON_USER
9562 || reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
9563 try {
9564 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07009565 mApp, subId, "setDataEnabledForReason");
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009566 } catch (SecurityException se) {
9567 enforceModifyPermission();
9568 }
9569 } else {
9570 enforceModifyPermission();
9571 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009572
9573 final long identity = Binder.clearCallingIdentity();
9574 try {
9575 Phone phone = getPhone(subId);
9576 if (phone != null) {
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009577 if (reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
9578 phone.carrierActionSetMeteredApnsEnabled(enabled);
9579 } else {
Jack Yu7968c6d2022-07-31 00:43:21 -07009580 phone.getDataSettingsManager().setDataEnabled(
9581 reason, enabled, callingPackage);
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009582 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009583 }
9584 } finally {
9585 Binder.restoreCallingIdentity(identity);
Jack Yu75ab2952016-07-08 14:29:33 -07009586 }
9587 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009588
9589 /**
9590 * Get Client request stats
9591 * @return List of Client Request Stats
9592 * @hide
9593 */
9594 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009595 public List<ClientRequestStats> getClientRequestStats(String callingPackage,
9596 String callingFeatureId, int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009597 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009598 mApp, subId, callingPackage, callingFeatureId, "getClientRequestStats")) {
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009599 return null;
9600 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009601 Phone phone = getPhone(subId);
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009602
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009603 final long identity = Binder.clearCallingIdentity();
9604 try {
9605 if (phone != null) {
9606 return phone.getClientRequestStats();
9607 }
9608
9609 return null;
9610 } finally {
9611 Binder.restoreCallingIdentity(identity);
9612 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009613 }
9614
Narayan Kamathf04b5a12018-01-09 11:47:15 +00009615 private WorkSource getWorkSource(int uid) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009616 String packageName = mApp.getPackageManager().getNameForUid(uid);
Hunter Knepshieldd03383b2022-03-29 22:47:54 +00009617 if (uid == Process.ROOT_UID && packageName == null) {
9618 // Downstream WorkSource attribution inside the RIL requires both a UID and package name
9619 // to be set for wakelock tracking, otherwise RIL requests fail with a runtime
9620 // exception. ROOT_UID seems not to have a valid package name returned by
9621 // PackageManager, so just fake it here to avoid issues when running telephony shell
9622 // commands that plumb through the RIL as root, like so:
9623 // $ adb root
9624 // $ adb shell cmd phone ...
9625 packageName = "root";
9626 }
Narayan Kamathf04b5a12018-01-09 11:47:15 +00009627 return new WorkSource(uid, packageName);
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009628 }
Jack Yueb4124c2017-02-16 15:32:43 -08009629
9630 /**
Grace Chen70990072017-03-24 17:21:30 -07009631 * Set SIM card power state.
Jack Yueb4124c2017-02-16 15:32:43 -08009632 *
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009633 * @param slotIndex SIM slot id.
Grace Chen70990072017-03-24 17:21:30 -07009634 * @param state State of SIM (power down, power up, pass through)
9635 * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
9636 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
9637 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
Jack Yueb4124c2017-02-16 15:32:43 -08009638 *
9639 **/
9640 @Override
Grace Chen70990072017-03-24 17:21:30 -07009641 public void setSimPowerStateForSlot(int slotIndex, int state) {
Jack Yueb4124c2017-02-16 15:32:43 -08009642 enforceModifyPermission();
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009643 Phone phone = PhoneFactory.getPhone(slotIndex);
9644
vagdeviaf9a5b92018-08-15 16:01:53 -07009645 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9646
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009647 final long identity = Binder.clearCallingIdentity();
9648 try {
9649 if (phone != null) {
Jordan Liu109698e2020-11-24 14:50:34 -08009650 phone.setSimPowerState(state, null, workSource);
9651 }
9652 } finally {
9653 Binder.restoreCallingIdentity(identity);
9654 }
9655 }
9656
9657 /**
9658 * Set SIM card power state.
9659 *
9660 * @param slotIndex SIM slot id.
9661 * @param state State of SIM (power down, power up, pass through)
9662 * @param callback callback to trigger after success or failure
9663 * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
9664 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
9665 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
9666 *
9667 **/
9668 @Override
9669 public void setSimPowerStateForSlotWithCallback(int slotIndex, int state,
9670 IIntegerConsumer callback) {
9671 enforceModifyPermission();
9672 Phone phone = PhoneFactory.getPhone(slotIndex);
9673
9674 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9675
9676 final long identity = Binder.clearCallingIdentity();
9677 try {
9678 if (phone != null) {
9679 Pair<Integer, IIntegerConsumer> arguments = Pair.create(state, callback);
9680 sendRequestAsync(CMD_SET_SIM_POWER, arguments, phone, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009681 }
9682 } finally {
9683 Binder.restoreCallingIdentity(identity);
Jack Yueb4124c2017-02-16 15:32:43 -08009684 }
9685 }
Shuo Qiandd210312017-04-12 22:11:33 +00009686
Tyler Gunn65d45c22017-06-05 11:22:26 -07009687 private boolean isUssdApiAllowed(int subId) {
9688 CarrierConfigManager configManager =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009689 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Tyler Gunn65d45c22017-06-05 11:22:26 -07009690 if (configManager == null) {
9691 return false;
9692 }
9693 PersistableBundle pb = configManager.getConfigForSubId(subId);
9694 if (pb == null) {
9695 return false;
9696 }
9697 return pb.getBoolean(
9698 CarrierConfigManager.KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL);
9699 }
9700
Shuo Qiandd210312017-04-12 22:11:33 +00009701 /**
9702 * Check if phone is in emergency callback mode
9703 * @return true if phone is in emergency callback mode
9704 * @param subId sub id
9705 */
goneil9c5f4872017-12-05 14:07:56 -08009706 @Override
Shuo Qiandd210312017-04-12 22:11:33 +00009707 public boolean getEmergencyCallbackMode(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009708 enforceReadPrivilegedPermission("getEmergencyCallbackMode");
Shuo Qiandd210312017-04-12 22:11:33 +00009709 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009710
9711 final long identity = Binder.clearCallingIdentity();
9712 try {
9713 if (phone != null) {
9714 return phone.isInEcm();
9715 } else {
9716 return false;
9717 }
9718 } finally {
9719 Binder.restoreCallingIdentity(identity);
Shuo Qiandd210312017-04-12 22:11:33 +00009720 }
9721 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08009722
9723 /**
9724 * Get the current signal strength information for the given subscription.
9725 * Because this information is not updated when the device is in a low power state
9726 * it should not be relied-upon to be current.
9727 * @param subId Subscription index
9728 * @return the most recent cached signal strength info from the modem
9729 */
9730 @Override
9731 public SignalStrength getSignalStrength(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009732 final long identity = Binder.clearCallingIdentity();
9733 try {
9734 Phone p = getPhone(subId);
9735 if (p == null) {
9736 return null;
9737 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08009738
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009739 return p.getSignalStrength();
9740 } finally {
9741 Binder.restoreCallingIdentity(identity);
9742 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08009743 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00009744
Pengquan Meng77b7f132018-08-22 14:49:57 -07009745 /**
Chen Xuf792fd62018-10-17 17:54:36 +00009746 * Get the current modem radio state for the given slot.
9747 * @param slotIndex slot index.
9748 * @param callingPackage the name of the package making the call.
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009749 * @param callingFeatureId The feature in the package.
Chen Xuf792fd62018-10-17 17:54:36 +00009750 * @return the current radio power state from the modem
9751 */
9752 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009753 public int getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId) {
Chen Xuf792fd62018-10-17 17:54:36 +00009754 Phone phone = PhoneFactory.getPhone(slotIndex);
9755 if (phone != null) {
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009756 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, phone.getSubId(),
9757 callingPackage, callingFeatureId, "getRadioPowerState")) {
Chen Xuf792fd62018-10-17 17:54:36 +00009758 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
9759 }
9760
9761 final long identity = Binder.clearCallingIdentity();
9762 try {
9763 return phone.getRadioPowerState();
9764 } finally {
9765 Binder.restoreCallingIdentity(identity);
9766 }
9767 }
9768 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
9769 }
9770
9771 /**
Pengquan Meng77b7f132018-08-22 14:49:57 -07009772 * Checks if data roaming is enabled on the subscription with id {@code subId}.
9773 *
9774 * <p>Requires one of the following permissions:
9775 * {@link android.Manifest.permission#ACCESS_NETWORK_STATE},
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009776 * {@link android.Manifest.permission#READ_BASIC_PHONE_STATE},
Pengquan Meng77b7f132018-08-22 14:49:57 -07009777 * {@link android.Manifest.permission#READ_PHONE_STATE} or that the calling app has carrier
9778 * privileges.
9779 *
9780 * @param subId subscription id
9781 * @return {@code true} if data roaming is enabled on this subscription, otherwise return
9782 * {@code false}.
9783 */
9784 @Override
9785 public boolean isDataRoamingEnabled(int subId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009786 String functionName = "isDataRoamingEnabled";
Shuo Qian093013d2020-08-13 15:42:55 -07009787 try {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009788 try {
9789 mApp.enforceCallingOrSelfPermission(
9790 android.Manifest.permission.ACCESS_NETWORK_STATE,
9791 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07009792 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009793 mApp.enforceCallingOrSelfPermission(
9794 permission.READ_BASIC_PHONE_STATE, functionName);
9795 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07009796 } catch (SecurityException e) {
Nathan Harold62c68512021-04-06 11:26:02 -07009797 TelephonyPermissions.enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009798 mApp, subId, functionName);
Shuo Qian093013d2020-08-13 15:42:55 -07009799 }
Pengquan Meng44e66f12019-04-01 10:48:20 -07009800
Pengquan Menga1bb6272018-09-06 09:59:22 -07009801 boolean isEnabled = false;
9802 final long identity = Binder.clearCallingIdentity();
Pengquan Meng77b7f132018-08-22 14:49:57 -07009803 try {
Pengquan Menga1bb6272018-09-06 09:59:22 -07009804 Phone phone = getPhone(subId);
9805 isEnabled = phone != null ? phone.getDataRoamingEnabled() : false;
Pengquan Menga1bb6272018-09-06 09:59:22 -07009806 } finally {
9807 Binder.restoreCallingIdentity(identity);
Pengquan Meng77b7f132018-08-22 14:49:57 -07009808 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07009809 return isEnabled;
Pengquan Meng77b7f132018-08-22 14:49:57 -07009810 }
9811
9812
9813 /**
9814 * Enables/Disables the data roaming on the subscription with id {@code subId}.
9815 *
9816 * <p> Requires permission:
9817 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the calling app has carrier
9818 * privileges.
9819 *
9820 * @param subId subscription id
9821 * @param isEnabled {@code true} means enable, {@code false} means disable.
9822 */
9823 @Override
9824 public void setDataRoamingEnabled(int subId, boolean isEnabled) {
Pengquan Meng44e66f12019-04-01 10:48:20 -07009825 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9826 mApp, subId, "setDataRoamingEnabled");
9827
Pengquan Menga1bb6272018-09-06 09:59:22 -07009828 final long identity = Binder.clearCallingIdentity();
9829 try {
Pengquan Menga1bb6272018-09-06 09:59:22 -07009830 Phone phone = getPhone(subId);
9831 if (phone != null) {
9832 phone.setDataRoamingEnabled(isEnabled);
9833 }
9834 } finally {
9835 Binder.restoreCallingIdentity(identity);
Pengquan Meng77b7f132018-08-22 14:49:57 -07009836 }
9837 }
9838
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00009839 @Override
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009840 public boolean isManualNetworkSelectionAllowed(int subId) {
tom hsuc91afc72020-01-06 23:46:07 +08009841 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07009842 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08009843 mApp, subId, "isManualNetworkSelectionAllowed");
Pengquan Meng44e66f12019-04-01 10:48:20 -07009844
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009845 boolean isAllowed = true;
9846 final long identity = Binder.clearCallingIdentity();
9847 try {
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009848 Phone phone = getPhone(subId);
9849 if (phone != null) {
9850 isAllowed = phone.isCspPlmnEnabled();
9851 }
9852 } finally {
9853 Binder.restoreCallingIdentity(identity);
9854 }
9855 return isAllowed;
9856 }
9857
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009858 private boolean haveCarrierPrivilegeAccess(UiccPort port, String callingPackage) {
9859 UiccProfile profile = port.getUiccProfile();
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08009860 if (profile == null) {
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009861 return false;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00009862 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08009863 Phone phone = PhoneFactory.getPhone(profile.getPhoneId());
9864 if (phone == null) {
9865 return false;
9866 }
9867 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
9868 return cpt != null && cpt.getCarrierPrivilegeStatusForPackage(callingPackage)
9869 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00009870 }
9871
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009872 @Override
Jordan Liu75f43ea2019-01-17 16:56:37 -08009873 public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
sandeepjsa208e3b2021-11-17 04:05:58 +00009874 // Verify that the callingPackage belongs to the calling UID
Jordan Liu4cda4552020-03-23 11:55:07 -07009875 mApp.getSystemService(AppOpsManager.class)
9876 .checkPackage(Binder.getCallingUid(), callingPackage);
9877
Jordan Liu1e142fc2019-04-22 15:10:43 -07009878 boolean hasReadPermission = false;
sandeepjsb6c87872021-09-27 15:34:44 +00009879 boolean isIccIdAccessRestricted = false;
Jordan Liuc65bc952019-02-12 17:54:02 -08009880 try {
9881 enforceReadPrivilegedPermission("getUiccCardsInfo");
Jordan Liu1e142fc2019-04-22 15:10:43 -07009882 hasReadPermission = true;
Jordan Liuc65bc952019-02-12 17:54:02 -08009883 } catch (SecurityException e) {
9884 // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
9885 // has carrier privileges on an active UICC
Rambo Wange7209ce2022-02-23 13:41:02 -08009886 if (checkCarrierPrivilegesForPackageAnyPhoneWithPermission(callingPackage)
Thomas Nguyen8ee49682023-02-01 11:46:09 -08009887 != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Jordan Liu1e142fc2019-04-22 15:10:43 -07009888 throw new SecurityException("Caller does not have permission.");
Jordan Liuc65bc952019-02-12 17:54:02 -08009889 }
Jordan Liu75f43ea2019-01-17 16:56:37 -08009890 }
sandeepjsb6c87872021-09-27 15:34:44 +00009891 // checking compatibility, if calling app's target SDK is T and beyond.
9892 if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
9893 Binder.getCallingUid())) {
9894 isIccIdAccessRestricted = true;
9895 }
Jordan Liu5aa07002018-12-18 15:44:48 -08009896 final long identity = Binder.clearCallingIdentity();
9897 try {
Jordan Liu75f43ea2019-01-17 16:56:37 -08009898 UiccController uiccController = UiccController.getInstance();
9899 ArrayList<UiccCardInfo> cardInfos = uiccController.getAllUiccCardInfos();
Jordan Liu1e142fc2019-04-22 15:10:43 -07009900 if (hasReadPermission) {
9901 return cardInfos;
Jordan Liu75f43ea2019-01-17 16:56:37 -08009902 }
Jordan Liu1e142fc2019-04-22 15:10:43 -07009903
9904 // Remove private info if the caller doesn't have access
9905 ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
9906 for (UiccCardInfo cardInfo : cardInfos) {
sandeepjsb6c87872021-09-27 15:34:44 +00009907 //setting the value after compatibility check
9908 cardInfo.setIccIdAccessRestricted(isIccIdAccessRestricted);
Jordan Liu1e142fc2019-04-22 15:10:43 -07009909 // For an inactive eUICC, the UiccCard will be null even though the UiccCardInfo
9910 // is available
sandeepjsb6c87872021-09-27 15:34:44 +00009911 UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getPhysicalSlotIndex());
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009912 if (card == null) {
9913 // assume no access if the card is unavailable
sandeepjsb6c87872021-09-27 15:34:44 +00009914 filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
Jordan Liu1e142fc2019-04-22 15:10:43 -07009915 continue;
9916 }
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009917 Collection<UiccPortInfo> portInfos = cardInfo.getPorts();
9918 if (portInfos.isEmpty()) {
sandeepjsb6c87872021-09-27 15:34:44 +00009919 filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009920 continue;
Jordan Liu1e142fc2019-04-22 15:10:43 -07009921 }
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009922 List<UiccPortInfo> uiccPortInfos = new ArrayList<>();
9923 for (UiccPortInfo portInfo : portInfos) {
9924 UiccPort port = uiccController.getUiccPortForSlot(
9925 cardInfo.getPhysicalSlotIndex(), portInfo.getPortIndex());
9926 if (port == null) {
9927 // assume no access if port is null
9928 uiccPortInfos.add(getUiccPortInfoUnPrivileged(portInfo));
9929 continue;
9930 }
9931 if (haveCarrierPrivilegeAccess(port, callingPackage)) {
9932 uiccPortInfos.add(portInfo);
9933 } else {
9934 uiccPortInfos.add(getUiccPortInfoUnPrivileged(portInfo));
9935 }
9936 }
9937 filteredInfos.add(new UiccCardInfo(
9938 cardInfo.isEuicc(),
9939 cardInfo.getCardId(),
9940 null,
9941 cardInfo.getPhysicalSlotIndex(),
9942 cardInfo.isRemovable(),
9943 cardInfo.isMultipleEnabledProfilesSupported(),
9944 uiccPortInfos));
Jordan Liu1e142fc2019-04-22 15:10:43 -07009945 }
9946 return filteredInfos;
Jordan Liu5aa07002018-12-18 15:44:48 -08009947 } finally {
9948 Binder.restoreCallingIdentity(identity);
9949 }
9950 }
9951
sandeepjsb6c87872021-09-27 15:34:44 +00009952 /**
9953 * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
9954 * generally private and require carrier privileges to view.
9955 *
9956 * @hide
9957 */
9958 @NonNull
9959 public UiccCardInfo getUiccCardInfoUnPrivileged(UiccCardInfo cardInfo) {
9960 List<UiccPortInfo> portinfo = new ArrayList<>();
9961 for (UiccPortInfo portinfos : cardInfo.getPorts()) {
9962 portinfo.add(getUiccPortInfoUnPrivileged(portinfos));
9963 }
9964 return new UiccCardInfo(
9965 cardInfo.isEuicc(),
9966 cardInfo.getCardId(),
9967 null,
9968 cardInfo.getPhysicalSlotIndex(),
9969 cardInfo.isRemovable(),
9970 cardInfo.isMultipleEnabledProfilesSupported(),
9971 portinfo
9972 );
9973 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00009974
sandeepjsb6c87872021-09-27 15:34:44 +00009975 /**
9976 * @hide
9977 * @return a copy of the UiccPortInfo with ICCID set to {@link UiccPortInfo#ICCID_REDACTED}.
9978 * These values are generally private and require carrier privileges to view.
9979 */
9980 @NonNull
9981 public UiccPortInfo getUiccPortInfoUnPrivileged(UiccPortInfo portInfo) {
9982 return new UiccPortInfo(
9983 UiccPortInfo.ICCID_REDACTED,
9984 portInfo.getPortIndex(),
9985 portInfo.getLogicalSlotIndex(),
9986 portInfo.isActive()
9987 );
9988 }
9989 @Override
9990 public UiccSlotInfo[] getUiccSlotsInfo(String callingPackage) {
sandeepjsa208e3b2021-11-17 04:05:58 +00009991 // Verify that the callingPackage belongs to the calling UID
sandeepjsb6c87872021-09-27 15:34:44 +00009992 mApp.getSystemService(AppOpsManager.class)
9993 .checkPackage(Binder.getCallingUid(), callingPackage);
9994
sandeepjsb6c87872021-09-27 15:34:44 +00009995 boolean isLogicalSlotAccessRestricted = false;
sandeepjsb6c87872021-09-27 15:34:44 +00009996
Aman Guptaf3c90b32022-03-17 04:54:16 +00009997 // This will make sure caller has the READ_PRIVILEGED_PHONE_STATE. Do not remove this as
9998 // we are reading iccId which is PII data.
9999 enforceReadPrivilegedPermission("getUiccSlotsInfo");
sandeepjsb6c87872021-09-27 15:34:44 +000010000
10001 // checking compatibility, if calling app's target SDK is T and beyond.
10002 if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
10003 Binder.getCallingUid())) {
10004 isLogicalSlotAccessRestricted = true;
10005 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010006 final long identity = Binder.clearCallingIdentity();
10007 try {
10008 UiccSlot[] slots = UiccController.getInstance().getUiccSlots();
Muralidhar Reddyd196bbf2022-01-17 17:56:30 +000010009 if (slots == null || slots.length == 0) {
10010 Rlog.i(LOG_TAG, "slots is null or empty.");
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010011 return null;
10012 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010013 UiccSlotInfo[] infos = new UiccSlotInfo[slots.length];
10014 for (int i = 0; i < slots.length; i++) {
10015 UiccSlot slot = slots[i];
10016 if (slot == null) {
10017 continue;
10018 }
10019
Jordan Liu7be7e652019-05-06 18:55:02 +000010020 String cardId;
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010021 UiccCard card = slot.getUiccCard();
10022 if (card != null) {
10023 cardId = card.getCardId();
Jordan Liu7be7e652019-05-06 18:55:02 +000010024 } else {
Jordan Liu01bd00d2019-09-12 16:19:43 -070010025 cardId = slot.getEid();
10026 if (TextUtils.isEmpty(cardId)) {
Aman Guptaf3c90b32022-03-17 04:54:16 +000010027 // If cardId is null, use iccId of default port as cardId.
10028 cardId = slot.getIccId(TelephonyManager.DEFAULT_PORT_INDEX);
Jordan Liu01bd00d2019-09-12 16:19:43 -070010029 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010030 }
10031
Jordan Liu857451f2019-05-09 16:35:35 -070010032 if (cardId != null) {
10033 // if cardId is an ICCID, strip off trailing Fs before exposing to user
10034 // if cardId is an EID, it's all digits so this is fine
10035 cardId = IccUtils.stripTrailingFs(cardId);
10036 }
10037
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010038 int cardState = 0;
10039 switch (slot.getCardState()) {
10040 case CARDSTATE_ABSENT:
10041 cardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT;
10042 break;
10043 case CARDSTATE_PRESENT:
10044 cardState = UiccSlotInfo.CARD_STATE_INFO_PRESENT;
10045 break;
10046 case CARDSTATE_ERROR:
10047 cardState = UiccSlotInfo.CARD_STATE_INFO_ERROR;
10048 break;
10049 case CARDSTATE_RESTRICTED:
10050 cardState = UiccSlotInfo.CARD_STATE_INFO_RESTRICTED;
10051 break;
10052 default:
10053 break;
10054
10055 }
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010056 List<UiccPortInfo> portInfos = new ArrayList<>();
10057 int[] portIndexes = slot.getPortList();
10058 for (int portIdx : portIndexes) {
10059 String iccId = IccUtils.stripTrailingFs(getIccId(slot, portIdx,
Aman Guptaf3c90b32022-03-17 04:54:16 +000010060 callingPackage, /* hasReadPermission= */ true));
Muralidhar Reddyfbcff0c2022-01-19 13:07:57 +000010061 portInfos.add(new UiccPortInfo(iccId, portIdx,
10062 slot.getPhoneIdFromPortIndex(portIdx), slot.isPortActive(portIdx)));
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010063 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010064 infos[i] = new UiccSlotInfo(
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010065 slot.isEuicc(),
10066 cardId,
10067 cardState,
Jordan Liua2619582019-02-14 12:56:40 -080010068 slot.isExtendedApduSupported(),
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010069 slot.isRemovable(), portInfos);
sandeepjsb6c87872021-09-27 15:34:44 +000010070 //setting the value after compatibility check
10071 infos[i].setLogicalSlotAccessRestricted(isLogicalSlotAccessRestricted);
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010072 }
10073 return infos;
10074 } finally {
10075 Binder.restoreCallingIdentity(identity);
Holly Jiuyu Sun1d957c52018-04-04 13:52:42 -070010076 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010077 }
10078
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010079 /* Returns null if doesn't have read permission or carrier privilege access. */
10080 private String getIccId(UiccSlot slot, int portIndex, String callingPackage,
10081 boolean hasReadPermission) {
10082 String iccId = slot.getIccId(portIndex);
10083 if (hasReadPermission) { // if has read permission
10084 return iccId;
10085 } else {
10086 if (slot.getUiccCard() != null && slot.getUiccCard().getUiccPort(portIndex) != null) {
10087 UiccPort port = slot.getUiccCard().getUiccPort(portIndex);
10088 // if no read permission, checking carrier privilege access
10089 if (haveCarrierPrivilegeAccess(port, callingPackage)) {
10090 return iccId;
10091 }
10092 }
10093 }
10094 // No read permission or carrier privilege access.
10095 return UiccPortInfo.ICCID_REDACTED;
10096 }
10097
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010098 @Override
sandeepjsb6c87872021-09-27 15:34:44 +000010099 @Deprecated
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010100 public boolean switchSlots(int[] physicalSlots) {
10101 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010102
10103 final long identity = Binder.clearCallingIdentity();
10104 try {
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010105 List<UiccSlotMapping> slotMappings = new ArrayList<>();
10106 for (int i = 0; i < physicalSlots.length; i++) {
10107 // Deprecated API, hence MEP is not supported. Adding default portIndex 0.
10108 slotMappings.add(new UiccSlotMapping(TelephonyManager.DEFAULT_PORT_INDEX,
10109 physicalSlots[i], i));
10110 }
10111 return (Boolean) sendRequest(CMD_SWITCH_SLOTS, slotMappings);
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010112 } finally {
10113 Binder.restoreCallingIdentity(identity);
10114 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010115 }
Jack Yu4c988042018-02-27 15:30:01 -080010116
10117 @Override
sandeepjsb6c87872021-09-27 15:34:44 +000010118 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
10119 public boolean setSimSlotMapping(@NonNull List<UiccSlotMapping> slotMapping) {
10120 enforceModifyPermission();
10121
10122 final long identity = Binder.clearCallingIdentity();
10123 try {
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010124 return (Boolean) sendRequest(CMD_SWITCH_SLOTS, slotMapping);
sandeepjsb6c87872021-09-27 15:34:44 +000010125 } finally {
10126 Binder.restoreCallingIdentity(identity);
10127 }
10128 }
10129
10130 @Override
Jordan Liu7de49fa2018-12-06 14:48:49 -080010131 public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
Jordan Liu7de49fa2018-12-06 14:48:49 -080010132 final long identity = Binder.clearCallingIdentity();
10133 try {
10134 return UiccController.getInstance().getCardIdForDefaultEuicc();
10135 } finally {
10136 Binder.restoreCallingIdentity(identity);
10137 }
10138 }
10139
Pengquan Meng85728fb2018-03-12 16:31:21 -070010140 /**
goneil47ffb6e2018-04-06 15:40:58 -070010141 * A test API to reload the UICC profile.
10142 *
10143 * <p>Requires that the calling app has permission
10144 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
10145 * @hide
10146 */
10147 @Override
10148 public void refreshUiccProfile(int subId) {
10149 enforceModifyPermission();
10150
10151 final long identity = Binder.clearCallingIdentity();
10152 try {
10153 Phone phone = getPhone(subId);
10154 if (phone == null) {
10155 return;
10156 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010157 UiccPort uiccPort = phone.getUiccPort();
10158 if (uiccPort == null) {
goneil47ffb6e2018-04-06 15:40:58 -070010159 return;
10160 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010161 UiccProfile uiccProfile = uiccPort.getUiccProfile();
goneil47ffb6e2018-04-06 15:40:58 -070010162 if (uiccProfile == null) {
10163 return;
10164 }
10165 uiccProfile.refresh();
10166 } finally {
10167 Binder.restoreCallingIdentity(identity);
10168 }
10169 }
10170
10171 /**
Pengquan Meng85728fb2018-03-12 16:31:21 -070010172 * Returns false if the mobile data is disabled by default, otherwise return true.
10173 */
10174 private boolean getDefaultDataEnabled() {
Inseob Kim14bb3d02018-12-13 17:11:34 +090010175 return TelephonyProperties.mobile_data().orElse(true);
Pengquan Meng85728fb2018-03-12 16:31:21 -070010176 }
10177
10178 /**
10179 * Returns true if the data roaming is enabled by default, i.e the system property
10180 * of {@link #DEFAULT_DATA_ROAMING_PROPERTY_NAME} is true or the config of
10181 * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} is true.
10182 */
10183 private boolean getDefaultDataRoamingEnabled(int subId) {
10184 final CarrierConfigManager configMgr = (CarrierConfigManager)
Nazanin Bakhshif782e562018-12-11 15:15:39 -080010185 mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Shuo Qian1d84a0e2020-07-15 12:36:44 -070010186 boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
Pengquan Meng85728fb2018-03-12 16:31:21 -070010187 isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
10188 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
10189 return isDataRoamingEnabled;
10190 }
10191
10192 /**
10193 * Returns the default network type for the given {@code subId}, if the default network type is
10194 * not set, return {@link Phone#PREFERRED_NT_MODE}.
10195 */
10196 private int getDefaultNetworkType(int subId) {
Inseob Kim14bb3d02018-12-13 17:11:34 +090010197 List<Integer> list = TelephonyProperties.default_network();
Jack Yu285100e2022-12-02 22:48:35 -080010198 int phoneId = SubscriptionManager.getPhoneId(subId);
Inseob Kim14bb3d02018-12-13 17:11:34 +090010199 if (phoneId >= 0 && phoneId < list.size() && list.get(phoneId) != null) {
10200 return list.get(phoneId);
10201 }
10202 return Phone.PREFERRED_NT_MODE;
Pengquan Meng85728fb2018-03-12 16:31:21 -070010203 }
fionaxua13278b2018-03-21 00:08:13 -070010204
10205 @Override
10206 public void setCarrierTestOverride(int subId, String mccmnc, String imsi, String iccid, String
chen xueaba88a2019-03-15 13:15:10 -070010207 gid1, String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn) {
fionaxua13278b2018-03-21 00:08:13 -070010208 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010209
10210 final long identity = Binder.clearCallingIdentity();
10211 try {
10212 final Phone phone = getPhone(subId);
10213 if (phone == null) {
10214 loge("setCarrierTestOverride fails with invalid subId: " + subId);
10215 return;
10216 }
Rambo Wang9c9ffdd2022-01-13 21:51:44 -080010217 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
10218 if (cpt != null) {
10219 cpt.setTestOverrideCarrierPrivilegeRules(carrierPrivilegeRules);
10220 }
10221 // TODO(b/211796398): remove the legacy logic below once CPT migration is done.
chen xueaba88a2019-03-15 13:15:10 -070010222 phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
10223 carrierPrivilegeRules, apn);
Jeff Davidson8ab02b22020-03-28 12:24:40 -070010224 if (carrierPrivilegeRules == null) {
10225 mCarrierPrivilegeTestOverrideSubIds.remove(subId);
10226 } else {
10227 mCarrierPrivilegeTestOverrideSubIds.add(subId);
10228 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010229 } finally {
10230 Binder.restoreCallingIdentity(identity);
fionaxua13278b2018-03-21 00:08:13 -070010231 }
fionaxua13278b2018-03-21 00:08:13 -070010232 }
10233
10234 @Override
10235 public int getCarrierIdListVersion(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -070010236 enforceReadPrivilegedPermission("getCarrierIdListVersion");
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010237
10238 final long identity = Binder.clearCallingIdentity();
10239 try {
10240 final Phone phone = getPhone(subId);
10241 if (phone == null) {
10242 loge("getCarrierIdListVersion fails with invalid subId: " + subId);
10243 return TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION;
10244 }
10245 return phone.getCarrierIdListVersion();
10246 } finally {
10247 Binder.restoreCallingIdentity(identity);
fionaxua13278b2018-03-21 00:08:13 -070010248 }
fionaxua13278b2018-03-21 00:08:13 -070010249 }
Malcolm Chen2c63d402018-08-14 16:00:53 -070010250
10251 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010252 public int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage,
10253 String callingFeatureId) {
Malcolm Chen2c63d402018-08-14 16:00:53 -070010254 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010255 mApp, subId, callingPackage, callingFeatureId,
10256 "getNumberOfModemsWithSimultaneousDataConnections")) {
Malcolm Chen2c63d402018-08-14 16:00:53 -070010257 return -1;
10258 }
10259
10260 final long identity = Binder.clearCallingIdentity();
10261 try {
10262 return mPhoneConfigurationManager.getNumberOfModemsWithSimultaneousDataConnections();
10263 } finally {
10264 Binder.restoreCallingIdentity(identity);
10265 }
10266 }
Pengquan Menga1bb6272018-09-06 09:59:22 -070010267
10268 @Override
10269 public int getCdmaRoamingMode(int subId) {
zoey chen7e6d4e52019-12-17 18:18:59 +080010270 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010271 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Thomas Nguyen8ee49682023-02-01 11:46:09 -080010272 mApp, subId, "getCdmaRoamingMode");
Pengquan Menga1bb6272018-09-06 09:59:22 -070010273
10274 final long identity = Binder.clearCallingIdentity();
10275 try {
10276 return (int) sendRequest(CMD_GET_CDMA_ROAMING_MODE, null /* argument */, subId);
10277 } finally {
10278 Binder.restoreCallingIdentity(identity);
10279 }
10280 }
10281
10282 @Override
10283 public boolean setCdmaRoamingMode(int subId, int mode) {
10284 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
10285 mApp, subId, "setCdmaRoamingMode");
10286
10287 final long identity = Binder.clearCallingIdentity();
10288 try {
10289 return (boolean) sendRequest(CMD_SET_CDMA_ROAMING_MODE, mode, subId);
10290 } finally {
10291 Binder.restoreCallingIdentity(identity);
10292 }
10293 }
10294
10295 @Override
Sarah Chinbaab1432020-10-28 13:46:24 -070010296 public int getCdmaSubscriptionMode(int subId) {
10297 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010298 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Sarah Chinbaab1432020-10-28 13:46:24 -070010299 mApp, subId, "getCdmaSubscriptionMode");
10300
10301 final long identity = Binder.clearCallingIdentity();
10302 try {
10303 return (int) sendRequest(CMD_GET_CDMA_SUBSCRIPTION_MODE, null /* argument */, subId);
10304 } finally {
10305 Binder.restoreCallingIdentity(identity);
10306 }
10307 }
10308
10309 @Override
Pengquan Menga1bb6272018-09-06 09:59:22 -070010310 public boolean setCdmaSubscriptionMode(int subId, int mode) {
10311 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
10312 mApp, subId, "setCdmaSubscriptionMode");
10313
10314 final long identity = Binder.clearCallingIdentity();
10315 try {
10316 return (boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION_MODE, mode, subId);
10317 } finally {
10318 Binder.restoreCallingIdentity(identity);
10319 }
10320 }
Makoto Onukida3bf792018-09-18 16:06:29 -070010321
sqianc5eccab2018-10-19 18:46:41 -070010322 @Override
sqian8c685422019-02-22 15:55:18 -080010323 public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010324 String callingPackage, String callingFeatureId) {
sqian11b7a0e2018-12-05 18:48:28 -080010325 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010326 mApp, getDefaultSubscription(), callingPackage, callingFeatureId,
10327 "getEmergencyNumberList")) {
sqian11b7a0e2018-12-05 18:48:28 -080010328 throw new SecurityException("Requires READ_PHONE_STATE permission.");
10329 }
10330 final long identity = Binder.clearCallingIdentity();
10331 try {
sqian854d44b2018-12-12 16:48:18 -080010332 Map<Integer, List<EmergencyNumber>> emergencyNumberListInternal = new HashMap<>();
10333 for (Phone phone: PhoneFactory.getPhones()) {
10334 if (phone.getEmergencyNumberTracker() != null
10335 && phone.getEmergencyNumberTracker().getEmergencyNumberList() != null) {
10336 emergencyNumberListInternal.put(
10337 phone.getSubId(),
10338 phone.getEmergencyNumberTracker().getEmergencyNumberList());
10339 }
sqian11b7a0e2018-12-05 18:48:28 -080010340 }
sqian854d44b2018-12-12 16:48:18 -080010341 return emergencyNumberListInternal;
sqian11b7a0e2018-12-05 18:48:28 -080010342 } finally {
10343 Binder.restoreCallingIdentity(identity);
10344 }
sqianc5eccab2018-10-19 18:46:41 -070010345 }
10346
10347 @Override
sqian8c685422019-02-22 15:55:18 -080010348 public boolean isEmergencyNumber(String number, boolean exactMatch) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -080010349 final Phone defaultPhone = getDefaultPhone();
sqian11b7a0e2018-12-05 18:48:28 -080010350 if (!exactMatch) {
10351 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010352 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
sqian8c685422019-02-22 15:55:18 -080010353 mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
sqian11b7a0e2018-12-05 18:48:28 -080010354 }
10355 final long identity = Binder.clearCallingIdentity();
10356 try {
sqian854d44b2018-12-12 16:48:18 -080010357 for (Phone phone: PhoneFactory.getPhones()) {
Chinmay Dhodapkard521bb12022-08-16 15:49:54 -070010358 //Note: we ignore passed in param exactMatch. We can remove it once
10359 // TelephonyManager#isPotentialEmergencyNumber is removed completely
sqian854d44b2018-12-12 16:48:18 -080010360 if (phone.getEmergencyNumberTracker() != null
Taesu Leee050c002020-10-13 17:19:35 +090010361 && phone.getEmergencyNumberTracker()
Thomas Nguyen8ee49682023-02-01 11:46:09 -080010362 .isEmergencyNumber(number)) {
Taesu Leee050c002020-10-13 17:19:35 +090010363 return true;
sqian11b7a0e2018-12-05 18:48:28 -080010364 }
sqian11b7a0e2018-12-05 18:48:28 -080010365 }
10366 return false;
10367 } finally {
10368 Binder.restoreCallingIdentity(identity);
10369 }
10370 }
10371
sqianf4ca7ed2019-01-15 18:32:07 -080010372 /**
Shuo Qianccbaf742021-02-22 18:32:21 -080010373 * Start emergency callback mode for GsmCdmaPhone for testing.
10374 */
10375 @Override
10376 public void startEmergencyCallbackMode() {
10377 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
10378 "startEmergencyCallbackMode");
10379 enforceModifyPermission();
10380 final long identity = Binder.clearCallingIdentity();
10381 try {
10382 for (Phone phone : PhoneFactory.getPhones()) {
10383 Rlog.d(LOG_TAG, "startEmergencyCallbackMode phone type: " + phone.getPhoneType());
10384 if (phone != null && ((phone.getPhoneType() == PHONE_TYPE_GSM)
10385 || (phone.getPhoneType() == PHONE_TYPE_CDMA))) {
10386 GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) phone;
10387 gsmCdmaPhone.obtainMessage(
10388 GsmCdmaPhone.EVENT_EMERGENCY_CALLBACK_MODE_ENTER).sendToTarget();
10389 Rlog.d(LOG_TAG, "startEmergencyCallbackMode: triggered");
10390 }
10391 }
10392 } finally {
10393 Binder.restoreCallingIdentity(identity);
10394 }
10395 }
10396
10397 /**
sqianf4ca7ed2019-01-15 18:32:07 -080010398 * Update emergency number list for test mode.
10399 */
10400 @Override
10401 public void updateEmergencyNumberListTestMode(int action, EmergencyNumber num) {
10402 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
10403 "updateEmergencyNumberListTestMode");
10404
10405 final long identity = Binder.clearCallingIdentity();
10406 try {
10407 for (Phone phone: PhoneFactory.getPhones()) {
10408 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10409 if (tracker != null) {
10410 tracker.executeEmergencyNumberTestModeCommand(action, num);
10411 }
10412 }
10413 } finally {
10414 Binder.restoreCallingIdentity(identity);
10415 }
10416 }
10417
10418 /**
10419 * Get the full emergency number list for test mode.
10420 */
10421 @Override
10422 public List<String> getEmergencyNumberListTestMode() {
10423 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
10424 "getEmergencyNumberListTestMode");
10425
10426 final long identity = Binder.clearCallingIdentity();
10427 try {
10428 Set<String> emergencyNumbers = new HashSet<>();
10429 for (Phone phone: PhoneFactory.getPhones()) {
10430 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10431 if (tracker != null) {
10432 for (EmergencyNumber num : tracker.getEmergencyNumberList()) {
10433 emergencyNumbers.add(num.getNumber());
10434 }
10435 }
10436 }
10437 return new ArrayList<>(emergencyNumbers);
10438 } finally {
10439 Binder.restoreCallingIdentity(identity);
10440 }
10441 }
10442
chen xud6b45bd2018-10-30 22:27:10 -070010443 @Override
Shuo Qian3b6ee772019-11-13 17:43:31 -080010444 public int getEmergencyNumberDbVersion(int subId) {
10445 enforceReadPrivilegedPermission("getEmergencyNumberDbVersion");
10446
10447 final long identity = Binder.clearCallingIdentity();
10448 try {
10449 final Phone phone = getPhone(subId);
10450 if (phone == null) {
10451 loge("getEmergencyNumberDbVersion fails with invalid subId: " + subId);
10452 return TelephonyManager.INVALID_EMERGENCY_NUMBER_DB_VERSION;
10453 }
10454 return phone.getEmergencyNumberDbVersion();
10455 } finally {
10456 Binder.restoreCallingIdentity(identity);
10457 }
10458 }
10459
10460 @Override
10461 public void notifyOtaEmergencyNumberDbInstalled() {
10462 enforceModifyPermission();
10463
10464 final long identity = Binder.clearCallingIdentity();
10465 try {
10466 for (Phone phone: PhoneFactory.getPhones()) {
10467 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10468 if (tracker != null) {
10469 tracker.updateOtaEmergencyNumberDatabase();
10470 }
10471 }
10472 } finally {
10473 Binder.restoreCallingIdentity(identity);
10474 }
10475 }
10476
10477 @Override
Shuo Qianc373f112020-03-05 17:55:34 -080010478 public void updateOtaEmergencyNumberDbFilePath(ParcelFileDescriptor otaParcelFileDescriptor) {
Shuo Qian3b6ee772019-11-13 17:43:31 -080010479 enforceActiveEmergencySessionPermission();
10480
10481 final long identity = Binder.clearCallingIdentity();
10482 try {
10483 for (Phone phone: PhoneFactory.getPhones()) {
10484 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10485 if (tracker != null) {
Shuo Qianc373f112020-03-05 17:55:34 -080010486 tracker.updateOtaEmergencyNumberDbFilePath(otaParcelFileDescriptor);
10487 }
10488 }
10489 } finally {
10490 Binder.restoreCallingIdentity(identity);
10491 }
10492 }
10493
10494 @Override
10495 public void resetOtaEmergencyNumberDbFilePath() {
10496 enforceActiveEmergencySessionPermission();
10497
10498 final long identity = Binder.clearCallingIdentity();
10499 try {
10500 for (Phone phone: PhoneFactory.getPhones()) {
10501 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10502 if (tracker != null) {
10503 tracker.resetOtaEmergencyNumberDbFilePath();
Shuo Qian3b6ee772019-11-13 17:43:31 -080010504 }
10505 }
10506 } finally {
10507 Binder.restoreCallingIdentity(identity);
10508 }
10509 }
10510
10511 @Override
chen xud6b45bd2018-10-30 22:27:10 -070010512 public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
10513 enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
10514 Phone phone = getPhone(subId);
10515 if (phone == null) {
10516 return null;
10517 }
10518 final long identity = Binder.clearCallingIdentity();
10519 try {
10520 UiccProfile profile = UiccController.getInstance()
10521 .getUiccProfileForPhone(phone.getPhoneId());
10522 if (profile != null) {
10523 return profile.getCertsFromCarrierPrivilegeAccessRules();
10524 }
10525 } finally {
10526 Binder.restoreCallingIdentity(identity);
10527 }
10528 return null;
10529 }
Malcolm Chen8e4ed912019-01-15 20:22:16 -080010530
10531 /**
10532 * Enable or disable a modem stack.
10533 */
10534 @Override
10535 public boolean enableModemForSlot(int slotIndex, boolean enable) {
10536 enforceModifyPermission();
10537
10538 final long identity = Binder.clearCallingIdentity();
10539 try {
10540 Phone phone = PhoneFactory.getPhone(slotIndex);
10541 if (phone == null) {
10542 return false;
10543 } else {
10544 return (Boolean) sendRequest(CMD_REQUEST_ENABLE_MODEM, enable, phone, null);
10545 }
10546 } finally {
10547 Binder.restoreCallingIdentity(identity);
10548 }
10549 }
Michelecea4cf22018-12-21 15:00:11 -080010550
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010551 /**
10552 * Whether a modem stack is enabled or not.
10553 */
10554 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010555 public boolean isModemEnabledForSlot(int slotIndex, String callingPackage,
10556 String callingFeatureId) {
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010557 Phone phone = PhoneFactory.getPhone(slotIndex);
10558 if (phone == null) return false;
10559
10560 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010561 mApp, phone.getSubId(), callingPackage, callingFeatureId,
10562 "isModemEnabledForSlot")) {
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010563 throw new SecurityException("Requires READ_PHONE_STATE permission.");
10564 }
10565
10566 final long identity = Binder.clearCallingIdentity();
10567 try {
Nazanin Bakhshif71371d2019-04-29 17:29:44 -070010568 try {
10569 return mPhoneConfigurationManager.getPhoneStatusFromCache(phone.getPhoneId());
10570 } catch (NoSuchElementException ex) {
10571 return (Boolean) sendRequest(CMD_GET_MODEM_STATUS, null, phone, null);
10572 }
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010573 } finally {
10574 Binder.restoreCallingIdentity(identity);
10575 }
10576 }
10577
Michelecea4cf22018-12-21 15:00:11 -080010578 @Override
Michele0ea7d782019-03-19 14:58:42 -070010579 public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
Michelecea4cf22018-12-21 15:00:11 -080010580 enforceModifyPermission();
10581
10582 final long identity = Binder.clearCallingIdentity();
10583 try {
10584 mTelephonySharedPreferences.edit()
Michele0ea7d782019-03-19 14:58:42 -070010585 .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultiSimCarrierRestricted)
Michelecea4cf22018-12-21 15:00:11 -080010586 .commit();
10587 } finally {
10588 Binder.restoreCallingIdentity(identity);
10589 }
10590 }
10591
10592 @Override
Michele0ea7d782019-03-19 14:58:42 -070010593 @TelephonyManager.IsMultiSimSupportedResult
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010594 public int isMultiSimSupported(String callingPackage, String callingFeatureId) {
Michele4245e952019-02-04 11:36:23 -080010595 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp,
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010596 getDefaultPhone().getSubId(), callingPackage, callingFeatureId,
10597 "isMultiSimSupported")) {
Michele0ea7d782019-03-19 14:58:42 -070010598 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele4245e952019-02-04 11:36:23 -080010599 }
Michelecea4cf22018-12-21 15:00:11 -080010600
10601 final long identity = Binder.clearCallingIdentity();
10602 try {
Michele0ea7d782019-03-19 14:58:42 -070010603 return isMultiSimSupportedInternal();
Michelecea4cf22018-12-21 15:00:11 -080010604 } finally {
10605 Binder.restoreCallingIdentity(identity);
10606 }
10607 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010608
Michele0ea7d782019-03-19 14:58:42 -070010609 @TelephonyManager.IsMultiSimSupportedResult
10610 private int isMultiSimSupportedInternal() {
Michele30b57b22019-03-01 12:01:14 -080010611 // If the device has less than 2 SIM cards, indicate that multisim is restricted.
10612 int numPhysicalSlots = UiccController.getInstance().getUiccSlots().length;
10613 if (numPhysicalSlots < 2) {
Michele0ea7d782019-03-19 14:58:42 -070010614 loge("isMultiSimSupportedInternal: requires at least 2 cards");
10615 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -080010616 }
10617 // Check if the hardware supports multisim functionality. If usage of multisim is not
10618 // supported by the modem, indicate that it is restricted.
10619 PhoneCapability staticCapability =
10620 mPhoneConfigurationManager.getStaticPhoneCapability();
10621 if (staticCapability == null) {
Michele0ea7d782019-03-19 14:58:42 -070010622 loge("isMultiSimSupportedInternal: no static configuration available");
10623 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -080010624 }
SongFerngWang8236caa2021-01-17 21:51:44 +080010625 if (staticCapability.getLogicalModemList().size() < 2) {
Michele0ea7d782019-03-19 14:58:42 -070010626 loge("isMultiSimSupportedInternal: maximum number of modem is < 2");
10627 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -080010628 }
10629 // Check if support of multiple SIMs is restricted by carrier
10630 if (mTelephonySharedPreferences.getBoolean(PREF_MULTI_SIM_RESTRICTED, false)) {
Michele0ea7d782019-03-19 14:58:42 -070010631 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_CARRIER;
Michele30b57b22019-03-01 12:01:14 -080010632 }
10633
Michele0ea7d782019-03-19 14:58:42 -070010634 return TelephonyManager.MULTISIM_ALLOWED;
Michele30b57b22019-03-01 12:01:14 -080010635 }
10636
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010637 /**
10638 * Switch configs to enable multi-sim or switch back to single-sim
Nazanin Bakhshi17318782019-03-01 11:56:08 -080010639 * Note: Switch from multi-sim to single-sim is only possible with MODIFY_PHONE_STATE
10640 * permission, but the other way around is possible with either MODIFY_PHONE_STATE
10641 * or carrier privileges
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010642 * @param numOfSims number of active sims we want to switch to
10643 */
10644 @Override
10645 public void switchMultiSimConfig(int numOfSims) {
Nazanin Bakhshi17318782019-03-01 11:56:08 -080010646 if (numOfSims == 1) {
10647 enforceModifyPermission();
10648 } else {
10649 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
10650 mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
10651 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010652 final long identity = Binder.clearCallingIdentity();
Michele30b57b22019-03-01 12:01:14 -080010653
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010654 try {
Michele30b57b22019-03-01 12:01:14 -080010655 //only proceed if multi-sim is not restricted
Michele0ea7d782019-03-19 14:58:42 -070010656 if (isMultiSimSupportedInternal() != TelephonyManager.MULTISIM_ALLOWED) {
Michele30b57b22019-03-01 12:01:14 -080010657 loge("switchMultiSimConfig not possible. It is restricted or not supported.");
10658 return;
10659 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010660 mPhoneConfigurationManager.switchMultiSimConfig(numOfSims);
10661 } finally {
10662 Binder.restoreCallingIdentity(identity);
10663 }
10664 }
10665
Hyungjun Parkbb07fde2019-01-10 15:28:51 +090010666 @Override
10667 public boolean isApplicationOnUicc(int subId, int appType) {
10668 enforceReadPrivilegedPermission("isApplicationOnUicc");
10669 Phone phone = getPhone(subId);
10670 if (phone == null) {
10671 return false;
10672 }
10673 final long identity = Binder.clearCallingIdentity();
10674 try {
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010675 UiccPort uiccPort = phone.getUiccPort();
10676 if (uiccPort == null) {
Hyungjun Parkbb07fde2019-01-10 15:28:51 +090010677 return false;
10678 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010679 UiccProfile uiccProfile = uiccPort.getUiccProfile();
Hyungjun Parkbb07fde2019-01-10 15:28:51 +090010680 if (uiccProfile == null) {
10681 return false;
10682 }
10683 if (TelephonyManager.APPTYPE_SIM <= appType
10684 && appType <= TelephonyManager.APPTYPE_ISIM) {
10685 return uiccProfile.isApplicationOnIcc(AppType.values()[appType]);
10686 }
10687 return false;
10688 } finally {
10689 Binder.restoreCallingIdentity(identity);
10690 }
10691 }
10692
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010693 /**
chen xub4baa772019-04-03 10:23:41 -070010694 * Get whether making changes to modem configurations will trigger reboot.
10695 * Return value defaults to true.
Nazanin Bakhshi5fe5ef22019-01-30 10:52:09 -080010696 */
10697 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010698 public boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage,
10699 String callingFeatureId) {
chen xub4baa772019-04-03 10:23:41 -070010700 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010701 mApp, subId, callingPackage, callingFeatureId,
10702 "doesSwitchMultiSimConfigTriggerReboot")) {
chen xub4baa772019-04-03 10:23:41 -070010703 return false;
10704 }
Nazanin Bakhshi5fe5ef22019-01-30 10:52:09 -080010705 final long identity = Binder.clearCallingIdentity();
10706 try {
10707 return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
10708 } finally {
10709 Binder.restoreCallingIdentity(identity);
10710 }
10711 }
10712
Nathan Harold29f5f052019-02-15 13:41:57 -080010713 private void updateModemStateMetrics() {
10714 TelephonyMetrics metrics = TelephonyMetrics.getInstance();
10715 // TODO: check the state for each modem if the api is ready.
10716 metrics.updateEnabledModemBitmap((1 << TelephonyManager.from(mApp).getPhoneCount()) - 1);
10717 }
10718
Pengquan Meng3889a572019-01-23 11:16:29 -080010719 @Override
sandeepjsa208e3b2021-11-17 04:05:58 +000010720 public List<UiccSlotMapping> getSlotsMapping(String callingPackage) {
Pengquan Meng3889a572019-01-23 11:16:29 -080010721 enforceReadPrivilegedPermission("getSlotsMapping");
sandeepjsa208e3b2021-11-17 04:05:58 +000010722 // Verify that the callingPackage belongs to the calling UID
10723 mApp.getSystemService(AppOpsManager.class)
10724 .checkPackage(Binder.getCallingUid(), callingPackage);
Pengquan Meng3889a572019-01-23 11:16:29 -080010725 final long identity = Binder.clearCallingIdentity();
sandeepjsa208e3b2021-11-17 04:05:58 +000010726 List<UiccSlotMapping> slotMap = new ArrayList<>();
Pengquan Meng3889a572019-01-23 11:16:29 -080010727 try {
sandeepjsa208e3b2021-11-17 04:05:58 +000010728 UiccSlotInfo[] slotInfos = getUiccSlotsInfo(mApp.getOpPackageName());
10729 if (slotInfos != null) {
10730 for (int i = 0; i < slotInfos.length; i++) {
10731 for (UiccPortInfo portInfo : slotInfos[i].getPorts()) {
10732 if (SubscriptionManager.isValidPhoneId(portInfo.getLogicalSlotIndex())) {
10733 slotMap.add(new UiccSlotMapping(portInfo.getPortIndex(), i,
10734 portInfo.getLogicalSlotIndex()));
10735 }
10736 }
Pengquan Meng3889a572019-01-23 11:16:29 -080010737 }
10738 }
sandeepjsa208e3b2021-11-17 04:05:58 +000010739 return slotMap;
Pengquan Meng3889a572019-01-23 11:16:29 -080010740 } finally {
10741 Binder.restoreCallingIdentity(identity);
10742 }
10743 }
Nathan Harold48d6fd52019-02-06 19:01:40 -080010744
10745 /**
10746 * Get the IRadio HAL Version
jimsunf9ec1622022-09-13 21:18:43 +080010747 * @deprecated use getHalVersion instead
Nathan Harold48d6fd52019-02-06 19:01:40 -080010748 */
jimsunf9ec1622022-09-13 21:18:43 +080010749 @Deprecated
Nathan Harold48d6fd52019-02-06 19:01:40 -080010750 @Override
10751 public int getRadioHalVersion() {
jimsunf9ec1622022-09-13 21:18:43 +080010752 return getHalVersion(HAL_SERVICE_RADIO);
10753 }
10754
10755 /**
10756 * Get the HAL Version of a specific service
10757 */
10758 @Override
10759 public int getHalVersion(int service) {
Nathan Harold48d6fd52019-02-06 19:01:40 -080010760 Phone phone = getDefaultPhone();
10761 if (phone == null) return -1;
jimsunf9ec1622022-09-13 21:18:43 +080010762 HalVersion hv = phone.getHalVersion(service);
Nathan Harold48d6fd52019-02-06 19:01:40 -080010763 if (hv.equals(HalVersion.UNKNOWN)) return -1;
10764 return hv.major * 100 + hv.minor;
10765 }
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010766
10767 /**
Shuo Qianda2d6ec2020-01-14 15:18:28 -080010768 * Get the current calling package name.
10769 * @return the current calling package name
10770 */
10771 @Override
10772 public String getCurrentPackageName() {
10773 return mApp.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0];
10774 }
10775
10776 /**
Malcolm Chene5ad5792019-04-18 13:51:02 -070010777 * Return whether data is enabled for certain APN type. This will tell if framework will accept
10778 * corresponding network requests on a subId.
10779 *
10780 * Data is enabled if:
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010781 * 1) user data is turned on, or
Malcolm Chene5ad5792019-04-18 13:51:02 -070010782 * 2) APN is un-metered for this subscription, or
10783 * 3) APN type is whitelisted. E.g. MMS is whitelisted if
Hall Liu746e03c2020-09-25 11:13:49 -070010784 * {@link TelephonyManager#MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED} is enabled.
Malcolm Chene5ad5792019-04-18 13:51:02 -070010785 *
10786 * @return whether data is allowed for a apn type.
10787 *
10788 * @hide
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010789 */
10790 @Override
Malcolm Chene5ad5792019-04-18 13:51:02 -070010791 public boolean isDataEnabledForApn(int apnType, int subId, String callingPackage) {
Amit Mahajan5d4e1922019-10-07 16:20:43 -070010792 enforceReadPrivilegedPermission("Needs READ_PRIVILEGED_PHONE_STATE for "
10793 + "isDataEnabledForApn");
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010794
10795 // Now that all security checks passes, perform the operation as ourselves.
10796 final long identity = Binder.clearCallingIdentity();
10797 try {
10798 Phone phone = getPhone(subId);
10799 if (phone == null) return false;
10800
Jack Yu27422a52022-03-21 10:38:05 -070010801 boolean isMetered;
Jack Yu99e87332021-12-17 23:14:15 -080010802 boolean isDataEnabled;
Jack Yu7968c6d2022-07-31 00:43:21 -070010803 isMetered = phone.getDataNetworkController().getDataConfigManager()
10804 .isMeteredCapability(DataUtils.apnTypeToNetworkCapability(apnType),
10805 phone.getServiceState().getDataRoaming());
10806 isDataEnabled = phone.getDataSettingsManager().isDataEnabled(apnType);
Jack Yu99e87332021-12-17 23:14:15 -080010807 return !isMetered || isDataEnabled;
Malcolm Chene5ad5792019-04-18 13:51:02 -070010808 } finally {
10809 Binder.restoreCallingIdentity(identity);
10810 }
10811 }
10812
10813 @Override
Jack Yu41407ee2019-05-13 16:54:09 -070010814 public boolean isApnMetered(@ApnType int apnType, int subId) {
Malcolm Chene5ad5792019-04-18 13:51:02 -070010815 enforceReadPrivilegedPermission("isApnMetered");
10816
10817 // Now that all security checks passes, perform the operation as ourselves.
10818 final long identity = Binder.clearCallingIdentity();
10819 try {
10820 Phone phone = getPhone(subId);
10821 if (phone == null) return true; // By default return true.
Jack Yu7968c6d2022-07-31 00:43:21 -070010822 return phone.getDataNetworkController().getDataConfigManager().isMeteredCapability(
10823 DataUtils.apnTypeToNetworkCapability(apnType),
10824 phone.getServiceState().getDataRoaming());
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010825 } finally {
10826 Binder.restoreCallingIdentity(identity);
10827 }
10828 }
Brad Ebingera63db5f2019-04-23 16:31:13 -070010829
10830 @Override
Hall Liu73f5d362020-01-20 13:42:00 -080010831 public void setSystemSelectionChannels(List<RadioAccessSpecifier> specifiers,
10832 int subscriptionId, IBooleanConsumer resultCallback) {
10833 enforceModifyPermission();
10834 long token = Binder.clearCallingIdentity();
10835 try {
10836 Phone phone = getPhone(subscriptionId);
10837 if (phone == null) {
10838 try {
10839 if (resultCallback != null) {
10840 resultCallback.accept(false);
10841 }
10842 } catch (RemoteException e) {
10843 // ignore
10844 }
10845 return;
10846 }
10847 Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> argument =
10848 Pair.create(specifiers, (x) -> {
10849 try {
10850 if (resultCallback != null) {
10851 resultCallback.accept(x);
10852 }
10853 } catch (RemoteException e) {
10854 // ignore
10855 }
10856 });
10857 sendRequestAsync(CMD_SET_SYSTEM_SELECTION_CHANNELS, argument, phone, null);
10858 } finally {
10859 Binder.restoreCallingIdentity(token);
10860 }
10861 }
10862
10863 @Override
Sarah Chin679c08a2020-11-18 13:39:35 -080010864 public List<RadioAccessSpecifier> getSystemSelectionChannels(int subId) {
10865 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010866 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Sarah Chin679c08a2020-11-18 13:39:35 -080010867 mApp, subId, "getSystemSelectionChannels");
10868 WorkSource workSource = getWorkSource(Binder.getCallingUid());
10869 final long identity = Binder.clearCallingIdentity();
10870 try {
Sarah Chin428d1d62021-03-13 03:17:40 -080010871 Object result = sendRequest(CMD_GET_SYSTEM_SELECTION_CHANNELS, null, subId, workSource);
10872 if (result instanceof IllegalStateException) {
10873 throw (IllegalStateException) result;
10874 }
10875 List<RadioAccessSpecifier> specifiers = (List<RadioAccessSpecifier>) result;
Sarah Chin679c08a2020-11-18 13:39:35 -080010876 if (DBG) log("getSystemSelectionChannels: " + specifiers);
10877 return specifiers;
10878 } finally {
10879 Binder.restoreCallingIdentity(identity);
10880 }
10881 }
10882
10883 @Override
Jack Yu8b766fc2022-03-21 09:42:33 -070010884 public boolean isMvnoMatched(int slotIndex, int mvnoType, @NonNull String mvnoMatchData) {
changbettyca3d40d2020-03-03 16:27:31 +080010885 enforceReadPrivilegedPermission("isMvnoMatched");
Jack Yu8b766fc2022-03-21 09:42:33 -070010886 return UiccController.getInstance().mvnoMatches(slotIndex, mvnoType, mvnoMatchData);
changbetty7157e9e2019-12-06 18:16:37 +080010887 }
10888
10889 @Override
Philip P. Moltmannd02b7372020-03-18 17:06:12 -070010890 public void enqueueSmsPickResult(String callingPackage, String callingAttributionTag,
10891 IIntegerConsumer pendingSubIdResult) {
Shuo Qianda2d6ec2020-01-14 15:18:28 -080010892 if (callingPackage == null) {
10893 callingPackage = getCurrentPackageName();
10894 }
Brad Ebingera63db5f2019-04-23 16:31:13 -070010895 SmsPermissions permissions = new SmsPermissions(getDefaultPhone(), mApp,
10896 (AppOpsManager) mApp.getSystemService(Context.APP_OPS_SERVICE));
Philip P. Moltmannd02b7372020-03-18 17:06:12 -070010897 if (!permissions.checkCallingCanSendSms(callingPackage, callingAttributionTag,
10898 "Sending message")) {
Brad Ebingera63db5f2019-04-23 16:31:13 -070010899 throw new SecurityException("Requires SEND_SMS permission to perform this operation");
10900 }
10901 PickSmsSubscriptionActivity.addPendingResult(pendingSubIdResult);
10902 Intent intent = new Intent();
10903 intent.setClass(mApp, PickSmsSubscriptionActivity.class);
10904 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
10905 // Bring up choose default SMS subscription dialog right now
10906 intent.putExtra(PickSmsSubscriptionActivity.DIALOG_TYPE_KEY,
10907 PickSmsSubscriptionActivity.SMS_PICK_FOR_MESSAGE);
10908 mApp.startActivity(intent);
10909 }
chen xud5ca2d52019-05-28 15:20:57 -070010910
10911 @Override
Ayush Sharma787854b2022-12-12 14:55:02 +000010912 public void showSwitchToManagedProfileDialog() {
10913 enforceModifyPermission();
10914
10915 Intent intent = new Intent();
10916 intent.setClass(mApp, ErrorDialogActivity.class);
10917 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
10918 mApp.startActivity(intent);
10919 }
10920
10921 @Override
chen xud5ca2d52019-05-28 15:20:57 -070010922 public String getMmsUAProfUrl(int subId) {
10923 //TODO investigate if this API should require proper permission check in R b/133791609
10924 final long identity = Binder.clearCallingIdentity();
10925 try {
Guoqiang.Qiu171383d2020-07-13 09:38:32 +080010926 String carrierUAProfUrl = mApp.getCarrierConfigForSubId(subId).getString(
10927 CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING);
10928 if (!TextUtils.isEmpty(carrierUAProfUrl)) {
10929 return carrierUAProfUrl;
10930 }
Daniel Brightebb4eb72020-02-18 15:16:33 -080010931 return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
10932 .getString(com.android.internal.R.string.config_mms_user_agent_profile_url);
chen xud5ca2d52019-05-28 15:20:57 -070010933 } finally {
10934 Binder.restoreCallingIdentity(identity);
10935 }
10936 }
10937
10938 @Override
10939 public String getMmsUserAgent(int subId) {
10940 //TODO investigate if this API should require proper permission check in R b/133791609
10941 final long identity = Binder.clearCallingIdentity();
10942 try {
Guoqiang.Qiu171383d2020-07-13 09:38:32 +080010943 String carrierUserAgent = mApp.getCarrierConfigForSubId(subId).getString(
10944 CarrierConfigManager.KEY_MMS_USER_AGENT_STRING);
10945 if (!TextUtils.isEmpty(carrierUserAgent)) {
10946 return carrierUserAgent;
10947 }
Daniel Brightebb4eb72020-02-18 15:16:33 -080010948 return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
10949 .getString(com.android.internal.R.string.config_mms_user_agent);
chen xud5ca2d52019-05-28 15:20:57 -070010950 } finally {
10951 Binder.restoreCallingIdentity(identity);
10952 }
10953 }
Jack Yub07d4972019-05-28 16:12:25 -070010954
10955 @Override
Hall Liua62f5da2020-09-25 10:42:19 -070010956 public boolean isMobileDataPolicyEnabled(int subscriptionId, int policy) {
10957 enforceReadPrivilegedPermission("isMobileDataPolicyEnabled");
Jack Yub07d4972019-05-28 16:12:25 -070010958
Jack Yub07d4972019-05-28 16:12:25 -070010959 final long identity = Binder.clearCallingIdentity();
10960 try {
Hall Liua62f5da2020-09-25 10:42:19 -070010961 Phone phone = getPhone(subscriptionId);
Jack Yub07d4972019-05-28 16:12:25 -070010962 if (phone == null) return false;
10963
Ling Maf188d502022-09-16 15:22:36 -070010964 return phone.getDataSettingsManager().isMobileDataPolicyEnabled(policy);
Jack Yub07d4972019-05-28 16:12:25 -070010965 } finally {
10966 Binder.restoreCallingIdentity(identity);
10967 }
10968 }
10969
10970 @Override
Hall Liuc66bb112021-02-02 12:09:32 -080010971 public void setMobileDataPolicyEnabled(int subscriptionId, int policy,
Hall Liua62f5da2020-09-25 10:42:19 -070010972 boolean enabled) {
changbettyd5c246e2019-12-24 15:40:37 +080010973 enforceModifyPermission();
10974
changbettyd5c246e2019-12-24 15:40:37 +080010975 final long identity = Binder.clearCallingIdentity();
10976 try {
Hall Liua62f5da2020-09-25 10:42:19 -070010977 Phone phone = getPhone(subscriptionId);
10978 if (phone == null) return;
changbettyd5c246e2019-12-24 15:40:37 +080010979
Ling Maf188d502022-09-16 15:22:36 -070010980 phone.getDataSettingsManager().setMobileDataPolicy(policy, enabled);
changbettyd5c246e2019-12-24 15:40:37 +080010981 } finally {
10982 Binder.restoreCallingIdentity(identity);
10983 }
10984 }
10985
Tyler Gunn7bcdc742019-10-04 15:56:59 -070010986 /**
Hall Liu746e03c2020-09-25 11:13:49 -070010987 * Updates whether conference event package handling is enabled.
Tyler Gunn7bcdc742019-10-04 15:56:59 -070010988 * @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
10989 * otherwise.
10990 */
10991 @Override
10992 public void setCepEnabled(boolean isCepEnabled) {
10993 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCepEnabled");
10994
10995 final long identity = Binder.clearCallingIdentity();
10996 try {
10997 Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled);
10998 for (Phone phone : PhoneFactory.getPhones()) {
10999 Phone defaultPhone = phone.getImsPhone();
11000 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
11001 ImsPhone imsPhone = (ImsPhone) defaultPhone;
11002 ImsPhoneCallTracker imsPhoneCallTracker =
11003 (ImsPhoneCallTracker) imsPhone.getCallTracker();
11004 imsPhoneCallTracker.setConferenceEventPackageEnabled(isCepEnabled);
11005 Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled + ", for imsPhone "
11006 + imsPhone.getMsisdn());
11007 }
11008 }
11009 } finally {
11010 Binder.restoreCallingIdentity(identity);
11011 }
11012 }
allenwtsu46dcc572020-01-08 18:24:03 +080011013
11014 /**
11015 * Notify that an RCS autoconfiguration XML file has been received for provisioning.
11016 *
11017 * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
11018 * @param isCompressed The XML file is compressed in gzip format and must be decompressed
11019 * before being read.
11020 */
11021 @Override
11022 public void notifyRcsAutoConfigurationReceived(int subId, @NonNull byte[] config, boolean
11023 isCompressed) {
11024 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
11025 mApp, subId, "notifyRcsAutoConfigurationReceived");
Hui Wang761a6682020-10-31 05:12:53 +000011026 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11027 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11028 }
11029 if (!isImsAvailableOnDevice()) {
joonhunshin46b49a32022-12-21 05:33:23 +000011030 // ProvisioningManager can not handle ServiceSpecificException.
11031 // Throw the IllegalStateException and annotate ProvisioningManager.
11032 throw new IllegalStateException("IMS not available on device.");
Hui Wang761a6682020-10-31 05:12:53 +000011033 }
11034
11035 final long identity = Binder.clearCallingIdentity();
allenwtsu46dcc572020-01-08 18:24:03 +080011036 try {
Hui Wang761a6682020-10-31 05:12:53 +000011037 RcsProvisioningMonitor.getInstance().updateConfig(subId, config, isCompressed);
11038 } finally {
11039 Binder.restoreCallingIdentity(identity);
allenwtsu46dcc572020-01-08 18:24:03 +080011040 }
11041 }
zoey chene02881a2019-12-30 16:11:23 +080011042
11043 @Override
11044 public boolean isIccLockEnabled(int subId) {
11045 enforceReadPrivilegedPermission("isIccLockEnabled");
11046
11047 // Now that all security checks passes, perform the operation as ourselves.
11048 final long identity = Binder.clearCallingIdentity();
11049 try {
11050 Phone phone = getPhone(subId);
11051 if (phone != null && phone.getIccCard() != null) {
11052 return phone.getIccCard().getIccLockEnabled();
11053 } else {
11054 return false;
11055 }
11056 } finally {
11057 Binder.restoreCallingIdentity(identity);
11058 }
11059 }
11060
11061 /**
11062 * Set the ICC pin lock enabled or disabled.
11063 *
11064 * @return an integer representing the status of IccLock enabled or disabled in the following
11065 * three cases:
11066 * - {@link TelephonyManager#CHANGE_ICC_LOCK_SUCCESS} if enabled or disabled IccLock
11067 * successfully.
11068 * - Positive number and zero for remaining password attempts.
11069 * - Negative number for other failure cases (such like enabling/disabling PIN failed).
11070 *
11071 */
11072 @Override
11073 public int setIccLockEnabled(int subId, boolean enabled, String password) {
11074 enforceModifyPermission();
11075
11076 Phone phone = getPhone(subId);
11077 if (phone == null) {
11078 return 0;
11079 }
11080 // Now that all security checks passes, perform the operation as ourselves.
11081 final long identity = Binder.clearCallingIdentity();
11082 try {
11083 int attemptsRemaining = (int) sendRequest(CMD_SET_ICC_LOCK_ENABLED,
11084 new Pair<Boolean, String>(enabled, password), phone, null);
11085 return attemptsRemaining;
11086
11087 } catch (Exception e) {
11088 Log.e(LOG_TAG, "setIccLockEnabled. Exception e =" + e);
11089 } finally {
11090 Binder.restoreCallingIdentity(identity);
11091 }
11092 return 0;
11093 }
11094
11095 /**
11096 * Change the ICC password used in ICC pin lock.
11097 *
11098 * @return an integer representing the status of IccLock changed in the following three cases:
11099 * - {@link TelephonyManager#CHANGE_ICC_LOCK_SUCCESS} if changed IccLock successfully.
11100 * - Positive number and zero for remaining password attempts.
11101 * - Negative number for other failure cases (such like enabling/disabling PIN failed).
11102 *
11103 */
11104 @Override
11105 public int changeIccLockPassword(int subId, String oldPassword, String newPassword) {
11106 enforceModifyPermission();
11107
11108 Phone phone = getPhone(subId);
11109 if (phone == null) {
11110 return 0;
11111 }
11112 // Now that all security checks passes, perform the operation as ourselves.
11113 final long identity = Binder.clearCallingIdentity();
11114 try {
11115 int attemptsRemaining = (int) sendRequest(CMD_CHANGE_ICC_LOCK_PASSWORD,
11116 new Pair<String, String>(oldPassword, newPassword), phone, null);
11117 return attemptsRemaining;
11118
11119 } catch (Exception e) {
11120 Log.e(LOG_TAG, "changeIccLockPassword. Exception e =" + e);
11121 } finally {
11122 Binder.restoreCallingIdentity(identity);
11123 }
11124 return 0;
11125 }
Peter Wangdafb9ac2020-01-15 14:13:38 -080011126
11127 /**
11128 * Request for receiving user activity notification
11129 */
11130 @Override
11131 public void requestUserActivityNotification() {
11132 if (!mNotifyUserActivity.get()
11133 && !mMainThreadHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
11134 mNotifyUserActivity.set(true);
11135 }
11136 }
11137
11138 /**
11139 * Called when userActivity is signalled in the power manager.
11140 * This is safe to call from any thread, with any window manager locks held or not.
11141 */
11142 @Override
11143 public void userActivity() {
11144 // ***************************************
11145 // * Inherited from PhoneWindowManager *
11146 // ***************************************
11147 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
11148 // WITH ITS LOCKS HELD.
11149 //
11150 // This code must be VERY careful about the locks
11151 // it acquires.
11152 // In fact, the current code acquires way too many,
11153 // and probably has lurking deadlocks.
11154
11155 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
11156 throw new SecurityException("Only the OS may call notifyUserActivity()");
11157 }
11158
11159 if (mNotifyUserActivity.getAndSet(false)) {
11160 mMainThreadHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
11161 USER_ACTIVITY_NOTIFICATION_DELAY);
11162 }
11163 }
Malcolm Chen4639c562020-04-13 11:59:40 -070011164
11165 @Override
11166 public boolean canConnectTo5GInDsdsMode() {
11167 return mApp.getResources().getBoolean(R.bool.config_5g_connection_in_dsds_mode);
11168 }
Jack Yud10cdd42020-09-28 20:28:01 -070011169
11170 @Override
11171 public @NonNull List<String> getEquivalentHomePlmns(int subId, String callingPackage,
11172 String callingFeatureId) {
11173 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
11174 mApp, subId, callingPackage, callingFeatureId, "getEquivalentHomePlmns")) {
11175 throw new SecurityException("Requires READ_PHONE_STATE permission.");
11176 }
11177
11178 Phone phone = getPhone(subId);
11179 if (phone == null) {
11180 throw new RuntimeException("phone is not available");
11181 }
11182 // Now that all security checks passes, perform the operation as ourselves.
11183 final long identity = Binder.clearCallingIdentity();
11184 try {
11185 return phone.getEquivalentHomePlmns();
11186 } finally {
11187 Binder.restoreCallingIdentity(identity);
11188 }
11189 }
Daniel Bright59e67312020-11-13 11:49:37 -080011190
11191 @Override
11192 public boolean isRadioInterfaceCapabilitySupported(
Daniel Bright95a4c1f2021-02-11 09:57:16 -080011193 final @NonNull @TelephonyManager.RadioInterfaceCapability String capability) {
11194 Set<String> radioInterfaceCapabilities =
Daniel Bright94f43662021-03-01 14:43:40 -080011195 mRadioInterfaceCapabilities.getCapabilities();
Daniel Bright59e67312020-11-13 11:49:37 -080011196 if (radioInterfaceCapabilities == null) {
11197 throw new RuntimeException("radio interface capabilities are not available");
Daniel Bright59e67312020-11-13 11:49:37 -080011198 }
Daniel Bright95a4c1f2021-02-11 09:57:16 -080011199 return radioInterfaceCapabilities.contains(capability);
Daniel Bright59e67312020-11-13 11:49:37 -080011200 }
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011201
Hui Wang641e81c2020-10-12 12:14:23 -070011202 @Override
11203 public void bootstrapAuthenticationRequest(int subId, int appType, Uri nafUrl,
11204 UaSecurityProtocolIdentifier securityProtocol,
Brad Ebinger34c09a52021-02-17 23:23:21 +000011205 boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) {
11206 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
11207 Binder.getCallingUid(), "bootstrapAuthenticationRequest",
11208 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11209 Manifest.permission.MODIFY_PHONE_STATE);
Hui Wang641e81c2020-10-12 12:14:23 -070011210 if (DBG) {
11211 log("bootstrapAuthenticationRequest, subId:" + subId + ", appType:"
11212 + appType + ", NAF:" + nafUrl + ", sp:" + securityProtocol
11213 + ", forceBootStrapping:" + forceBootStrapping + ", callback:" + callback);
11214 }
11215
11216 if (!SubscriptionManager.isValidSubscriptionId(subId)
11217 || appType < TelephonyManager.APPTYPE_UNKNOWN
11218 || appType > TelephonyManager.APPTYPE_ISIM
11219 || nafUrl == null || securityProtocol == null || callback == null) {
11220 Log.d(LOG_TAG, "bootstrapAuthenticationRequest failed due to invalid parameters");
11221 if (callback != null) {
11222 try {
11223 callback.onAuthenticationFailure(
11224 0, TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED);
11225 } catch (RemoteException exception) {
11226 log("Fail to notify onAuthenticationFailure due to " + exception);
11227 }
11228 return;
11229 }
11230 }
11231
11232 final long token = Binder.clearCallingIdentity();
11233 try {
11234 getGbaManager(subId).bootstrapAuthenticationRequest(
11235 new GbaAuthRequest(subId, appType, nafUrl, securityProtocol.toByteArray(),
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011236 forceBootStrapping, callback));
Hui Wang641e81c2020-10-12 12:14:23 -070011237 } finally {
11238 Binder.restoreCallingIdentity(token);
11239 }
11240 }
11241
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011242 /**
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011243 * Attempts to set the radio power state for all phones for thermal reason.
11244 * This does not guarantee that the
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011245 * requested radio power state will actually be set. See {@link
11246 * PhoneInternalInterface#setRadioPowerForReason} for more details.
11247 *
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011248 * @param enable {@code true} if trying to turn radio on.
11249 * @return {@code true} if phone setRadioPowerForReason was called. Otherwise, returns {@code
11250 * false}.
11251 */
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011252 private boolean setRadioPowerForThermal(boolean enable) {
11253 boolean isPhoneAvailable = false;
11254 for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) {
11255 Phone phone = PhoneFactory.getPhone(i);
11256 if (phone != null) {
Thomas Nguyenfd0572f2022-07-15 22:28:49 +000011257 phone.setRadioPowerForReason(enable, TelephonyManager.RADIO_POWER_REASON_THERMAL);
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011258 isPhoneAvailable = true;
11259 }
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011260 }
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011261
11262 // return true if successfully informed the phone object about the thermal radio power
11263 // request.
11264 return isPhoneAvailable;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011265 }
11266
11267 private int handleDataThrottlingRequest(int subId,
Sarah Chinecc78c42022-03-31 21:16:48 -070011268 DataThrottlingRequest dataThrottlingRequest, String callingPackage) {
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011269 boolean isDataThrottlingSupported = isRadioInterfaceCapabilitySupported(
11270 TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING);
11271 if (!isDataThrottlingSupported && dataThrottlingRequest.getDataThrottlingAction()
11272 != DataThrottlingRequest.DATA_THROTTLING_ACTION_NO_DATA_THROTTLING) {
11273 throw new IllegalArgumentException("modem does not support data throttling");
11274 }
11275
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011276 // Ensure that radio is on. If not able to power on due to phone being unavailable, return
11277 // THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011278 if (!setRadioPowerForThermal(true)) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011279 return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11280 }
11281
Sarah Chinecc78c42022-03-31 21:16:48 -070011282 setDataEnabledForReason(
11283 subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL, true, callingPackage);
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011284
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011285 if (isDataThrottlingSupported) {
11286 int thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011287 (int) sendRequest(CMD_SET_DATA_THROTTLING, dataThrottlingRequest, subId);
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011288 if (thermalMitigationResult == SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS) {
11289 throw new IllegalArgumentException("modem returned INVALID_ARGUMENTS");
11290 } else if (thermalMitigationResult
11291 == MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE) {
Jack Nudelman760d0962021-05-20 13:57:30 -070011292 log("Modem likely does not support data throttling on secondary carrier. Data " +
11293 "throttling action = " + dataThrottlingRequest.getDataThrottlingAction());
11294 return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011295 }
11296 return thermalMitigationResult;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011297 }
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011298
11299 return TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011300 }
11301
Jack Nudelman644b91a2021-03-12 14:09:48 -080011302 private static List<String> getThermalMitigationAllowlist(Context context) {
11303 if (sThermalMitigationAllowlistedPackages.isEmpty()) {
11304 for (String pckg : context.getResources()
11305 .getStringArray(R.array.thermal_mitigation_allowlisted_packages)) {
11306 sThermalMitigationAllowlistedPackages.add(pckg);
11307 }
11308 }
11309
11310 return sThermalMitigationAllowlistedPackages;
11311 }
11312
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011313 private boolean isAnyPhoneInEmergencyState() {
11314 TelecomManager tm = mApp.getSystemService(TelecomManager.class);
11315 if (tm.isInEmergencyCall()) {
11316 Log.e(LOG_TAG , "Phone state is not valid. One of the phones is in an emergency call");
11317 return true;
11318 }
11319 for (Phone phone : PhoneFactory.getPhones()) {
11320 if (phone.isInEmergencySmsMode() || phone.isInEcm()) {
11321 Log.e(LOG_TAG, "Phone state is not valid. isInEmergencySmsMode = "
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011322 + phone.isInEmergencySmsMode() + " isInEmergencyCallbackMode = "
11323 + phone.isInEcm());
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011324 return true;
11325 }
11326 }
11327
11328 return false;
11329 }
11330
Jack Nudelman644b91a2021-03-12 14:09:48 -080011331 /**
11332 * Used by shell commands to add an authorized package name for thermal mitigation.
11333 * @param packageName name of package to be allowlisted
11334 * @param context
11335 */
11336 static void addPackageToThermalMitigationAllowlist(String packageName, Context context) {
11337 sThermalMitigationAllowlistedPackages = getThermalMitigationAllowlist(context);
11338 sThermalMitigationAllowlistedPackages.add(packageName);
11339 }
11340
11341 /**
11342 * Used by shell commands to remove an authorized package name for thermal mitigation.
11343 * @param packageName name of package to remove from allowlist
11344 * @param context
11345 */
11346 static void removePackageFromThermalMitigationAllowlist(String packageName, Context context) {
11347 sThermalMitigationAllowlistedPackages = getThermalMitigationAllowlist(context);
11348 sThermalMitigationAllowlistedPackages.remove(packageName);
11349 }
11350
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011351 /**
11352 * Thermal mitigation request to control functionalities at modem.
11353 *
11354 * @param subId the id of the subscription.
11355 * @param thermalMitigationRequest holds all necessary information to be passed down to modem.
Jack Nudelman644b91a2021-03-12 14:09:48 -080011356 * @param callingPackage the package name of the calling package.
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011357 *
11358 * @return thermalMitigationResult enum as defined in android.telephony.Annotation.
11359 */
11360 @Override
11361 @ThermalMitigationResult
11362 public int sendThermalMitigationRequest(
11363 int subId,
Jack Nudelman644b91a2021-03-12 14:09:48 -080011364 ThermalMitigationRequest thermalMitigationRequest,
11365 String callingPackage) throws IllegalArgumentException {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011366 enforceModifyPermission();
11367
Jack Nudelman644b91a2021-03-12 14:09:48 -080011368 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
11369 if (!getThermalMitigationAllowlist(getDefaultPhone().getContext())
11370 .contains(callingPackage)) {
11371 throw new SecurityException("Calling package must be configured in the device config. "
11372 + "calling package: " + callingPackage);
11373 }
11374
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011375 WorkSource workSource = getWorkSource(Binder.getCallingUid());
11376 final long identity = Binder.clearCallingIdentity();
11377
11378 int thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR;
11379 try {
11380 int thermalMitigationAction = thermalMitigationRequest.getThermalMitigationAction();
11381 switch (thermalMitigationAction) {
11382 case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING:
11383 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011384 handleDataThrottlingRequest(subId,
11385 thermalMitigationRequest.getDataThrottlingRequest(),
11386 callingPackage);
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011387 break;
11388 case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY:
11389 if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
11390 throw new IllegalArgumentException("dataThrottlingRequest must be null for "
11391 + "ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY");
11392 }
11393
11394 // Ensure that radio is on. If not able to power on due to phone being
11395 // unavailable, return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011396 if (!setRadioPowerForThermal(true)) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011397 thermalMitigationResult =
11398 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11399 break;
11400 }
11401
11402 setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL,
Sarah Chinecc78c42022-03-31 21:16:48 -070011403 false, callingPackage);
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011404 thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
11405 break;
11406 case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF:
11407 if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
11408 throw new IllegalArgumentException("dataThrottlingRequest must be null for"
11409 + " ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF");
11410 }
11411
11412 TelecomAccountRegistry registry = TelecomAccountRegistry.getInstance(null);
11413 if (registry != null) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011414 Phone phone = getPhone(subId);
11415 if (phone == null) {
11416 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011417 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011418 break;
11419 }
11420
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011421 TelephonyConnectionService service =
11422 registry.getTelephonyConnectionService();
Jack Nudelmanb30ac302021-06-17 15:39:58 -070011423 if (service != null && service.isEmergencyCallPending()) {
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011424 Log.e(LOG_TAG, "An emergency call is pending");
11425 thermalMitigationResult =
11426 TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
11427 break;
11428 } else if (isAnyPhoneInEmergencyState()) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011429 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011430 TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011431 break;
11432 }
11433 } else {
11434 thermalMitigationResult =
11435 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11436 break;
11437 }
11438
11439 // Turn radio off. If not able to power off due to phone being unavailable,
11440 // return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011441 if (!setRadioPowerForThermal(false)) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011442 thermalMitigationResult =
11443 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11444 break;
11445 }
11446 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011447 TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011448 break;
11449 default:
11450 throw new IllegalArgumentException("the requested thermalMitigationAction does "
11451 + "not exist. Requested action: " + thermalMitigationAction);
11452 }
11453 } catch (IllegalArgumentException e) {
11454 throw e;
11455 } catch (Exception e) {
11456 Log.e(LOG_TAG, "thermalMitigationRequest. Exception e =" + e);
11457 thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
11458 } finally {
11459 Binder.restoreCallingIdentity(identity);
11460 }
11461
11462 if (DBG) {
11463 log("thermalMitigationRequest returning with thermalMitigationResult: "
11464 + thermalMitigationResult);
11465 }
11466
11467 return thermalMitigationResult;
11468 }
Hui Wang641e81c2020-10-12 12:14:23 -070011469
11470 /**
11471 * Set the GbaService Package Name that Telephony will bind to.
11472 *
11473 * @param subId The sim that the GbaService is associated with.
11474 * @param packageName The name of the package to be replaced with.
11475 * @return true if setting the GbaService to bind to succeeded, false if it did not.
11476 */
11477 @Override
11478 public boolean setBoundGbaServiceOverride(int subId, String packageName) {
11479 enforceModifyPermission();
11480
11481 final long identity = Binder.clearCallingIdentity();
11482 try {
11483 return getGbaManager(subId).overrideServicePackage(packageName);
11484 } finally {
11485 Binder.restoreCallingIdentity(identity);
11486 }
11487 }
11488
11489 /**
11490 * Return the package name of the currently bound GbaService.
11491 *
11492 * @param subId The sim that the GbaService is associated with.
11493 * @return the package name of the GbaService configuration, null if GBA is not supported.
11494 */
11495 @Override
11496 public String getBoundGbaService(int subId) {
11497 enforceReadPrivilegedPermission("getBoundGbaServicePackage");
11498
11499 final long identity = Binder.clearCallingIdentity();
11500 try {
11501 return getGbaManager(subId).getServicePackage();
11502 } finally {
11503 Binder.restoreCallingIdentity(identity);
11504 }
11505 }
11506
11507 /**
11508 * Set the release time for telephony to unbind GbaService.
11509 *
11510 * @param subId The sim that the GbaService is associated with.
11511 * @param interval The release time to unbind GbaService by millisecond.
11512 * @return true if setting the GbaService to bind to succeeded, false if it did not.
11513 */
11514 @Override
11515 public boolean setGbaReleaseTimeOverride(int subId, int interval) {
11516 enforceModifyPermission();
11517
11518 final long identity = Binder.clearCallingIdentity();
11519 try {
11520 return getGbaManager(subId).overrideReleaseTime(interval);
11521 } finally {
11522 Binder.restoreCallingIdentity(identity);
11523 }
11524 }
11525
11526 /**
11527 * Return the release time for telephony to unbind GbaService.
11528 *
11529 * @param subId The sim that the GbaService is associated with.
11530 * @return The release time to unbind GbaService by millisecond.
11531 */
11532 @Override
11533 public int getGbaReleaseTime(int subId) {
11534 enforceReadPrivilegedPermission("getGbaReleaseTime");
11535
11536 final long identity = Binder.clearCallingIdentity();
11537 try {
11538 return getGbaManager(subId).getReleaseTime();
11539 } finally {
11540 Binder.restoreCallingIdentity(identity);
11541 }
11542 }
11543
11544 private GbaManager getGbaManager(int subId) {
11545 GbaManager instance = GbaManager.getInstance(subId);
11546 if (instance == null) {
11547 String packageName = mApp.getResources().getString(R.string.config_gba_package);
11548 int releaseTime = mApp.getResources().getInteger(R.integer.config_gba_release_time);
11549 instance = GbaManager.make(mApp, subId, packageName, releaseTime);
11550 }
11551 return instance;
11552 }
Hui Wang761a6682020-10-31 05:12:53 +000011553
11554 /**
11555 * indicate whether the device and the carrier can support
11556 * RCS VoLTE single registration.
11557 */
11558 @Override
11559 public boolean isRcsVolteSingleRegistrationCapable(int subId) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011560 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
11561 Binder.getCallingUid(), "isRcsVolteSingleRegistrationCapable",
11562 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11563 permission.READ_PRIVILEGED_PHONE_STATE);
Hui Wang761a6682020-10-31 05:12:53 +000011564
11565 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11566 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11567 }
11568
11569 final long identity = Binder.clearCallingIdentity();
11570 try {
11571 RcsProvisioningMonitor rpm = RcsProvisioningMonitor.getInstance();
11572 if (rpm != null) {
Hui Wang67af90e2021-06-04 16:57:15 -070011573 Boolean isCapable = rpm.isRcsVolteSingleRegistrationEnabled(subId);
11574 if (isCapable != null) {
11575 return isCapable;
11576 }
Hui Wang761a6682020-10-31 05:12:53 +000011577 }
Hui Wang67af90e2021-06-04 16:57:15 -070011578 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
11579 "service is temporarily unavailable.");
Hui Wang761a6682020-10-31 05:12:53 +000011580 } finally {
11581 Binder.restoreCallingIdentity(identity);
11582 }
11583 }
11584
11585 /**
11586 * Register RCS provisioning callback.
11587 */
11588 @Override
Hui Wang3cac7e52021-01-27 14:45:25 -080011589 public void registerRcsProvisioningCallback(int subId,
Hui Wang761a6682020-10-31 05:12:53 +000011590 IRcsConfigCallback callback) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011591 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
Hui Wang3cac7e52021-01-27 14:45:25 -080011592 Binder.getCallingUid(), "registerRcsProvisioningCallback",
Brad Ebinger34c09a52021-02-17 23:23:21 +000011593 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11594 permission.READ_PRIVILEGED_PHONE_STATE);
Hui Wang761a6682020-10-31 05:12:53 +000011595
11596 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11597 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11598 }
11599 if (!isImsAvailableOnDevice()) {
11600 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
11601 "IMS not available on device.");
11602 }
11603
11604 final long identity = Binder.clearCallingIdentity();
11605 try {
Hui Wang68cd3722021-01-11 20:04:53 -080011606 if (!RcsProvisioningMonitor.getInstance()
Hui Wang3cac7e52021-01-27 14:45:25 -080011607 .registerRcsProvisioningCallback(subId, callback)) {
Brad Ebinger919631e2021-06-02 17:46:35 -070011608 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
11609 "Active subscription not found.");
Hui Wang68cd3722021-01-11 20:04:53 -080011610 }
Hui Wang761a6682020-10-31 05:12:53 +000011611 } finally {
11612 Binder.restoreCallingIdentity(identity);
11613 }
11614 }
11615
11616 /**
11617 * Unregister RCS provisioning callback.
11618 */
11619 @Override
Hui Wang3cac7e52021-01-27 14:45:25 -080011620 public void unregisterRcsProvisioningCallback(int subId,
Hui Wang761a6682020-10-31 05:12:53 +000011621 IRcsConfigCallback callback) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011622 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
Hui Wang3cac7e52021-01-27 14:45:25 -080011623 Binder.getCallingUid(), "unregisterRcsProvisioningCallback",
Brad Ebinger34c09a52021-02-17 23:23:21 +000011624 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11625 permission.READ_PRIVILEGED_PHONE_STATE);
Hui Wang761a6682020-10-31 05:12:53 +000011626
11627 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11628 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11629 }
11630 if (!isImsAvailableOnDevice()) {
joonhunshin46b49a32022-12-21 05:33:23 +000011631 // operation failed silently
11632 Rlog.w(LOG_TAG, "IMS not available on device.");
11633 return;
Hui Wang761a6682020-10-31 05:12:53 +000011634 }
11635
11636 final long identity = Binder.clearCallingIdentity();
11637 try {
Hui Wang68cd3722021-01-11 20:04:53 -080011638 RcsProvisioningMonitor.getInstance()
Hui Wang3cac7e52021-01-27 14:45:25 -080011639 .unregisterRcsProvisioningCallback(subId, callback);
Hui Wang761a6682020-10-31 05:12:53 +000011640 } finally {
11641 Binder.restoreCallingIdentity(identity);
11642 }
11643 }
11644
11645 /**
11646 * trigger RCS reconfiguration.
11647 */
11648 public void triggerRcsReconfiguration(int subId) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011649 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
11650 "triggerRcsReconfiguration",
11651 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
Hui Wang761a6682020-10-31 05:12:53 +000011652
11653 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11654 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11655 }
11656 if (!isImsAvailableOnDevice()) {
joonhunshin46b49a32022-12-21 05:33:23 +000011657 // ProvisioningManager can not handle ServiceSpecificException.
11658 // Throw the IllegalStateException and annotate ProvisioningManager.
11659 throw new IllegalStateException("IMS not available on device.");
Hui Wang761a6682020-10-31 05:12:53 +000011660 }
11661
11662 final long identity = Binder.clearCallingIdentity();
11663 try {
11664 RcsProvisioningMonitor.getInstance().requestReconfig(subId);
11665 } finally {
11666 Binder.restoreCallingIdentity(identity);
11667 }
11668 }
11669
11670 /**
11671 * Provide the client configuration parameters of the RCS application.
11672 */
11673 public void setRcsClientConfiguration(int subId, RcsClientConfiguration rcc) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011674 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
11675 "setRcsClientConfiguration",
11676 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
Hui Wang761a6682020-10-31 05:12:53 +000011677
11678 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11679 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11680 }
11681 if (!isImsAvailableOnDevice()) {
11682 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
11683 "IMS not available on device.");
11684 }
11685
11686 final long identity = Binder.clearCallingIdentity();
11687
11688 try {
11689 IImsConfig configBinder = getImsConfig(getSlotIndex(subId), ImsFeature.FEATURE_RCS);
11690 if (configBinder == null) {
11691 Rlog.e(LOG_TAG, "null result for setRcsClientConfiguration");
Brad Ebinger919631e2021-06-02 17:46:35 -070011692 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
11693 "could not find the requested subscription");
Hui Wang761a6682020-10-31 05:12:53 +000011694 } else {
11695 configBinder.setRcsClientConfiguration(rcc);
11696 }
joonhunshin3e154242021-09-17 06:33:39 +000011697
11698 RcsStats.getInstance().onRcsClientProvisioningStats(subId,
11699 RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT);
Hui Wang761a6682020-10-31 05:12:53 +000011700 } catch (RemoteException e) {
11701 Rlog.e(LOG_TAG, "fail to setRcsClientConfiguration " + e.getMessage());
Brad Ebinger919631e2021-06-02 17:46:35 -070011702 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
11703 "service is temporarily unavailable.");
Hui Wang761a6682020-10-31 05:12:53 +000011704 } finally {
11705 Binder.restoreCallingIdentity(identity);
11706 }
11707 }
11708
11709 /**
Hui Wangbaaee6a2021-02-19 20:45:36 -080011710 * Enables or disables the test mode for RCS VoLTE single registration.
11711 */
11712 @Override
11713 public void setRcsSingleRegistrationTestModeEnabled(boolean enabled) {
11714 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11715 "setRcsSingleRegistrationTestModeEnabled");
11716
11717 RcsProvisioningMonitor.getInstance().setTestModeEnabled(enabled);
11718 }
11719
11720 /**
11721 * Gets the test mode for RCS VoLTE single registration.
11722 */
11723 @Override
11724 public boolean getRcsSingleRegistrationTestModeEnabled() {
11725 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11726 "getRcsSingleRegistrationTestModeEnabled");
11727
11728 return RcsProvisioningMonitor.getInstance().getTestModeEnabled();
11729 }
11730
11731 /**
Hui Wang761a6682020-10-31 05:12:53 +000011732 * Overrides the config of RCS VoLTE single registration enabled for the device.
11733 */
11734 @Override
11735 public void setDeviceSingleRegistrationEnabledOverride(String enabledStr) {
11736 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11737 "setDeviceSingleRegistrationEnabledOverride");
11738 enforceModifyPermission();
11739
11740 Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
11741 : Boolean.parseBoolean(enabledStr);
11742 RcsProvisioningMonitor.getInstance().overrideDeviceSingleRegistrationEnabled(enabled);
Brad Ebinger49a72b42021-01-29 00:55:24 +000011743 mApp.imsRcsController.setDeviceSingleRegistrationSupportOverride(enabled);
Hui Wang761a6682020-10-31 05:12:53 +000011744 }
11745
11746 /**
Tyler Gunn92479152021-01-20 16:30:10 -080011747 * Sends a device to device communication message. Only usable via shell.
11748 * @param message message to send.
11749 * @param value message value.
11750 */
11751 @Override
11752 public void sendDeviceToDeviceMessage(int message, int value) {
11753 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
Tyler Gunnbabbda02021-02-10 11:05:02 -080011754 "sendDeviceToDeviceMessage");
Tyler Gunn92479152021-01-20 16:30:10 -080011755 enforceModifyPermission();
11756
11757 final long identity = Binder.clearCallingIdentity();
11758 try {
11759 TelephonyConnectionService service =
11760 TelecomAccountRegistry.getInstance(null).getTelephonyConnectionService();
11761 if (service == null) {
11762 Rlog.e(LOG_TAG, "sendDeviceToDeviceMessage: not in a call.");
11763 return;
11764 }
11765 service.sendTestDeviceToDeviceMessage(message, value);
11766 } finally {
11767 Binder.restoreCallingIdentity(identity);
11768 }
11769 }
11770
Tyler Gunnbabbda02021-02-10 11:05:02 -080011771 /**
11772 * Sets the specified device to device transport active.
11773 * @param transport The transport to set active.
11774 */
11775 @Override
11776 public void setActiveDeviceToDeviceTransport(@NonNull String transport) {
11777 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11778 "setActiveDeviceToDeviceTransport");
11779 enforceModifyPermission();
11780
11781 final long identity = Binder.clearCallingIdentity();
11782 try {
11783 TelephonyConnectionService service =
11784 TelecomAccountRegistry.getInstance(null).getTelephonyConnectionService();
11785 if (service == null) {
11786 Rlog.e(LOG_TAG, "setActiveDeviceToDeviceTransport: not in a call.");
11787 return;
11788 }
11789 service.setActiveDeviceToDeviceTransport(transport);
11790 } finally {
11791 Binder.restoreCallingIdentity(identity);
11792 }
11793 }
Tyler Gunn92479152021-01-20 16:30:10 -080011794
Tyler Gunnd4339262021-05-03 14:46:49 -070011795 @Override
11796 public void setDeviceToDeviceForceEnabled(boolean isForceEnabled) {
11797 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11798 "setDeviceToDeviceForceEnabled");
11799
11800 final long identity = Binder.clearCallingIdentity();
11801 try {
11802 Arrays.stream(PhoneFactory.getPhones()).forEach(
11803 p -> {
11804 Phone thePhone = p.getImsPhone();
11805 if (thePhone != null && thePhone instanceof ImsPhone) {
11806 ImsPhone imsPhone = (ImsPhone) thePhone;
11807 CallTracker tracker = imsPhone.getCallTracker();
11808 if (tracker != null && tracker instanceof ImsPhoneCallTracker) {
11809 ImsPhoneCallTracker imsPhoneCallTracker =
11810 (ImsPhoneCallTracker) tracker;
11811 imsPhoneCallTracker.setDeviceToDeviceForceEnabled(isForceEnabled);
11812 }
11813 }
11814 }
11815 );
11816 } finally {
11817 Binder.restoreCallingIdentity(identity);
11818 }
11819 }
11820
Tyler Gunn92479152021-01-20 16:30:10 -080011821 /**
Hui Wang761a6682020-10-31 05:12:53 +000011822 * Gets the config of RCS VoLTE single registration enabled for the device.
11823 */
11824 @Override
11825 public boolean getDeviceSingleRegistrationEnabled() {
11826 enforceReadPrivilegedPermission("getDeviceSingleRegistrationEnabled");
11827 return RcsProvisioningMonitor.getInstance().getDeviceSingleRegistrationEnabled();
11828 }
11829
11830 /**
11831 * Overrides the config of RCS VoLTE single registration enabled for the carrier/subscription.
11832 */
11833 @Override
11834 public boolean setCarrierSingleRegistrationEnabledOverride(int subId, String enabledStr) {
11835 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11836 "setCarrierSingleRegistrationEnabledOverride");
11837 enforceModifyPermission();
11838
11839 Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
11840 : Boolean.parseBoolean(enabledStr);
11841 return RcsProvisioningMonitor.getInstance().overrideCarrierSingleRegistrationEnabled(
11842 subId, enabled);
11843 }
11844
11845 /**
11846 * Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
11847 */
11848 @Override
11849 public boolean getCarrierSingleRegistrationEnabled(int subId) {
11850 enforceReadPrivilegedPermission("getCarrierSingleRegistrationEnabled");
11851 return RcsProvisioningMonitor.getInstance().getCarrierSingleRegistrationEnabled(subId);
11852 }
Chiachang Wangd6d34772020-12-22 11:38:27 +080011853
11854 /**
Hui Wangb647abe2021-02-26 09:33:38 -080011855 * Overrides the ims feature validation result
11856 */
11857 @Override
11858 public boolean setImsFeatureValidationOverride(int subId, String enabledStr) {
11859 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11860 "setImsFeatureValidationOverride");
11861
11862 Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
11863 : Boolean.parseBoolean(enabledStr);
11864 return RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(
11865 subId, enabled);
11866 }
11867
11868 /**
11869 * Gets the ims feature validation override value
11870 */
11871 @Override
11872 public boolean getImsFeatureValidationOverride(int subId) {
11873 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11874 "getImsFeatureValidationOverride");
11875 return RcsProvisioningMonitor.getInstance().getImsFeatureValidationOverride(subId);
11876 }
11877
11878 /**
Chiachang Wangd6d34772020-12-22 11:38:27 +080011879 * Get the mobile provisioning url that is used to launch a browser to allow users to manage
11880 * their mobile plan.
11881 */
11882 @Override
11883 public String getMobileProvisioningUrl() {
11884 enforceReadPrivilegedPermission("getMobileProvisioningUrl");
11885 final long identity = Binder.clearCallingIdentity();
11886 try {
11887 return getDefaultPhone().getMobileProvisioningUrl();
11888 } finally {
11889 Binder.restoreCallingIdentity(identity);
11890 }
11891 }
Rambo Wanga5cc9b72021-01-07 10:51:54 -080011892
James.cf Linbcdf8b32021-01-14 16:44:13 +080011893 /**
calvinpane4a8a1d2021-01-25 13:51:18 +080011894 * Get the EAB contact from the EAB database.
11895 */
11896 @Override
11897 public String getContactFromEab(String contact) {
11898 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getContactFromEab");
11899 enforceModifyPermission();
11900 final long identity = Binder.clearCallingIdentity();
11901 try {
11902 return EabUtil.getContactFromEab(getDefaultPhone().getContext(), contact);
11903 } finally {
11904 Binder.restoreCallingIdentity(identity);
11905 }
11906 }
11907
11908 /**
Calvin Pana1434322021-07-01 19:27:01 +080011909 * Get the EAB capability from the EAB database.
11910 */
11911 @Override
11912 public String getCapabilityFromEab(String contact) {
11913 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getCapabilityFromEab");
11914 enforceModifyPermission();
11915 final long identity = Binder.clearCallingIdentity();
11916 try {
11917 return EabUtil.getCapabilityFromEab(getDefaultPhone().getContext(), contact);
11918 } finally {
11919 Binder.restoreCallingIdentity(identity);
11920 }
11921 }
11922
11923 /**
James.cf Linbcdf8b32021-01-14 16:44:13 +080011924 * Remove the EAB contacts from the EAB database.
11925 */
11926 @Override
11927 public int removeContactFromEab(int subId, String contacts) {
11928 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "removeCapabilitiesFromEab");
11929 enforceModifyPermission();
11930 final long identity = Binder.clearCallingIdentity();
11931 try {
11932 return EabUtil.removeContactFromEab(subId, contacts, getDefaultPhone().getContext());
11933 } finally {
11934 Binder.restoreCallingIdentity(identity);
11935 }
11936 }
11937
Rambo Wanga5cc9b72021-01-07 10:51:54 -080011938 @Override
James.cf Lin4b784aa2021-01-31 03:25:15 +080011939 public boolean getDeviceUceEnabled() {
11940 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getDeviceUceEnabled");
11941 final long identity = Binder.clearCallingIdentity();
11942 try {
11943 return mApp.getDeviceUceEnabled();
11944 } finally {
11945 Binder.restoreCallingIdentity(identity);
11946 }
11947 }
11948
11949 @Override
11950 public void setDeviceUceEnabled(boolean isEnabled) {
11951 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setDeviceUceEnabled");
11952 final long identity = Binder.clearCallingIdentity();
11953 try {
11954 mApp.setDeviceUceEnabled(isEnabled);
11955 } finally {
11956 Binder.restoreCallingIdentity(identity);
11957 }
11958 }
11959
Brad Ebinger14d467f2021-02-12 06:18:28 +000011960 /**
11961 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
11962 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
11963 */
11964 // Used for SHELL command only right now.
11965 @Override
11966 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
11967 List<String> featureTags) {
11968 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11969 "addUceRegistrationOverrideShell");
11970 final long identity = Binder.clearCallingIdentity();
11971 try {
11972 return mApp.imsRcsController.addUceRegistrationOverrideShell(subId,
11973 new ArraySet<>(featureTags));
11974 } catch (ImsException e) {
11975 throw new ServiceSpecificException(e.getCode(), e.getMessage());
11976 } finally {
11977 Binder.restoreCallingIdentity(identity);
11978 }
11979 }
11980
11981 /**
11982 * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
11983 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
11984 */
11985 // Used for SHELL command only right now.
11986 @Override
11987 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
11988 List<String> featureTags) {
11989 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11990 "removeUceRegistrationOverrideShell");
11991 final long identity = Binder.clearCallingIdentity();
11992 try {
11993 return mApp.imsRcsController.removeUceRegistrationOverrideShell(subId,
11994 new ArraySet<>(featureTags));
11995 } catch (ImsException e) {
11996 throw new ServiceSpecificException(e.getCode(), e.getMessage());
11997 } finally {
11998 Binder.restoreCallingIdentity(identity);
11999 }
12000 }
12001
12002 /**
12003 * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
12004 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
12005 */
12006 // Used for SHELL command only right now.
12007 @Override
12008 public RcsContactUceCapability clearUceRegistrationOverrideShell(int subId) {
12009 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
12010 "clearUceRegistrationOverrideShell");
12011 final long identity = Binder.clearCallingIdentity();
12012 try {
12013 return mApp.imsRcsController.clearUceRegistrationOverrideShell(subId);
12014 } catch (ImsException e) {
12015 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12016 } finally {
12017 Binder.restoreCallingIdentity(identity);
12018 }
12019 }
12020
12021 /**
12022 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
12023 */
12024 // Used for SHELL command only right now.
12025 @Override
12026 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId) {
12027 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
12028 "getLatestRcsContactUceCapabilityShell");
12029 final long identity = Binder.clearCallingIdentity();
12030 try {
12031 return mApp.imsRcsController.getLatestRcsContactUceCapabilityShell(subId);
12032 } catch (ImsException e) {
12033 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12034 } finally {
12035 Binder.restoreCallingIdentity(identity);
12036 }
12037 }
12038
12039 /**
12040 * Returns the last PIDF XML sent to the network during the last PUBLISH or "none" if the
12041 * device does not have an active PUBLISH.
12042 */
12043 // Used for SHELL command only right now.
12044 @Override
12045 public String getLastUcePidfXmlShell(int subId) {
12046 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "uceGetLastPidfXml");
12047 final long identity = Binder.clearCallingIdentity();
12048 try {
12049 return mApp.imsRcsController.getLastUcePidfXmlShell(subId);
12050 } catch (ImsException e) {
12051 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12052 } finally {
12053 Binder.restoreCallingIdentity(identity);
12054 }
12055 }
12056
James.cf Line8713a42021-04-29 16:04:26 +080012057 /**
12058 * Remove UCE requests cannot be sent to the network status.
12059 */
12060 // Used for SHELL command only right now.
12061 @Override
12062 public boolean removeUceRequestDisallowedStatus(int subId) {
12063 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "uceRemoveDisallowedStatus");
12064 final long identity = Binder.clearCallingIdentity();
12065 try {
12066 return mApp.imsRcsController.removeUceRequestDisallowedStatus(subId);
12067 } catch (ImsException e) {
12068 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12069 } finally {
12070 Binder.restoreCallingIdentity(identity);
12071 }
12072 }
12073
James.cf Lin18bb9002021-05-25 01:37:38 +080012074 /**
12075 * Remove UCE requests cannot be sent to the network status.
12076 */
12077 // Used for SHELL command only.
12078 @Override
12079 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfterMs) {
12080 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCapRequestTimeout");
12081 final long identity = Binder.clearCallingIdentity();
12082 try {
12083 return mApp.imsRcsController.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
12084 } catch (ImsException e) {
12085 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12086 } finally {
12087 Binder.restoreCallingIdentity(identity);
12088 }
12089 }
Brad Ebinger14d467f2021-02-12 06:18:28 +000012090
James.cf Lin4b784aa2021-01-31 03:25:15 +080012091 @Override
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012092 public void setSignalStrengthUpdateRequest(int subId, SignalStrengthUpdateRequest request,
12093 String callingPackage) {
12094 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
12095 mApp, subId, "setSignalStrengthUpdateRequest");
12096
12097 final int callingUid = Binder.getCallingUid();
12098 // Verify that tha callingPackage belongs to the calling UID
12099 mApp.getSystemService(AppOpsManager.class)
12100 .checkPackage(callingUid, callingPackage);
12101
Rambo Wang3607f502021-02-01 21:51:40 -080012102 validateSignalStrengthUpdateRequest(mApp, request, callingUid);
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012103
12104 final long identity = Binder.clearCallingIdentity();
12105 try {
12106 Object result = sendRequest(CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST,
12107 new Pair<Integer, SignalStrengthUpdateRequest>(callingUid, request), subId);
12108
12109 if (result instanceof IllegalStateException) {
12110 throw (IllegalStateException) result;
12111 }
12112 } finally {
12113 Binder.restoreCallingIdentity(identity);
12114 }
12115 }
12116
12117 @Override
12118 public void clearSignalStrengthUpdateRequest(int subId, SignalStrengthUpdateRequest request,
12119 String callingPackage) {
12120 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
12121 mApp, subId, "clearSignalStrengthUpdateRequest");
12122
12123 final int callingUid = Binder.getCallingUid();
12124 // Verify that tha callingPackage belongs to the calling UID
12125 mApp.getSystemService(AppOpsManager.class)
12126 .checkPackage(callingUid, callingPackage);
12127
12128 final long identity = Binder.clearCallingIdentity();
12129 try {
12130 Object result = sendRequest(CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST,
12131 new Pair<Integer, SignalStrengthUpdateRequest>(callingUid, request), subId);
12132
12133 if (result instanceof IllegalStateException) {
12134 throw (IllegalStateException) result;
12135 }
12136 } finally {
12137 Binder.restoreCallingIdentity(identity);
12138 }
12139 }
12140
Rambo Wang3607f502021-02-01 21:51:40 -080012141 private static void validateSignalStrengthUpdateRequest(Context context,
12142 SignalStrengthUpdateRequest request, int callingUid) {
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012143 if (callingUid == Process.PHONE_UID || callingUid == Process.SYSTEM_UID) {
12144 // phone/system process do not have further restriction on request
12145 return;
12146 }
12147
12148 // Applications has restrictions on how to use the request:
Rambo Wang3607f502021-02-01 21:51:40 -080012149 // Non-system callers need permission to set mIsSystemThresholdReportingRequestedWhileIdle
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012150 if (request.isSystemThresholdReportingRequestedWhileIdle()) {
Rambo Wang3607f502021-02-01 21:51:40 -080012151 context.enforceCallingOrSelfPermission(
12152 android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH,
12153 "validateSignalStrengthUpdateRequest");
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012154 }
12155
12156 for (SignalThresholdInfo info : request.getSignalThresholdInfos()) {
Nagendra Prasad Nagarle Basavarajufee544c2022-12-07 16:34:52 +000012157 // Only system caller can set mHysteresisMs/mIsEnabled.
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012158 if (info.getHysteresisMs() != SignalThresholdInfo.HYSTERESIS_MS_DISABLED
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012159 || info.isEnabled()) {
12160 throw new IllegalArgumentException(
12161 "Only system can set hide fields in SignalThresholdInfo");
12162 }
12163
12164 // Thresholds length for each RAN need in range. This has been validated in
12165 // SignalThresholdInfo#Builder#setThreshold. Here we prevent apps calling hide method
12166 // setThresholdUnlimited (e.g. through reflection) with too short or too long thresholds
12167 final int[] thresholds = info.getThresholds();
12168 Objects.requireNonNull(thresholds);
12169 if (thresholds.length < SignalThresholdInfo.getMinimumNumberOfThresholdsAllowed()
12170 || thresholds.length
12171 > SignalThresholdInfo.getMaximumNumberOfThresholdsAllowed()) {
12172 throw new IllegalArgumentException(
12173 "thresholds length is out of range: " + thresholds.length);
12174 }
12175 }
12176 }
SongFerngWang8236caa2021-01-17 21:51:44 +080012177
12178 /**
12179 * Gets the current phone capability.
12180 *
12181 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
12182 * @return the PhoneCapability which describes the data connection capability of modem.
12183 * It's used to evaluate possible phone config change, for example from single
12184 * SIM device to multi-SIM device.
12185 */
12186 @Override
12187 public PhoneCapability getPhoneCapability() {
12188 enforceReadPrivilegedPermission("getPhoneCapability");
12189 final long identity = Binder.clearCallingIdentity();
12190 try {
12191 return mPhoneConfigurationManager.getCurrentPhoneCapability();
12192 } finally {
12193 Binder.restoreCallingIdentity(identity);
12194 }
12195 }
Michele Berionne5e411512020-11-13 02:36:59 +000012196
12197 /**
12198 * Prepare TelephonyManager for an unattended reboot. The reboot is
12199 * required to be done shortly after the API is invoked.
12200 */
12201 @Override
12202 @TelephonyManager.PrepareUnattendedRebootResult
12203 public int prepareForUnattendedReboot() {
Rafael Higuera Silvad9630642021-09-20 15:32:01 +000012204 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Michele Berionne5e411512020-11-13 02:36:59 +000012205 enforceRebootPermission();
12206
12207 final long identity = Binder.clearCallingIdentity();
12208 try {
Rafael Higuera Silvad9630642021-09-20 15:32:01 +000012209 return (int) sendRequest(CMD_PREPARE_UNATTENDED_REBOOT, null, workSource);
Michele Berionne5e411512020-11-13 02:36:59 +000012210 } finally {
12211 Binder.restoreCallingIdentity(identity);
12212 }
12213 }
Hongbo Zeng156aa4a2021-02-08 21:50:28 +080012214
12215 /**
12216 * Request to get the current slicing configuration including URSP rules and
12217 * NSSAIs (configured, allowed and rejected).
12218 *
12219 * Requires carrier privileges or READ_PRIVILEGED_PHONE_STATE permission.
12220 */
12221 @Override
12222 public void getSlicingConfig(ResultReceiver callback) {
Hongbo Zeng1b2063d2022-02-21 01:33:03 +000012223 TelephonyPermissions
12224 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
12225 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, "getSlicingConfig");
Hongbo Zeng156aa4a2021-02-08 21:50:28 +080012226
12227 final long identity = Binder.clearCallingIdentity();
12228 try {
12229 Phone phone = getDefaultPhone();
12230 sendRequestAsync(CMD_GET_SLICING_CONFIG, callback, phone, null);
12231 } finally {
12232 Binder.restoreCallingIdentity(identity);
12233 }
12234 }
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012235
12236 /**
Sarah Chin2ec39f62022-08-31 17:03:26 -070012237 * Check whether the given premium capability is available for purchase from the carrier.
12238 *
12239 * @param capability The premium capability to check.
12240 * @param subId The subId to check the premium capability for.
12241 *
12242 * @return Whether the given premium capability is available to purchase.
12243 */
12244 @Override
12245 public boolean isPremiumCapabilityAvailableForPurchase(int capability, int subId) {
12246 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
12247 mApp, "isPremiumCapabilityAvailableForPurchase")) {
12248 log("Premium capability "
12249 + TelephonyManager.convertPremiumCapabilityToString(capability)
12250 + " is not available for purchase due to missing permissions.");
12251 throw new SecurityException("isPremiumCapabilityAvailableForPurchase requires "
12252 + "permission READ_BASIC_PHONE_STATE.");
12253 }
12254
12255 Phone phone = getPhone(subId);
Thomas Nguyen7216ed62022-11-29 16:45:31 -080012256 if (phone == null) {
12257 loge("isPremiumCapabilityAvailableForPurchase: phone is null, subId=" + subId);
12258 return false;
12259 }
Sarah Chin2ec39f62022-08-31 17:03:26 -070012260 final long identity = Binder.clearCallingIdentity();
12261 try {
Sarah Chin46355ba2022-11-01 23:51:16 -070012262 return SlicePurchaseController.getInstance(phone)
Sarah Chin2ec39f62022-08-31 17:03:26 -070012263 .isPremiumCapabilityAvailableForPurchase(capability);
12264 } finally {
12265 Binder.restoreCallingIdentity(identity);
12266 }
12267 }
12268
12269 /**
12270 * Purchase the given premium capability from the carrier.
12271 *
12272 * @param capability The premium capability to purchase.
12273 * @param callback The result of the purchase request.
12274 * @param subId The subId to purchase the premium capability for.
12275 */
12276 @Override
12277 public void purchasePremiumCapability(int capability, IIntegerConsumer callback, int subId) {
12278 log("purchasePremiumCapability: capability="
12279 + TelephonyManager.convertPremiumCapabilityToString(capability) + ", caller="
12280 + getCurrentPackageName());
12281
12282 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
12283 mApp, "purchasePremiumCapability")) {
12284 log("purchasePremiumCapability "
12285 + TelephonyManager.convertPremiumCapabilityToString(capability)
12286 + " failed due to missing permissions.");
12287 throw new SecurityException("purchasePremiumCapability requires permission "
12288 + "READ_BASIC_PHONE_STATE.");
Sarah Chin532d6bb2022-12-28 22:50:43 -080012289 } else if (!TelephonyPermissions.checkInternetPermissionNoThrow(
12290 mApp, "purchasePremiumCapability")) {
12291 log("purchasePremiumCapability "
12292 + TelephonyManager.convertPremiumCapabilityToString(capability)
12293 + " failed due to missing permissions.");
12294 throw new SecurityException("purchasePremiumCapability requires permission INTERNET.");
Sarah Chin2ec39f62022-08-31 17:03:26 -070012295 }
12296
12297 Phone phone = getPhone(subId);
Sarah Chin19694112022-12-06 15:41:37 -080012298 if (phone == null) {
12299 try {
12300 int result = TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_REQUEST_FAILED;
12301 callback.accept(result);
12302 loge("purchasePremiumCapability: phone is null, subId=" + subId);
12303 } catch (RemoteException e) {
12304 String logStr = "Purchase premium capability "
12305 + TelephonyManager.convertPremiumCapabilityToString(capability)
12306 + " failed due to RemoteException handling null phone: " + e;
12307 if (DBG) log(logStr);
12308 AnomalyReporter.reportAnomaly(
12309 UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
12310 }
12311 return;
12312 }
Sarah Chin532d6bb2022-12-28 22:50:43 -080012313
12314 String callingProcess;
Sarah Chin71b3a852022-09-28 15:54:19 -070012315 try {
Sarah Chin532d6bb2022-12-28 22:50:43 -080012316 callingProcess = mApp.getPackageManager().getApplicationInfo(
12317 getCurrentPackageName(), 0).processName;
Sarah Chin71b3a852022-09-28 15:54:19 -070012318 } catch (PackageManager.NameNotFoundException e) {
Sarah Chin532d6bb2022-12-28 22:50:43 -080012319 callingProcess = getCurrentPackageName();
Sarah Chin71b3a852022-09-28 15:54:19 -070012320 }
Sarah Chin532d6bb2022-12-28 22:50:43 -080012321
12322 boolean isVisible = false;
12323 ActivityManager am = mApp.getSystemService(ActivityManager.class);
12324 if (am != null) {
12325 List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
12326 if (processes != null) {
12327 for (ActivityManager.RunningAppProcessInfo process : processes) {
12328 log("purchasePremiumCapability: process " + process.processName
12329 + "has importance " + process.importance);
12330 if (process.processName.equals(callingProcess) && process.importance
12331 <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
12332 isVisible = true;
12333 break;
12334 }
12335 }
12336 }
12337 }
12338
12339 if (!isVisible) {
12340 try {
12341 int result = TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND;
12342 callback.accept(result);
12343 loge("purchasePremiumCapability: " + callingProcess + " is not in the foreground.");
12344 } catch (RemoteException e) {
12345 String logStr = "Purchase premium capability "
12346 + TelephonyManager.convertPremiumCapabilityToString(capability)
12347 + " failed due to RemoteException handling background application: " + e;
12348 if (DBG) log(logStr);
12349 AnomalyReporter.reportAnomaly(
12350 UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
12351 }
12352 return;
12353 }
12354
Sarah Chin71b3a852022-09-28 15:54:19 -070012355 sendRequestAsync(CMD_PURCHASE_PREMIUM_CAPABILITY,
Sarah Chinb8218c22023-01-04 13:35:29 -080012356 new PurchasePremiumCapabilityArgument(capability, callback), phone, null);
Sarah Chin2ec39f62022-08-31 17:03:26 -070012357 }
12358
12359 /**
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012360 * Register an IMS connection state callback
12361 */
12362 @Override
Hunsuk Choi89bd22c2021-11-01 13:04:54 +000012363 public void registerImsStateCallback(int subId, int feature, IImsStateCallback cb,
12364 String callingPackage) {
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012365 if (feature == ImsFeature.FEATURE_MMTEL) {
12366 // ImsMmTelManager
12367 // The following also checks READ_PRIVILEGED_PHONE_STATE.
12368 TelephonyPermissions
12369 .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
12370 mApp, subId, "registerImsStateCallback");
12371 } else if (feature == ImsFeature.FEATURE_RCS) {
12372 // ImsRcsManager or SipDelegateManager
12373 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
12374 Binder.getCallingUid(), "registerImsStateCallback",
12375 Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
12376 Manifest.permission.READ_PRECISE_PHONE_STATE,
12377 Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
12378 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
12379 }
12380
12381 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
12382 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
12383 "IMS not available on device.");
12384 }
12385
12386 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
12387 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
12388 }
12389
12390 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
12391 if (controller == null) {
12392 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
12393 "IMS not available on device.");
12394 }
12395
Hunsuk Choi89bd22c2021-11-01 13:04:54 +000012396 if (callingPackage == null) {
12397 callingPackage = getCurrentPackageName();
12398 }
12399
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012400 final long token = Binder.clearCallingIdentity();
12401 try {
12402 int slotId = getSlotIndexOrException(subId);
Hunsuk Choi89bd22c2021-11-01 13:04:54 +000012403 controller.registerImsStateCallback(subId, feature, cb, callingPackage);
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012404 } catch (ImsException e) {
12405 throw new ServiceSpecificException(e.getCode());
12406 } finally {
12407 Binder.restoreCallingIdentity(token);
12408 }
12409 }
12410
12411 /**
12412 * Unregister an IMS connection state callback
12413 */
12414 @Override
12415 public void unregisterImsStateCallback(IImsStateCallback cb) {
12416 final long token = Binder.clearCallingIdentity();
12417 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
12418 if (controller == null) {
12419 return;
12420 }
12421 try {
12422 controller.unregisterImsStateCallback(cb);
12423 } finally {
12424 Binder.restoreCallingIdentity(token);
12425 }
12426 }
Sooraj Sasindranfae41b32021-10-26 02:10:05 -070012427
12428 /**
12429 * @return {@CellIdentity} last known cell identity {@CellIdentity}.
12430 *
12431 * Require {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
12432 * com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID, otherwise throws
12433 * SecurityException.
12434 * If there is current registered network this value will be same as the registered cell
12435 * identity. If the device goes out of service the previous cell identity is cached and
12436 * will be returned. If the cache age of the Cell identity is more than 24 hours
12437 * it will be cleared and null will be returned.
12438 *
12439 */
12440 @Override
12441 public @Nullable CellIdentity getLastKnownCellIdentity(int subId, String callingPackage,
12442 String callingFeatureId) {
12443 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12444 LocationAccessPolicy.LocationPermissionResult fineLocationResult =
12445 LocationAccessPolicy.checkLocationPermission(mApp,
12446 new LocationAccessPolicy.LocationPermissionQuery.Builder()
12447 .setCallingPackage(callingPackage)
12448 .setCallingFeatureId(callingFeatureId)
12449 .setCallingPid(Binder.getCallingPid())
12450 .setCallingUid(Binder.getCallingUid())
12451 .setMethod("getLastKnownCellIdentity")
12452 .setLogAsInfo(true)
12453 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
12454 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
12455 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
12456 .build());
12457
12458 boolean hasFinePermission =
12459 fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
12460 if (!hasFinePermission
12461 || !TelephonyPermissions.checkLastKnownCellIdAccessPermission(mApp)) {
12462 throw new SecurityException("getLastKnownCellIdentity need ACCESS_FINE_LOCATION "
Rambo Wang918993a2022-04-27 09:08:36 -070012463 + "and ACCESS_LAST_KNOWN_CELL_ID permission.");
Sooraj Sasindranfae41b32021-10-26 02:10:05 -070012464 }
12465
12466 final long identity = Binder.clearCallingIdentity();
12467 try {
12468 Phone phone = getPhone(subId);
12469 if (phone == null) return null;
12470 ServiceStateTracker sst = phone.getServiceStateTracker();
12471 if (sst == null) return null;
12472 return sst.getLastKnownCellIdentity();
12473 } finally {
12474 Binder.restoreCallingIdentity(identity);
12475 }
12476 }
Jack Yu4c0a5502021-12-03 23:58:26 -080012477
jimsun3b9ccac2021-10-26 15:01:23 +080012478 /**
12479 * Sets the modem service class Name that Telephony will bind to.
12480 *
12481 * @param serviceName The class name of the modem service.
12482 * @return true if the operation is succeed, otherwise false.
12483 */
12484 public boolean setModemService(String serviceName) {
12485 Log.d(LOG_TAG, "setModemService - " + serviceName);
12486 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setModemService");
12487 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012488 SubscriptionManager.INVALID_SUBSCRIPTION_ID,
12489 "setModemService");
jimsun3b9ccac2021-10-26 15:01:23 +080012490 return mPhoneConfigurationManager.setModemService(serviceName);
12491 }
12492
12493 /**
12494 * Return the class name of the currently bounded modem service.
12495 *
12496 * @return the class name of the modem service.
12497 */
12498 public String getModemService() {
12499 String result;
12500 Log.d(LOG_TAG, "getModemService");
12501 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getModemService");
12502 TelephonyPermissions
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012503 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
jimsun3b9ccac2021-10-26 15:01:23 +080012504 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
12505 "getModemService");
12506 result = mPhoneConfigurationManager.getModemService();
12507 Log.d(LOG_TAG, "result = " + result);
12508 return result;
12509 }
Hunter Knepshield2b076fa2022-01-19 02:26:22 -080012510
12511 @Override
12512 public void setVoiceServiceStateOverride(int subId, boolean hasService, String callingPackage) {
12513 // Only telecom (and shell, for CTS purposes) is allowed to call this method.
12514 mApp.enforceCallingOrSelfPermission(
12515 permission.BIND_TELECOM_CONNECTION_SERVICE, "setVoiceServiceStateOverride");
12516 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12517
12518 final long identity = Binder.clearCallingIdentity();
12519 try {
12520 Phone phone = getPhone(subId);
12521 if (phone == null) return;
Grant Menke63ade122023-01-20 14:31:54 -080012522 Log.i(LOG_TAG, "setVoiceServiceStateOverride: subId=" + subId + ", phone=" + phone
12523 + ", hasService=" + hasService + ", callingPackage=" + callingPackage);
Hunter Knepshield2b076fa2022-01-19 02:26:22 -080012524 phone.setVoiceServiceStateOverride(hasService);
12525 } finally {
12526 Binder.restoreCallingIdentity(identity);
12527 }
12528 }
Muralidhar Reddy4e5a8012022-05-11 14:49:00 +000012529
12530 /**
12531 * set removable eSIM as default eUICC.
12532 *
12533 * @hide
12534 */
12535 @Override
12536 public void setRemovableEsimAsDefaultEuicc(boolean isDefault, String callingPackage) {
12537 enforceModifyPermission();
12538 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12539
12540 final long identity = Binder.clearCallingIdentity();
12541 try {
12542 UiccController.getInstance().setRemovableEsimAsDefaultEuicc(isDefault);
12543 } finally {
12544 Binder.restoreCallingIdentity(identity);
12545 }
12546 }
12547
12548 /**
12549 * Returns whether the removable eSIM is default eUICC or not.
12550 *
12551 * @hide
12552 */
12553 @Override
12554 public boolean isRemovableEsimDefaultEuicc(String callingPackage) {
12555 enforceReadPrivilegedPermission("isRemovableEsimDefaultEuicc");
12556 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12557
12558 final long identity = Binder.clearCallingIdentity();
12559 try {
12560 return UiccController.getInstance().isRemovableEsimDefaultEuicc();
12561 } finally {
12562 Binder.restoreCallingIdentity(identity);
12563 }
12564 }
12565
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +000012566 /**
12567 * Get the component name of the default app to direct respond-via-message intent for the
12568 * user associated with this subscription, update the cache if there is no respond-via-message
12569 * application currently configured for this user.
12570 * @return component name of the app and class to direct Respond Via Message intent to, or
12571 * {@code null} if the functionality is not supported.
12572 * @hide
12573 */
12574 @Override
12575 public @Nullable ComponentName getDefaultRespondViaMessageApplication(int subId,
12576 boolean updateIfNeeded) {
12577 enforceInteractAcrossUsersPermission("getDefaultRespondViaMessageApplication");
Muralidhar Reddy4e5a8012022-05-11 14:49:00 +000012578
Aishwarya Mallampati5e581e12023-01-17 21:57:06 +000012579 Context context = getPhoneFromSubIdOrDefault(subId).getContext();
12580
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +000012581 UserHandle userHandle = null;
12582 final long identity = Binder.clearCallingIdentity();
12583 try {
12584 userHandle = TelephonyUtils.getSubscriptionUserHandle(context, subId);
12585 } finally {
12586 Binder.restoreCallingIdentity(identity);
12587 }
12588 return SmsApplication.getDefaultRespondViaMessageApplicationAsUser(context,
12589 updateIfNeeded, userHandle);
12590 }
Jack Yuf5badd92022-12-08 00:50:53 -080012591
12592 /**
Gil Cukierman1c0eb932022-12-06 22:28:24 +000012593 * Set whether the device is able to connect with null ciphering or integrity
12594 * algorithms. This is a global setting and will apply to all active subscriptions
12595 * and all new subscriptions after this.
12596 *
12597 * @param enabled when true, null cipher and integrity algorithms are allowed.
12598 * @hide
12599 */
12600 @Override
12601 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
12602 public void setNullCipherAndIntegrityEnabled(boolean enabled) {
12603 enforceModifyPermission();
12604 checkForNullCipherAndIntegritySupport();
12605
12606 // Persist the state of our preference. Each GsmCdmaPhone instance is responsible
12607 // for listening to these preference changes and applying them immediately.
12608 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
12609 editor.putBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, enabled);
12610 editor.apply();
12611
12612 for (Phone phone: PhoneFactory.getPhones()) {
12613 phone.handleNullCipherEnabledChange();
12614 }
12615 }
12616
12617
12618 /**
12619 * Get whether the device is able to connect with null ciphering or integrity
12620 * algorithms. Note that this retrieves the phone-global preference and not
12621 * the state of the radio.
12622 *
12623 * @throws SecurityException if {@link permission#MODIFY_PHONE_STATE} is not satisfied
12624 * @throws UnsupportedOperationException if the device does not support the minimum HAL
12625 * version for this feature.
12626 * @hide
12627 */
12628 @Override
12629 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
12630 public boolean isNullCipherAndIntegrityPreferenceEnabled() {
12631 enforceReadPermission();
12632 checkForNullCipherAndIntegritySupport();
12633 return getDefaultPhone().getNullCipherAndIntegrityEnabledPreference();
12634 }
12635
12636 private void checkForNullCipherAndIntegritySupport() {
12637 if (getHalVersion(HAL_SERVICE_NETWORK) < MIN_NULL_CIPHER_AND_INTEGRITY_VERSION) {
12638 throw new UnsupportedOperationException(
12639 "Null cipher and integrity operations require HAL 2.1 or above");
12640 }
Gil Cukierman92cc7db2023-01-06 19:25:53 +000012641 if (!getDefaultPhone().isNullCipherAndIntegritySupported()) {
12642 throw new UnsupportedOperationException(
12643 "Null cipher and integrity operations unsupported by modem");
12644 }
Gil Cukierman1c0eb932022-12-06 22:28:24 +000012645 }
12646
12647 /**
Jack Yuf5badd92022-12-08 00:50:53 -080012648 * Get the SIM state for the slot index.
12649 * For Remote-SIMs, this method returns {@link IccCardConstants.State#UNKNOWN}
12650 *
12651 * @return SIM state as the ordinal of {@link IccCardConstants.State}
12652 */
12653 @Override
12654 @SimState
12655 public int getSimStateForSlotIndex(int slotIndex) {
12656 IccCardConstants.State simState;
12657 if (slotIndex < 0) {
12658 simState = IccCardConstants.State.UNKNOWN;
12659 } else {
12660 Phone phone = null;
12661 try {
12662 phone = PhoneFactory.getPhone(slotIndex);
12663 } catch (IllegalStateException e) {
12664 // ignore
12665 }
12666 if (phone == null) {
12667 simState = IccCardConstants.State.UNKNOWN;
12668 } else {
12669 IccCard icc = phone.getIccCard();
12670 if (icc == null) {
12671 simState = IccCardConstants.State.UNKNOWN;
12672 } else {
12673 simState = icc.getState();
12674 }
12675 }
12676 }
12677 return simState.ordinal();
12678 }
Hui Wang9b5793a2022-12-05 14:38:06 -060012679
12680 /**
12681 * Get current cell broadcast ranges.
12682 */
12683 @Override
12684 @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
12685 public List<CellBroadcastIdRange> getCellBroadcastIdRanges(int subId) {
12686 mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
12687 "getCellBroadcastIdRanges");
12688 final long identity = Binder.clearCallingIdentity();
12689 try {
12690 return getPhone(subId).getCellBroadcastIdRanges();
12691 } finally {
12692 Binder.restoreCallingIdentity(identity);
12693 }
12694 }
12695
12696 /**
12697 * Set reception of cell broadcast messages with the list of the given ranges
12698 *
12699 * @param ranges the list of {@link CellBroadcastIdRange} to be enabled
12700 */
12701 @Override
12702 @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
12703 public void setCellBroadcastIdRanges(int subId, @NonNull List<CellBroadcastIdRange> ranges,
12704 @Nullable IIntegerConsumer callback) {
12705 mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
12706 "setCellBroadcastIdRanges");
12707 final long identity = Binder.clearCallingIdentity();
12708 try {
12709 Phone phone = getPhoneFromSubId(subId);
12710 if (DBG) {
12711 log("setCellBroadcastIdRanges for subId :" + subId + ", phone:" + phone);
12712 }
12713 phone.setCellBroadcastIdRanges(ranges, result -> {
12714 if (callback != null) {
12715 try {
12716 callback.accept(result);
12717 } catch (RemoteException e) {
12718 Log.w(LOG_TAG, "setCellBroadcastIdRanges: callback not available.");
12719 }
12720 }
12721 });
12722 } finally {
12723 Binder.restoreCallingIdentity(identity);
12724 }
12725 }
Hunsuk Choi42cc62a2022-10-16 06:03:40 +000012726
12727 /**
12728 * Returns whether the device supports the domain selection service.
12729 *
12730 * @return {@code true} if the device supports the domain selection service.
12731 */
12732 @Override
12733 public boolean isDomainSelectionSupported() {
12734 mApp.enforceCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
12735 "isDomainSelectionSupported");
12736
12737 final long identity = Binder.clearCallingIdentity();
12738 try {
12739 return DomainSelectionResolver.getInstance().isDomainSelectionSupported();
12740 } finally {
12741 Binder.restoreCallingIdentity(identity);
12742 }
12743 }
arunvoddud5c6ce02022-12-11 06:03:12 +000012744
12745 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012746 * Enable or disable the satellite modem. If the satellite modem is enabled, this will also
12747 * disable the cellular modem, and if the satellite modem is disabled, this will also re-enable
12748 * the cellular modem.
Sarah Chin503828c2023-02-01 23:54:20 -080012749 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012750 * @param subId The subId of the subscription to set satellite enabled for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012751 * @param enable {@code true} to enable the satellite modem and {@code false} to disable.
12752 * @param callback The callback to get the error code of the request.
Sarah Chin503828c2023-02-01 23:54:20 -080012753 *
12754 * @throws SecurityException if the caller doesn't have the required permission.
12755 */
12756 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012757 public void setSatelliteEnabled(int subId, boolean enable, @NonNull IIntegerConsumer callback) {
12758 enforceSatelliteCommunicationPermission("setSatelliteEnabled");
12759 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012760 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012761 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
12762 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012763 }
Sarah Chin503828c2023-02-01 23:54:20 -080012764
12765 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012766 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012767 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
12768 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012769 }
12770
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012771 Phone phone = getPhoneOrDefault(validSubId, "setSatelliteEnabled");
Sarah Chin503828c2023-02-01 23:54:20 -080012772 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012773 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
12774 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012775 }
12776
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012777 Pair<Boolean, Consumer<Integer>> arg = new Pair<>(enable, result);
12778 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, arg, phone, null);
Sarah Chin503828c2023-02-01 23:54:20 -080012779 }
12780
12781 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012782 * Request to get whether the satellite modem is enabled.
Sarah Chin503828c2023-02-01 23:54:20 -080012783 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012784 * @param subId The subId of the subscription to check whether satellite is enabled for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012785 * @param result The result receiver that returns whether the satellite modem is enabled
12786 * if the request is successful or an error code if the request failed.
Sarah Chin503828c2023-02-01 23:54:20 -080012787 *
12788 * @throws SecurityException if the caller doesn't have the required permission.
12789 */
12790 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012791 public void requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result) {
12792 enforceSatelliteCommunicationPermission("requestIsSatelliteEnabled");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012793 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012794 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
12795 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012796 }
Sarah Chin503828c2023-02-01 23:54:20 -080012797
12798 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012799 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012800 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
12801 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012802 }
12803
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012804 Phone phone = getPhoneOrDefault(validSubId, "requestIsSatelliteEnabled");
Sarah Chin503828c2023-02-01 23:54:20 -080012805 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012806 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
12807 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012808 }
12809
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012810 sendRequest(CMD_IS_SATELLITE_ENABLED, result, subId);
Sarah Chin503828c2023-02-01 23:54:20 -080012811 }
12812
12813 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012814 * Request to get whether the satellite service is supported on the device.
Sarah Chin503828c2023-02-01 23:54:20 -080012815 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012816 * @param subId The subId of the subscription to check satellite service support for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012817 * @param result The result receiver that returns whether the satellite service is supported on
12818 * the device if the request is successful or an error code if the request failed.
Sarah Chin503828c2023-02-01 23:54:20 -080012819 */
12820 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012821 public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012822 synchronized (mIsSatelliteSupportedLock) {
12823 if (mIsSatelliteSupported != null) {
12824 /* We have already successfully queried the satellite modem. */
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012825 Bundle bundle = new Bundle();
12826 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported);
12827 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, bundle);
12828 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012829 }
12830 }
Sarah Chin503828c2023-02-01 23:54:20 -080012831
12832 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012833 Phone phone = getPhoneOrDefault(validSubId, "requestIsSatelliteSupported");
Sarah Chin503828c2023-02-01 23:54:20 -080012834 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012835 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
12836 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012837 }
12838
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012839 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, result, phone, null);
Sarah Chin503828c2023-02-01 23:54:20 -080012840 }
12841
12842 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012843 * Request to get the {@link SatelliteCapabilities} of the satellite service.
Sarah Chin503828c2023-02-01 23:54:20 -080012844 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012845 * @param subId The subId of the subscription to get the satellite capabilities for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012846 * @param result The result receiver that returns the {@link SatelliteCapabilities}
12847 * if the request is successful or an error code if the request failed.
Sarah Chin503828c2023-02-01 23:54:20 -080012848 *
12849 * @throws SecurityException if the caller doesn't have required permission.
12850 */
12851 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012852 public void requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result) {
12853 enforceSatelliteCommunicationPermission("requestSatelliteCapabilities");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012854 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012855 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
12856 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012857 }
Sarah Chin503828c2023-02-01 23:54:20 -080012858
12859 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012860 Phone phone = getPhoneOrDefault(validSubId, "requestSatelliteCapabilities");
Sarah Chin503828c2023-02-01 23:54:20 -080012861 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012862 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
12863 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012864 }
12865
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012866 sendRequestAsync(CMD_GET_SATELLITE_CAPABILITIES, result, phone, null);
Sarah Chin503828c2023-02-01 23:54:20 -080012867 }
12868
12869 /**
Sarah Chineccfbd12023-01-20 19:00:35 -080012870 * Start receiving satellite position updates.
12871 * This can be called by the pointing UI when the user starts pointing to the satellite.
12872 * Modem should continue to report the pointing input as the device or satellite moves.
12873 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012874 * @param subId The subId of the subscription to start satellite position updates for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012875 * @param errorCallback The callback to get the error code of the request.
Sarah Chineccfbd12023-01-20 19:00:35 -080012876 * @param callback The callback to notify of changes in satellite position.
Sarah Chin503828c2023-02-01 23:54:20 -080012877 *
12878 * @throws SecurityException if the caller doesn't have the required permission.
Sarah Chineccfbd12023-01-20 19:00:35 -080012879 */
12880 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012881 public void startSatellitePositionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012882 @NonNull ISatelliteStateListener callback) {
Sarah Chinf75afa72023-02-01 01:32:19 -080012883 enforceSatelliteCommunicationPermission("startSatellitePositionUpdates");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012884 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012885 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012886 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
12887 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012888 }
Sarah Chinf75afa72023-02-01 01:32:19 -080012889
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012890 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012891 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012892 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
12893 return;
Sarah Chinf75afa72023-02-01 01:32:19 -080012894 }
12895
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012896 Phone phone = getPhoneOrDefault(validSubId, "startSatellitePositionUpdates");
Sarah Chineccfbd12023-01-20 19:00:35 -080012897 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012898 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
12899 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012900 }
12901
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012902 if (mSatellitePositionUpdateHandlers.containsKey(callback.asBinder())) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012903 if (DBG) {
12904 log("startSatellitePositionUpdates: callback already registered: "
12905 + callback.asBinder());
12906 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012907 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
12908 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012909 }
12910
12911 SatellitePositionUpdateHandler handler =
12912 new SatellitePositionUpdateHandler(callback, Looper.getMainLooper());
12913 phone.registerForSatellitePointingInfoChanged(handler,
12914 SatellitePositionUpdateHandler.EVENT_POSITION_UPDATE, null);
12915 phone.registerForSatelliteMessagesTransferComplete(handler,
12916 SatellitePositionUpdateHandler.EVENT_MESSAGE_TRANSFER_STATE_UPDATE, null);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012917 mSatellitePositionUpdateHandlers.put(callback.asBinder(), handler);
Sarah Chineccfbd12023-01-20 19:00:35 -080012918
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012919 sendRequestAsync(CMD_START_SATELLITE_POSITION_UPDATES, result, phone, null);
Sarah Chineccfbd12023-01-20 19:00:35 -080012920 }
12921
12922 /**
12923 * Stop receiving satellite position updates.
12924 * This can be called by the pointing UI when the user stops pointing to the satellite.
12925 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012926 * @param subId The subId of the subscription to stop satellite position updates for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012927 * @param errorCallback The callback to get the error code of the request.
12928 * @param callback The callback that was passed to {@link
12929 * #startSatellitePositionUpdates(int, IIntegerConsumer, ISatelliteStateListener)}
Sarah Chin503828c2023-02-01 23:54:20 -080012930 *
12931 * @throws SecurityException if the caller doesn't have the required permission.
Sarah Chineccfbd12023-01-20 19:00:35 -080012932 */
12933 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012934 public void stopSatellitePositionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012935 @NonNull ISatelliteStateListener callback) {
Sarah Chinf75afa72023-02-01 01:32:19 -080012936 enforceSatelliteCommunicationPermission("stopSatellitePositionUpdates");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012937 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012938 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012939 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
12940 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012941 }
Sarah Chinf75afa72023-02-01 01:32:19 -080012942
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012943 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012944 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012945 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
12946 return;
Sarah Chinf75afa72023-02-01 01:32:19 -080012947 }
12948
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012949 Phone phone = getPhoneOrDefault(validSubId, "stopSatellitePositionUpdates");
Sarah Chineccfbd12023-01-20 19:00:35 -080012950 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012951 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
12952 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012953 }
12954
12955 SatellitePositionUpdateHandler handler =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012956 mSatellitePositionUpdateHandlers.remove(callback.asBinder());
Sarah Chineccfbd12023-01-20 19:00:35 -080012957 if (handler == null) {
Sarah Chindf715ec2023-02-13 13:46:24 -080012958 loge("stopSatellitePositionUpdates: No SatellitePositionUpdateHandler");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012959 result.accept(SatelliteManager.SATELLITE_INVALID_ARGUMENTS);
12960 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012961 } else {
12962 phone.unregisterForSatellitePointingInfoChanged(handler);
12963 phone.unregisterForSatelliteMessagesTransferComplete(handler);
12964 }
12965
12966 if (!mSatellitePositionUpdateHandlers.isEmpty()) {
12967 log("stopSatellitePositionUpdates: other listeners still exist.");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012968 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
12969 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012970 }
12971
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012972 sendRequestAsync(CMD_STOP_SATELLITE_POSITION_UPDATES, result, phone, null);
Sarah Chineccfbd12023-01-20 19:00:35 -080012973 }
12974
12975 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012976 * Request to get the maximum number of characters per text message on satellite.
12977 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012978 * @param subId The subId of the subscription to get the maximum number of characters for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012979 * @param result The result receiver that returns the maximum number of characters per text
12980 * message on satellite if the request is successful or an error code
12981 * if the request failed.
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000012982 *
12983 * @throws SecurityException if the caller doesn't have the required permission.
12984 */
12985 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012986 public void requestMaxCharactersPerSatelliteTextMessage(int subId,
12987 @NonNull ResultReceiver result) {
12988 enforceSatelliteCommunicationPermission("requestMaxCharactersPerSatelliteTextMessage");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012989 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012990 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
12991 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012992 }
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000012993
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012994 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012995 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012996 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
12997 return;
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000012998 }
12999
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013000 Phone phone = getPhoneOrDefault(validSubId, "requestMaxCharactersPerSatelliteTextMessage");
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013001 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013002 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
13003 return;
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013004 }
13005
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013006 sendRequestAsync(CMD_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG, result, phone, null);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013007 }
13008
13009 /**
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013010 * Register the subscription with a satellite provider.
13011 * This is needed to register the subscription if the provider allows dynamic registration.
13012 *
13013 * @param subId The subId of the subscription to be provisioned.
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013014 * @param token The token to be used as a unique identifier for provisioning with satellite
13015 * gateway.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013016 * @param callback The callback to get the error code of the request.
Sarah Chindf715ec2023-02-13 13:46:24 -080013017 *
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013018 * @return The signal transport used by the caller to cancel the provision request,
13019 * or {@code null} if the request failed.
13020 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013021 * @throws SecurityException if the caller doesn't have the required permission.
13022 */
13023 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013024 @Nullable public ICancellationSignal provisionSatelliteService(int subId,
13025 @NonNull String token, @NonNull IIntegerConsumer callback) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013026 enforceSatelliteCommunicationPermission("provisionSatelliteService");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013027 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013028 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013029 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013030 return null;
13031 }
13032
13033 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013034 Phone phone = getPhoneOrDefault(validSubId, "provisionSatelliteService");
13035 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013036 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013037 return null;
13038 }
13039
13040 if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013041 result.accept(SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013042 return null;
13043 }
13044
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013045 if (isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013046 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013047 return null;
13048 }
13049
13050 sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE,
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013051 new ProvisionSatelliteServiceArgument(token, result, validSubId), phone, null);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013052
13053 ICancellationSignal cancelTransport = CancellationSignal.createTransport();
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013054 CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
13055 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
13056 new ProvisionSatelliteServiceArgument(token, null, validSubId),
13057 phone, null);
13058 });
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013059 return cancelTransport;
13060 }
13061
13062 /**
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013063 * Unregister the device/subscription with the satellite provider.
13064 * This is needed if the provider allows dynamic registration. Once deprovisioned,
13065 * {@link SatelliteCallback.SatelliteProvisionStateListener#onSatelliteProvisionStateChanged}
13066 * should report as deprovisioned.
13067 *
13068 * @param subId The subId of the subscription to be deprovisioned.
13069 * @param token The token of the device/subscription to be deprovisioned.
13070 * @param callback The callback to get the error code of the request.
13071 *
13072 * @throws SecurityException if the caller doesn't have the required permission.
13073 */
13074 @Override
13075 public void deprovisionSatelliteService(int subId,
13076 @NonNull String token, @NonNull IIntegerConsumer callback) {
13077 enforceSatelliteCommunicationPermission("deprovisionSatelliteService");
13078 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
13079 if (!isSatelliteSupported()) {
13080 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
13081 return;
13082 }
13083
13084 final int validSubId = getValidSatelliteSubId(subId);
13085 if (!isSatelliteProvisioned(validSubId)) {
13086 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
13087 return;
13088 }
13089
13090 Phone phone = getPhoneOrDefault(validSubId, "deprovisionSatelliteService");
13091 if (phone == null) {
13092 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13093 return;
13094 }
13095
13096 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
13097 new ProvisionSatelliteServiceArgument(token, result, validSubId), phone, null);
13098 }
13099
13100 /**
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013101 * Register for the satellite provision state change.
13102 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013103 * @param subId The subId of the subscription to register for provision state changes.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013104 * @param callback The callback to handle the satellite provision state changed event.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013105 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013106 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13107 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013108 * @throws SecurityException if the caller doesn't have the required permission.
13109 */
13110 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013111 @SatelliteManager.SatelliteError public int registerForSatelliteProvisionStateChanged(int subId,
13112 @NonNull ISatelliteStateListener callback) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013113 enforceSatelliteCommunicationPermission("registerForSatelliteProvisionStateChanged");
Sarah Chindf715ec2023-02-13 13:46:24 -080013114 return registerForSatelliteProvisionStateChangedInternal(subId, callback);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013115 }
13116
13117 /**
13118 * Unregister for the satellite provision state change.
13119 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013120 * @param subId The subId of the subscription to unregister for provision state changes.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013121 * @param callback The callback that was passed to {@link
Sarah Chindf715ec2023-02-13 13:46:24 -080013122 * #registerForSatelliteProvisionStateChanged(int, ISatelliteStateListener)}.
13123 *
13124 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013125 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013126 * @throws SecurityException if the caller doesn't have the required permission.
13127 */
13128 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013129 @SatelliteManager.SatelliteError public int unregisterForSatelliteProvisionStateChanged(
13130 int subId, @NonNull ISatelliteStateListener callback) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013131 enforceSatelliteCommunicationPermission("unregisterForSatelliteProvisionStateChanged");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013132 if (!isSatelliteSupported()) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013133 return SatelliteManager.SATELLITE_NOT_SUPPORTED;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013134 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013135
13136 final int validSubId = getValidSatelliteSubId(subId);
13137 SatelliteProvisionStateChangedHandler satelliteProvisionStateChangedHandler =
13138 mSatelliteProvisionStateChangedHandlers.get(validSubId);
13139 if (satelliteProvisionStateChangedHandler != null) {
13140 if (satelliteProvisionStateChangedHandler.removeListener(callback)) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013141 return SatelliteManager.SATELLITE_ERROR_NONE;
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013142 }
13143 }
Sarah Chindf715ec2023-02-13 13:46:24 -080013144 return SatelliteManager.SATELLITE_INVALID_ARGUMENTS;
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013145 }
13146
13147 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013148 * Request to get whether the device is provisioned with a satellite provider.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013149 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013150 * @param subId The subId of the subscription to get whether the device is provisioned for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013151 * @param result The result receiver that returns whether the device is provisioned with a
13152 * satellite provider if the request is successful or an error code if the
13153 * request failed.
13154 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013155 * @throws SecurityException if the caller doesn't have the required permission.
13156 */
13157 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013158 public void requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result) {
13159 enforceSatelliteCommunicationPermission("requestIsSatelliteProvisioned");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013160 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013161 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13162 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013163 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013164
13165 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013166 Bundle bundle = new Bundle();
13167 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
13168 isSatelliteProvisioned(validSubId));
13169 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013170 }
13171
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013172 /**
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013173 * Register for listening to satellite modem state changes.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013174 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013175 * @param subId The subId of the subscription to register for satellite modem state changes.
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013176 * @param callback The callback to handle the satellite modem state change event.
Sarah Chindf715ec2023-02-13 13:46:24 -080013177 *
13178 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13179 *
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013180 * @throws SecurityException if the caller doesn't have the required permission.
13181 */
13182 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013183 @SatelliteManager.SatelliteError public int registerForSatelliteModemStateChange(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013184 @NonNull ISatelliteStateListener callback) {
13185 enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChange");
13186
13187 final int validSubId = getValidSatelliteSubId(subId);
13188 Phone phone = getPhoneOrDefault(
13189 validSubId, "registerForSatelliteModemStateChange");
13190 if (phone == null) {
13191 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13192 }
13193
13194 SatelliteStateListenerHandler satelliteStateListenerHandler =
13195 mSatelliteStateListenerHandlers.get(validSubId);
13196 if (satelliteStateListenerHandler == null) {
13197 satelliteStateListenerHandler = new SatelliteStateListenerHandler(
13198 Looper.getMainLooper(), validSubId);
13199 phone.registerForSatelliteModemStateChange(satelliteStateListenerHandler,
13200 SatelliteStateListenerHandler.EVENT_SATELLITE_MODEM_STATE_CHANGE, null);
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013201 phone.registerForPendingDatagramCount(satelliteStateListenerHandler,
13202 SatelliteStateListenerHandler.EVENT_PENDING_DATAGRAM_COUNT, null);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013203 }
13204
13205 satelliteStateListenerHandler.addListener(callback);
13206 mSatelliteStateListenerHandlers.put(validSubId, satelliteStateListenerHandler);
13207 return SatelliteManager.SATELLITE_ERROR_NONE;
13208 }
13209
13210 /**
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013211 * Unregister from listening to satellite modem state changes.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013212 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013213 * @param subId The subId of the subscription to unregister for satellite modem state changes.
13214 * @param callback The callback that was passed to
13215 * {@link #registerForSatelliteModemStateChange(int, ISatelliteStateListener)}.
13216 *
13217 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013218 *
13219 * @throws SecurityException if the caller doesn't have the required permission.
13220 */
13221 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013222 @SatelliteManager.SatelliteError public int unregisterForSatelliteModemStateChange(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013223 @NonNull ISatelliteStateListener callback) {
13224 enforceSatelliteCommunicationPermission("unregisterForSatelliteModemStateChange");
13225
13226 final int validSubId = getValidSatelliteSubId(subId);
13227 SatelliteStateListenerHandler satelliteStateListenerHandler =
13228 mSatelliteStateListenerHandlers.get(validSubId);
13229 if (satelliteStateListenerHandler != null) {
13230 if (satelliteStateListenerHandler.removeListener(callback)) {
13231 return SatelliteManager.SATELLITE_ERROR_NONE;
13232 }
13233 }
13234 return SatelliteManager.SATELLITE_INVALID_ARGUMENTS;
13235 }
13236
13237 /**
13238 * Register to receive incoming datagrams over satellite.
13239 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013240 * @param subId The subId of the subscription to register for incoming satellite datagrams.
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013241 * @param datagramType datagram type indicating whether the datagram is of type
13242 * SOS_SMS or LOCATION_SHARING.
Sarah Chindf715ec2023-02-13 13:46:24 -080013243 * @param callback The callback to handle incoming datagrams over satellite.
13244 *
13245 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13246 *
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013247 * @throws SecurityException if the caller doesn't have the required permission.
13248 */
13249 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013250 @SatelliteManager.SatelliteError public int registerForSatelliteDatagram(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013251 @SatelliteManager.DatagramType int datagramType,
13252 @NonNull ISatelliteStateListener callback) {
13253 enforceSatelliteCommunicationPermission("registerForSatelliteDatagram");
13254
13255 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chindf715ec2023-02-13 13:46:24 -080013256 Phone phone = getPhoneOrDefault(validSubId, "registerForSatelliteDatagram");
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013257 if (phone == null) {
13258 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13259 }
13260
13261 SatelliteDatagramListenerHandler satelliteDatagramListenerHandler =
13262 mSatelliteDatagramListenerHandlers.get(validSubId);
13263 if (satelliteDatagramListenerHandler == null) {
13264 satelliteDatagramListenerHandler = new SatelliteDatagramListenerHandler(
13265 Looper.getMainLooper(), validSubId);
13266 phone.registerForNewSatelliteDatagram(satelliteDatagramListenerHandler,
13267 SatelliteDatagramListenerHandler.EVENT_SATELLITE_DATAGRAMS_RECEIVED, null);
13268 }
13269
13270 satelliteDatagramListenerHandler.addListener(callback);
13271 mSatelliteDatagramListenerHandlers.put(validSubId, satelliteDatagramListenerHandler);
13272 return SatelliteManager.SATELLITE_ERROR_NONE;
13273 }
13274
13275 /**
13276 * Unregister to stop receiving incoming datagrams over satellite.
13277 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013278 * @param subId The subId of the subscription to unregister for incoming satellite datagrams.
13279 * @param callback The callback that was passed to
13280 * {@link #registerForSatelliteDatagram(int, int, ISatelliteStateListener)}.
13281 *
13282 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013283 *
13284 * @throws SecurityException if the caller doesn't have the required permission.
13285 */
13286 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013287 @SatelliteManager.SatelliteError public int unregisterForSatelliteDatagram(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013288 @NonNull ISatelliteStateListener callback) {
13289 enforceSatelliteCommunicationPermission("unregisterForSatelliteDatagram");
13290
13291 final int validSubId = getValidSatelliteSubId(subId);
13292 SatelliteDatagramListenerHandler satelliteDatagramListenerHandler =
13293 mSatelliteDatagramListenerHandlers.get(validSubId);
13294 if (satelliteDatagramListenerHandler != null) {
13295 if (satelliteDatagramListenerHandler.removeListener(callback)) {
13296 return SatelliteManager.SATELLITE_ERROR_NONE;
13297 }
13298 }
13299 return SatelliteManager.SATELLITE_INVALID_ARGUMENTS;
13300 }
13301
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013302 /**
13303 * Poll pending satellite datagrams over satellite.
Sarah Chindf715ec2023-02-13 13:46:24 -080013304 *
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013305 * This method requests modem to check if there are any pending datagrams to be received over
13306 * satellite. If there are any incoming datagrams, they will be received via
13307 * {@link SatelliteCallback.SatelliteDatagramListener#onSatelliteDatagrams(SatelliteDatagram[])}
Sarah Chindf715ec2023-02-13 13:46:24 -080013308 *
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013309 * @param subId The subId of the subscription used for receiving datagrams.
13310 * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request.
Sarah Chindf715ec2023-02-13 13:46:24 -080013311 *
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013312 * @throws SecurityException if the caller doesn't have required permission.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013313 */
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013314 @Override
13315 public void pollPendingSatelliteDatagrams(int subId, IIntegerConsumer callback) {
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013316 enforceSatelliteCommunicationPermission("pollPendingSatelliteDatagrams");
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013317 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013318
13319 final int validSubId = getValidSatelliteSubId(subId);
13320 if (!isSatelliteProvisioned(validSubId)) {
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013321 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
13322 return;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013323 }
13324
13325 Phone phone = getPhoneOrDefault(validSubId, "pollPendingSatelliteDatagrams");
13326 if (phone == null) {
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013327 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13328 return;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013329 }
13330
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013331 sendRequestAsync(CMD_POLL_PENDING_SATELLITE_DATAGRAMS, result, phone, null);
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013332 }
13333
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +000013334 /**
13335 * Send datagram over satellite.
Sarah Chindf715ec2023-02-13 13:46:24 -080013336 *
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013337 * Gateway encodes SOS SMS or location sharing message into a datagram and passes it as input to
13338 * this method. Datagram received here will be passed down to modem without any encoding or
13339 * encryption.
Sarah Chindf715ec2023-02-13 13:46:24 -080013340 *
Aishwarya Mallampati224317a2023-02-13 22:09:30 +000013341 * @param subId The subId of the subscription to send satellite datagrams for.
13342 * @param datagramType datagram type indicating whether the datagram is of type
13343 * SOS_SMS or LOCATION_SHARING.
13344 * @param datagram encoded gateway datagram which is encrypted by the caller.
13345 * Datagram will be passed down to modem without any encoding or encryption.
13346 * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request.
13347 *
13348 * @throws SecurityException if the caller doesn't have required permission.
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +000013349 */
13350 @Override
13351 public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
13352 SatelliteDatagram datagram, IIntegerConsumer callback) {
13353 enforceSatelliteCommunicationPermission("sendSatelliteDatagram");
13354 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
13355
13356 final int validSubId = getValidSatelliteSubId(subId);
13357 if (!isSatelliteProvisioned(validSubId)) {
13358 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
13359 return;
13360 }
13361
13362 Phone phone = getPhoneOrDefault(validSubId, "sendSatelliteDatagram");
13363 if (phone == null) {
13364 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13365 return;
13366 }
13367
13368 // check if we need to start PointingUI.
13369
13370 sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM,
13371 new SendSatelliteDatagramArgument(datagramType, datagram, result),
13372 phone, null);
13373 }
13374
Sarah Chindf715ec2023-02-13 13:46:24 -080013375 /**
13376 * Request to get whether satellite communication is allowed for the current location.
13377 *
13378 * @param subId The subId of the subscription to check whether satellite communication is
13379 * allowed for the current location for.
13380 * @param result The result receiver that returns whether satellite communication is allowed
13381 * for the current location if the request is successful or an error code
13382 * if the request failed.
13383 *
13384 * @throws SecurityException if the caller doesn't have the required permission.
13385 */
13386 @Override
13387 public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId,
13388 @NonNull ResultReceiver result) {
13389 enforceSatelliteCommunicationPermission(
13390 "requestIsSatelliteCommunicationAllowedForCurrentLocation");
13391 if (!isSatelliteSupported()) {
13392 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13393 return;
13394 }
13395
13396 final int validSubId = getValidSatelliteSubId(subId);
13397 if (!isSatelliteProvisioned(validSubId)) {
13398 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
13399 return;
13400 }
13401
13402 Phone phone = getPhoneOrDefault(validSubId,
13403 "requestIsSatelliteCommunicationAllowedForCurrentLocation");
13404 if (phone == null) {
13405 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
13406 return;
13407 }
13408
13409 sendRequest(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED, result, subId);
13410 }
13411
13412 /**
Sarah Chin5f57c582023-02-14 04:16:10 -080013413 * Request to get the time after which the satellite will be visible
Sarah Chindf715ec2023-02-13 13:46:24 -080013414 *
Sarah Chin5f57c582023-02-14 04:16:10 -080013415 * @param subId The subId to get the time after which the satellite will be visible for.
13416 * @param result The result receiver that returns the time after which the satellite will
Sarah Chindf715ec2023-02-13 13:46:24 -080013417 * be visible if the request is successful or an error code if the request failed.
13418 *
13419 * @throws SecurityException if the caller doesn't have the required permission.
13420 */
13421 @Override
13422 public void requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result) {
13423 enforceSatelliteCommunicationPermission("requestTimeForNextSatelliteVisibility");
13424 if (!isSatelliteSupported()) {
13425 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13426 return;
13427 }
13428
13429 final int validSubId = getValidSatelliteSubId(subId);
13430 if (!isSatelliteProvisioned(validSubId)) {
13431 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
13432 return;
13433 }
13434
13435 Phone phone = getPhoneOrDefault(validSubId, "requestTimeForNextSatelliteVisibility");
13436 if (phone == null) {
13437 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
13438 return;
13439 }
13440
13441 sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, phone, null);
13442 }
13443
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013444 private void handleCmdProvisionSatelliteService(@NonNull ProvisionSatelliteServiceArgument arg,
13445 @NonNull Phone phone, Message onCompleted) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013446 if (!mSatelliteProvisionCallbacks.containsKey(arg.subId)) {
13447 mSatelliteProvisionCallbacks.put(arg.subId, arg.callback);
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013448 phone.provisionSatelliteService(onCompleted, arg.token);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013449 } else {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013450 arg.callback.accept(SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013451 }
13452 }
13453
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013454 private void handleEventProvisionSatelliteServiceDone(
13455 @NonNull ProvisionSatelliteServiceArgument arg,
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013456 @SatelliteManager.SatelliteError int result) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013457 log("handleEventProvisionSatelliteServiceDone: result="
13458 + result + ", subId=" + arg.subId);
13459
13460 Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013461 if (callback == null) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013462 loge("handleEventProvisionSatelliteServiceDone: callback is null for subId="
13463 + arg.subId);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013464 return;
13465 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013466 callback.accept(result);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013467
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013468 if (result == SatelliteManager.SATELLITE_ERROR_NONE) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013469 setSatelliteProvisioned(arg.subId, true);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013470 }
13471
13472 /**
13473 * We need to update satellite provision status in SubscriptionController
13474 * or SatelliteController.
13475 * TODO (b/267826133) we need to do this for all subscriptions on the device.
13476 */
Sarah Chindf715ec2023-02-13 13:46:24 -080013477 registerForSatelliteProvisionStateChangedInternal(arg.subId, null);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013478 }
13479
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013480 private void handleCmdDeprovisionSatelliteService(
Sarah Chindf715ec2023-02-13 13:46:24 -080013481 @NonNull ProvisionSatelliteServiceArgument arg, @NonNull Phone phone,
13482 @NonNull Message onCompleted) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013483 if (arg == null) {
13484 loge("handleCmdDeprovisionSatelliteService: arg is null");
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013485 return;
13486 }
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013487 if (phone == null) {
13488 loge("handleCmdDeprovisionSatelliteService: phone is null");
13489 if (arg.callback != null) {
13490 arg.callback.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13491 }
13492 return;
13493 }
13494 phone.deprovisionSatelliteService(onCompleted, arg.token);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013495 }
13496
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013497 private void handleEventDeprovisionSatelliteServiceDone(
13498 @NonNull ProvisionSatelliteServiceArgument arg,
13499 @SatelliteManager.SatelliteError int result) {
13500 if (arg == null) {
13501 loge("handleEventDeprovisionSatelliteServiceDone: arg is null");
13502 return;
13503 }
13504 log("handleEventDeprovisionSatelliteServiceDone: result="
13505 + result + ", subId=" + arg.subId);
13506
13507 if (arg.callback != null) {
13508 arg.callback.accept(result);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013509 }
13510
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013511 if (result == SatelliteManager.SATELLITE_ERROR_NONE) {
13512 setSatelliteProvisioned(arg.subId, false);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013513 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013514 }
13515
13516 private Phone getPhoneOrDefault(int subId, String caller) {
13517 Phone phone = getPhone(subId);
13518 if (phone == null) {
13519 loge(caller + " called with invalid subId: " + subId
13520 + ". Retrying with default phone.");
13521 phone = getDefaultPhone();
13522 if (phone == null) {
13523 loge(caller + " failed with no phone object.");
13524 }
13525 }
13526 return phone;
13527 }
13528
13529 /**
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013530 * Check if satellite is provisioned for a subscription or the device.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013531 *
13532 * Note: this is the version without permission check for telephony internal use only. The
13533 * caller need to take care of the permission check.
13534 */
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013535 private boolean isSatelliteProvisioned(int subId) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013536 if (subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
13537 if (mSubscriptionController == null) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013538 loge("isSatelliteProvisioned mSubscriptionController is null");
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013539 return false;
13540 }
13541
13542 String strResult = mSubscriptionController.getSubscriptionProperty(
13543 subId, SubscriptionManager.SATELLITE_ENABLED);
13544 if (strResult != null) {
13545 int intResult = Integer.parseInt(strResult);
13546 return (intResult == 1) ? true : false;
13547 }
13548 } else {
13549 //TODO (b/267826133): check via SatelliteController
13550 }
13551 return false;
13552 }
13553
13554 /**
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013555 * Set satellite provisioned for a subscription or the device.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013556 *
13557 * The permission {@link android.Manifest.permission#MODIFY_PHONE_STATE} will be enforced by
13558 * {@link SubscriptionController} when setting satellite enabled for an active subscription.
13559 * Otherwise, {@link android.Manifest.permission#SATELLITE_COMMUNICATION} will be enforced.
13560 */
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013561 private synchronized void setSatelliteProvisioned(int subId, boolean isEnabled) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013562 if (subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
13563 if (mSubscriptionController == null) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013564 loge("setSatelliteProvisioned mSubscriptionController is null");
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013565 return;
13566 }
13567 mSubscriptionController.setSubscriptionProperty(
13568 subId, SubscriptionManager.SATELLITE_ENABLED, isEnabled ? "1" : "0");
13569 } else {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013570 //TODO (b/267826133): set via SatelliteController
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013571 }
13572 }
13573
13574 private int getValidSatelliteSubId(int subId) {
13575 if (mSubscriptionController == null) {
13576 loge("getValidSatelliteSubId mSubscriptionController is null. "
13577 + "Use DEFAULT_SUBSCRIPTION_ID for subId=" + subId);
13578 return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
13579 }
13580 final long identity = Binder.clearCallingIdentity();
13581 try {
13582 Context context = getDefaultPhone().getContext();
13583 if (mSubscriptionController.isActiveSubId(
13584 subId, context.getOpPackageName(), context.getAttributionTag())) {
13585 return subId;
13586 }
13587 } finally {
13588 Binder.restoreCallingIdentity(identity);
13589 }
13590 if (DBG) log("getValidSatelliteSubId: use DEFAULT_SUBSCRIPTION_ID for subId=" + subId);
13591 return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
13592 }
13593
13594 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013595 * If we have not successfully queried the satellite modem for its satellite service support,
13596 * we will retry the query one more time. Otherwise, we will return the queried result.
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013597 */
13598 private boolean isSatelliteSupported() {
13599 synchronized (mIsSatelliteSupportedLock) {
13600 if (mIsSatelliteSupported != null) {
13601 /* We have already successfully queried the satellite modem. */
13602 return mIsSatelliteSupported;
13603 }
13604 }
13605 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013606 * We have not successfully checked whether the modem supports satellite service.
13607 * Thus, we need to retry it now.
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013608 */
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013609 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
13610 mSatelliteSupportedReceiver);
13611 return false;
13612 }
13613
13614 /**
13615 * Get the {@link SatelliteManager.SatelliteError} from the provided result.
Sarah Chindf715ec2023-02-13 13:46:24 -080013616 *
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013617 * @param ar AsyncResult used to determine the error code.
13618 * @param caller The satellite request.
13619 * @param checkResult Whether to check if the result exists.
Sarah Chindf715ec2023-02-13 13:46:24 -080013620 *
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013621 * @return The {@link SatelliteManager.SatelliteError} error code from the request.
13622 */
13623 @SatelliteManager.SatelliteError private int getSatelliteError(@NonNull AsyncResult ar,
13624 @NonNull String caller, boolean checkResult) {
13625 int errorCode;
13626 if (ar.exception == null) {
13627 errorCode = SatelliteManager.SATELLITE_ERROR_NONE;
13628 if (checkResult && ar.result == null) {
13629 loge(caller + ": result is null");
13630 errorCode = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13631 }
13632 } else {
13633 errorCode = SatelliteManager.SATELLITE_ERROR;
13634 if (ar.exception instanceof CommandException) {
13635 CommandException.Error error =
13636 ((CommandException) (ar.exception)).getCommandError();
13637 errorCode = RILUtils.convertToSatelliteError(error);
13638 loge(caller + " CommandException: " + ar.exception);
13639 } else {
13640 loge(caller + " unknown exception: " + ar.exception);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013641 }
13642 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013643 log(caller + " error: " + errorCode);
13644 return errorCode;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013645 }
13646
13647 /**
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013648 * Register for the satellite provision state change.
13649 *
13650 * @param subId The subId of the subscription associated with the satellite service.
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013651 * @param callback The callback to handle the satellite provision state changed event.
Sarah Chindf715ec2023-02-13 13:46:24 -080013652 *
13653 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013654 */
Sarah Chindf715ec2023-02-13 13:46:24 -080013655 @SatelliteManager.SatelliteError private int registerForSatelliteProvisionStateChangedInternal(
13656 int subId, @Nullable ISatelliteStateListener callback) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013657 if (!isSatelliteSupported()) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013658 return SatelliteManager.SATELLITE_NOT_SUPPORTED;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013659 }
13660
13661 final int validSubId = getValidSatelliteSubId(subId);
13662 Phone phone = getPhoneOrDefault(validSubId, "registerForSatelliteProvisionStateChanged");
13663 if (phone == null) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013664 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013665 }
13666
13667 SatelliteProvisionStateChangedHandler satelliteProvisionStateChangedHandler =
13668 mSatelliteProvisionStateChangedHandlers.get(validSubId);
13669 if (satelliteProvisionStateChangedHandler == null) {
13670 satelliteProvisionStateChangedHandler = new SatelliteProvisionStateChangedHandler(
13671 Looper.getMainLooper(), validSubId);
13672 phone.registerForSatelliteProvisionStateChanged(satelliteProvisionStateChangedHandler,
13673 SatelliteProvisionStateChangedHandler.EVENT_PROVISION_STATE_CHANGED, null);
13674 }
13675
13676 if (callback != null) {
13677 satelliteProvisionStateChangedHandler.addListener(callback);
13678 }
13679 mSatelliteProvisionStateChangedHandlers.put(
13680 validSubId, satelliteProvisionStateChangedHandler);
Sarah Chindf715ec2023-02-13 13:46:24 -080013681 return SatelliteManager.SATELLITE_ERROR_NONE;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013682 }
13683
13684 /**
arunvoddud5c6ce02022-12-11 06:03:12 +000013685 * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
13686 *
13687 * <p>This method behaves in one of the following ways:
13688 * <ul>
13689 * <li>return true : if the calling package has the appop permission {@link
13690 * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} in the manifest </>
13691 * <li>return true : if any one subscription has the READ_PRIVILEGED_PHONE_STATE
13692 * permission, the calling package passes a DevicePolicyManager Device Owner / Profile
13693 * Owner device identifier access check, or the calling package has carrier privileges</>
13694 * <li>throw SecurityException: if the caller does not meet any of the requirements.
13695 * </ul>
13696 */
13697 private static boolean checkCallingOrSelfReadDeviceIdentifiersForAnySub(Context context,
13698 String callingPackage, @Nullable String callingFeatureId, String message) {
13699 for (Phone phone : PhoneFactory.getPhones()) {
13700 if (TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(context,
13701 phone.getSubId(), callingPackage, callingFeatureId, message)) {
13702 return true;
13703 }
13704 }
13705 return false;
13706 }
arunvoddud7401012022-12-15 16:08:12 +000013707
13708 /**
Jack Yufa8ed012023-02-11 15:42:28 -080013709 * @return The subscription manager service instance.
13710 */
13711 public SubscriptionManagerService getSubscriptionManagerService() {
13712 return SubscriptionManagerService.getInstance();
13713 }
13714
13715 /**
arunvoddud7401012022-12-15 16:08:12 +000013716 * Class binds the consumer[callback] and carrierId.
13717 */
13718 private static class CallerCallbackInfo {
13719 private final Consumer<Integer> mConsumer;
13720 private final int mCarrierId;
13721
13722 public CallerCallbackInfo(Consumer<Integer> consumer, int carrierId) {
13723 mConsumer = consumer;
13724 mCarrierId = carrierId;
13725 }
13726
13727 public Consumer<Integer> getConsumer() {
13728 return mConsumer;
13729 }
13730
13731 public int getCarrierId() {
13732 return mCarrierId;
13733 }
13734 }
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013735
13736 private static SatelliteDatagram[] convertToSatelliteDatagramArray(byte[][] datagrams) {
13737 // Convert 2D byte array into SatelliteDatagramArray.
13738 SatelliteDatagram[] satelliteDatagramArray =
13739 new SatelliteDatagram[datagrams.length];
13740 for (int i = 0; i < datagrams.length; i++) {
13741 satelliteDatagramArray[i] = new SatelliteDatagram(datagrams[i]);
13742 }
13743 return satelliteDatagramArray;
13744 }
Jack Yufa8ed012023-02-11 15:42:28 -080013745}