blob: 901c8b2f14507ddd71c49c92061e394a3fa0de38 [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;
Sarah Chin503828c2023-02-01 23:54:20 -0800150import android.telephony.satellite.SatelliteCapabilities;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000151import android.telephony.satellite.SatelliteDatagram;
Sarah Chineccfbd12023-01-20 19:00:35 -0800152import android.telephony.satellite.SatelliteManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700153import android.text.TextUtils;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800154import android.util.ArraySet;
Hall Liud60acc92020-05-21 17:09:35 -0700155import android.util.EventLog;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700156import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -0800157import android.util.Pair;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800158
Andrew Lee312e8172014-10-23 17:01:36 -0700159import com.android.ims.ImsManager;
Brad Ebinger34bef922017-11-09 10:27:08 -0800160import com.android.ims.internal.IImsServiceFeatureCallback;
James.cf Linbcdf8b32021-01-14 16:44:13 +0800161import com.android.ims.rcs.uce.eab.EabUtil;
SongFerngWangfd89b102021-05-27 22:44:54 +0800162import com.android.internal.annotations.VisibleForTesting;
Shuo Qian4a594052020-01-23 11:59:30 -0800163import com.android.internal.telephony.CallForwardInfo;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700164import com.android.internal.telephony.CallManager;
Tyler Gunn52dcf772017-04-26 11:30:31 -0700165import com.android.internal.telephony.CallStateException;
Tyler Gunnd4339262021-05-03 14:46:49 -0700166import com.android.internal.telephony.CallTracker;
Rambo Wang9c9ffdd2022-01-13 21:51:44 -0800167import com.android.internal.telephony.CarrierPrivilegesTracker;
chen xu651eec72018-11-11 19:03:44 -0800168import com.android.internal.telephony.CarrierResolver;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700169import com.android.internal.telephony.CellNetworkScanResult;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700170import com.android.internal.telephony.CommandException;
Shuo Qian4a594052020-01-23 11:59:30 -0800171import com.android.internal.telephony.CommandsInterface;
Hui Wang641e81c2020-10-12 12:14:23 -0700172import com.android.internal.telephony.GbaManager;
Shuo Qianccbaf742021-02-22 18:32:21 -0800173import com.android.internal.telephony.GsmCdmaPhone;
Nathan Harold48d6fd52019-02-06 19:01:40 -0800174import com.android.internal.telephony.HalVersion;
Hall Liu73f5d362020-01-20 13:42:00 -0800175import com.android.internal.telephony.IBooleanConsumer;
Hall Liu27d24262020-09-18 19:04:59 -0700176import com.android.internal.telephony.ICallForwardingInfoCallback;
Hunsuk Choi3b742d62021-10-25 19:48:34 +0000177import com.android.internal.telephony.IImsStateCallback;
Brad Ebingera63db5f2019-04-23 16:31:13 -0700178import com.android.internal.telephony.IIntegerConsumer;
Hall Liud892bec2018-11-30 14:51:45 -0800179import com.android.internal.telephony.INumberVerificationCallback;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700180import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -0800181import com.android.internal.telephony.IccCard;
Jack Yuf5badd92022-12-08 00:50:53 -0800182import com.android.internal.telephony.IccCardConstants;
Rambo Wanga1782702021-11-10 20:15:19 -0800183import com.android.internal.telephony.IccLogicalChannelRequest;
Jack Yu5f7092c2018-04-13 14:05:37 -0700184import com.android.internal.telephony.LocaleTracker;
yinxub1bed742017-04-17 11:45:04 -0700185import com.android.internal.telephony.NetworkScanRequestTracker;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700186import com.android.internal.telephony.OperatorInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700187import com.android.internal.telephony.Phone;
Malcolm Chen2c63d402018-08-14 16:00:53 -0700188import com.android.internal.telephony.PhoneConfigurationManager;
Nathan Harolda667c152016-12-14 11:27:20 -0800189import com.android.internal.telephony.PhoneConstantConversions;
Ta-wei Yen87c49842016-05-13 21:19:52 -0700190import com.android.internal.telephony.PhoneConstants;
Wink Saville36469e72014-06-11 15:17:00 -0700191import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -0700192import com.android.internal.telephony.ProxyController;
Sanket Padawe99ef1e32016-05-18 16:12:33 -0700193import com.android.internal.telephony.RIL;
SongFerngWang8c6e82e2021-03-02 22:09:29 +0800194import com.android.internal.telephony.RILConstants;
Sarah Chineccfbd12023-01-20 19:00:35 -0800195import com.android.internal.telephony.RILUtils;
Daniel Bright94f43662021-03-01 14:43:40 -0800196import com.android.internal.telephony.RadioInterfaceCapabilityController;
Jack Yu5f7092c2018-04-13 14:05:37 -0700197import com.android.internal.telephony.ServiceStateTracker;
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +0000198import com.android.internal.telephony.SmsApplication;
Amit Mahajandccb3f12019-05-13 13:48:32 -0700199import com.android.internal.telephony.SmsController;
Brad Ebingera63db5f2019-04-23 16:31:13 -0700200import com.android.internal.telephony.SmsPermissions;
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800201import com.android.internal.telephony.SubscriptionController;
Peter Wang59571be2020-01-27 12:35:15 +0800202import com.android.internal.telephony.TelephonyIntents;
Jeff Davidson7e17e312018-02-13 18:17:36 -0800203import com.android.internal.telephony.TelephonyPermissions;
Jack Yu27422a52022-03-21 10:38:05 -0700204import com.android.internal.telephony.data.DataUtils;
Hunsuk Choi42cc62a2022-10-16 06:03:40 +0000205import com.android.internal.telephony.domainselection.DomainSelectionResolver;
sqianf4ca7ed2019-01-15 18:32:07 -0800206import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Derek Tan740e1672017-06-27 14:56:27 -0700207import com.android.internal.telephony.euicc.EuiccConnector;
Brad Ebinger9c0eb502019-01-23 15:06:19 -0800208import com.android.internal.telephony.ims.ImsResolver;
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700209import com.android.internal.telephony.imsphone.ImsPhone;
210import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
joonhunshin3e154242021-09-17 06:33:39 +0000211import com.android.internal.telephony.metrics.RcsStats;
Pengquan Meng6c2dc9f2019-02-06 11:12:53 -0800212import com.android.internal.telephony.metrics.TelephonyMetrics;
Jack Yu285100e2022-12-02 22:48:35 -0800213import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
214import com.android.internal.telephony.subscription.SubscriptionManagerService;
Meng Wangafbc5852019-09-19 17:37:13 -0700215import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700216import com.android.internal.telephony.uicc.IccIoResult;
217import com.android.internal.telephony.uicc.IccUtils;
Nathan Haroldb3014052017-01-25 15:57:32 -0800218import com.android.internal.telephony.uicc.SIMRecords;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700219import com.android.internal.telephony.uicc.UiccCard;
Nathan Haroldb3014052017-01-25 15:57:32 -0800220import com.android.internal.telephony.uicc.UiccCardApplication;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700221import com.android.internal.telephony.uicc.UiccController;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000222import com.android.internal.telephony.uicc.UiccPort;
Jeff Davidson7e17e312018-02-13 18:17:36 -0800223import com.android.internal.telephony.uicc.UiccProfile;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000224import com.android.internal.telephony.uicc.UiccSlot;
zoey chenc730df82019-12-18 17:07:20 +0800225import com.android.internal.telephony.util.LocaleUtils;
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +0000226import com.android.internal.telephony.util.TelephonyUtils;
fionaxu7ed723d2017-05-30 18:58:54 -0700227import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
Hall Liu27d24262020-09-18 19:04:59 -0700228import com.android.internal.util.FunctionalUtils;
Jake Hambye994d462014-02-03 13:10:13 -0800229import com.android.internal.util.HexDump;
Hall Liuaa4211e2021-01-20 15:43:39 -0800230import com.android.phone.callcomposer.CallComposerPictureManager;
231import com.android.phone.callcomposer.CallComposerPictureTransfer;
232import com.android.phone.callcomposer.ImageData;
Brad Ebingera63db5f2019-04-23 16:31:13 -0700233import com.android.phone.settings.PickSmsSubscriptionActivity;
Sarah Chin46355ba2022-11-01 23:51:16 -0700234import com.android.phone.slice.SlicePurchaseController;
arunvoddud7401012022-12-15 16:08:12 +0000235import com.android.phone.utils.CarrierAllowListInfo;
Ta-wei Yenc9df0432017-04-17 17:09:07 -0700236import com.android.phone.vvm.PhoneAccountHandleConverter;
Ta-wei Yen527a9c02017-01-06 15:29:25 -0800237import com.android.phone.vvm.RemoteVvmTaskManager;
Ta-wei Yenc9df0432017-04-17 17:09:07 -0700238import com.android.phone.vvm.VisualVoicemailSettingsUtil;
Ta-wei Yenc8905312017-03-28 11:14:45 -0700239import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800240import com.android.services.telephony.TelecomAccountRegistry;
241import com.android.services.telephony.TelephonyConnectionService;
Peter Wang44b186e2020-01-13 23:33:09 -0800242import com.android.telephony.Rlog;
Ta-wei Yen30a69c82016-12-27 14:52:32 -0800243
Hall Liu82694d52020-12-11 18:22:04 -0800244import java.io.ByteArrayOutputStream;
Ta-wei Yenc236d6b2016-06-21 13:33:12 -0700245import java.io.FileDescriptor;
Hall Liu82694d52020-12-11 18:22:04 -0800246import java.io.IOException;
247import java.io.InputStream;
Ta-wei Yenc236d6b2016-06-21 13:33:12 -0700248import java.io.PrintWriter;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700249import java.util.ArrayList;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800250import java.util.Arrays;
Muralidhar Reddyeb809e32021-11-19 03:07:54 +0000251import java.util.Collection;
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -0800252import java.util.Collections;
sqian11b7a0e2018-12-05 18:48:28 -0800253import java.util.HashMap;
sqianf4ca7ed2019-01-15 18:32:07 -0800254import java.util.HashSet;
Jake Hambye994d462014-02-03 13:10:13 -0800255import java.util.List;
Narayan Kamath1c496c22015-04-16 14:40:19 +0100256import java.util.Locale;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800257import java.util.Map;
Nazanin Bakhshif71371d2019-04-29 17:29:44 -0700258import java.util.NoSuchElementException;
Hall Liu82694d52020-12-11 18:22:04 -0800259import java.util.Objects;
sqianf4ca7ed2019-01-15 18:32:07 -0800260import java.util.Set;
Sarah Chin2ec39f62022-08-31 17:03:26 -0700261import java.util.UUID;
Sarah Chineccfbd12023-01-20 19:00:35 -0800262import java.util.concurrent.ConcurrentHashMap;
Hall Liu82694d52020-12-11 18:22:04 -0800263import java.util.concurrent.Executors;
Peter Wangdafb9ac2020-01-15 14:13:38 -0800264import java.util.concurrent.atomic.AtomicBoolean;
Hall Liu73f5d362020-01-20 13:42:00 -0800265import java.util.function.Consumer;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700266
267/**
268 * Implementation of the ITelephony interface.
269 */
Santos Cordon117fee72014-05-16 17:56:12 -0700270public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700271 private static final String LOG_TAG = "PhoneInterfaceManager";
272 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
273 private static final boolean DBG_LOC = false;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800274 private static final boolean DBG_MERGE = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700275
276 // Message codes used with mMainThreadHandler
277 private static final int CMD_HANDLE_PIN_MMI = 1;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700278 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
279 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700280 private static final int CMD_OPEN_CHANNEL = 9;
281 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
282 private static final int CMD_CLOSE_CHANNEL = 11;
283 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800284 private static final int CMD_NV_READ_ITEM = 13;
285 private static final int EVENT_NV_READ_ITEM_DONE = 14;
286 private static final int CMD_NV_WRITE_ITEM = 15;
287 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
288 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
289 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
chen xu6dac5ab2018-10-26 17:39:23 -0700290 private static final int CMD_RESET_MODEM_CONFIG = 19;
291 private static final int EVENT_RESET_MODEM_CONFIG_DONE = 20;
SongFerngWang3ef3e072020-12-21 16:41:52 +0800292 private static final int CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK = 21;
293 private static final int EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE = 22;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800294 private static final int CMD_SEND_ENVELOPE = 25;
295 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Shuo Qian850e4d6a2018-04-25 21:02:08 +0000296 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
297 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
Derek Tan6b088ee2014-09-05 14:15:18 -0700298 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
299 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
300 private static final int CMD_EXCHANGE_SIM_IO = 31;
301 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800302 private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
303 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
Stuart Scott54788802015-03-30 13:18:01 -0700304 private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
305 private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700306 private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
307 private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700308 private static final int CMD_PERFORM_NETWORK_SCAN = 39;
309 private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
310 private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
311 private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
Meng Wang1a7c35a2016-05-05 20:56:15 -0700312 private static final int CMD_SET_ALLOWED_CARRIERS = 43;
313 private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
314 private static final int CMD_GET_ALLOWED_CARRIERS = 45;
315 private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
pkanwar32d516d2016-10-14 19:37:38 -0700316 private static final int CMD_HANDLE_USSD_REQUEST = 47;
Nathan Haroldb3014052017-01-25 15:57:32 -0800317 private static final int CMD_GET_FORBIDDEN_PLMNS = 48;
318 private static final int EVENT_GET_FORBIDDEN_PLMNS_DONE = 49;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +0000319 private static final int CMD_SWITCH_SLOTS = 50;
320 private static final int EVENT_SWITCH_SLOTS_DONE = 51;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700321 private static final int CMD_GET_NETWORK_SELECTION_MODE = 52;
322 private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 53;
323 private static final int CMD_GET_CDMA_ROAMING_MODE = 54;
324 private static final int EVENT_GET_CDMA_ROAMING_MODE_DONE = 55;
325 private static final int CMD_SET_CDMA_ROAMING_MODE = 56;
326 private static final int EVENT_SET_CDMA_ROAMING_MODE_DONE = 57;
327 private static final int CMD_SET_CDMA_SUBSCRIPTION_MODE = 58;
328 private static final int EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE = 59;
Nathan Harold3ff88932018-08-14 10:19:49 -0700329 private static final int CMD_GET_ALL_CELL_INFO = 60;
330 private static final int EVENT_GET_ALL_CELL_INFO_DONE = 61;
331 private static final int CMD_GET_CELL_LOCATION = 62;
332 private static final int EVENT_GET_CELL_LOCATION_DONE = 63;
chen xu6dac5ab2018-10-26 17:39:23 -0700333 private static final int CMD_MODEM_REBOOT = 64;
334 private static final int EVENT_CMD_MODEM_REBOOT_DONE = 65;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -0700335 private static final int CMD_REQUEST_CELL_INFO_UPDATE = 66;
336 private static final int EVENT_REQUEST_CELL_INFO_UPDATE_DONE = 67;
Malcolm Chen8e4ed912019-01-15 20:22:16 -0800337 private static final int CMD_REQUEST_ENABLE_MODEM = 68;
338 private static final int EVENT_ENABLE_MODEM_DONE = 69;
Nazanin Bakhshif71371d2019-04-29 17:29:44 -0700339 private static final int CMD_GET_MODEM_STATUS = 70;
340 private static final int EVENT_GET_MODEM_STATUS_DONE = 71;
yincheng zhao2737e882019-09-06 17:06:54 -0700341 private static final int CMD_SET_FORBIDDEN_PLMNS = 72;
342 private static final int EVENT_SET_FORBIDDEN_PLMNS_DONE = 73;
Naina Nallurid63128d2019-09-17 14:10:30 -0700343 private static final int CMD_ERASE_MODEM_CONFIG = 74;
344 private static final int EVENT_ERASE_MODEM_CONFIG_DONE = 75;
zoey chene02881a2019-12-30 16:11:23 +0800345 private static final int CMD_CHANGE_ICC_LOCK_PASSWORD = 76;
346 private static final int EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE = 77;
347 private static final int CMD_SET_ICC_LOCK_ENABLED = 78;
348 private static final int EVENT_SET_ICC_LOCK_ENABLED_DONE = 79;
Hall Liu73f5d362020-01-20 13:42:00 -0800349 private static final int CMD_SET_SYSTEM_SELECTION_CHANNELS = 80;
350 private static final int EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE = 81;
Peter Wangdafb9ac2020-01-15 14:13:38 -0800351 private static final int MSG_NOTIFY_USER_ACTIVITY = 82;
Shuo Qian4a594052020-01-23 11:59:30 -0800352 private static final int CMD_GET_CALL_FORWARDING = 83;
353 private static final int EVENT_GET_CALL_FORWARDING_DONE = 84;
354 private static final int CMD_SET_CALL_FORWARDING = 85;
355 private static final int EVENT_SET_CALL_FORWARDING_DONE = 86;
356 private static final int CMD_GET_CALL_WAITING = 87;
357 private static final int EVENT_GET_CALL_WAITING_DONE = 88;
358 private static final int CMD_SET_CALL_WAITING = 89;
359 private static final int EVENT_SET_CALL_WAITING_DONE = 90;
Sooraj Sasindran37444802020-08-11 10:40:43 -0700360 private static final int CMD_ENABLE_NR_DUAL_CONNECTIVITY = 91;
361 private static final int EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE = 92;
362 private static final int CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED = 93;
363 private static final int EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE = 94;
Sarah Chinbaab1432020-10-28 13:46:24 -0700364 private static final int CMD_GET_CDMA_SUBSCRIPTION_MODE = 95;
365 private static final int EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE = 96;
Sarah Chin679c08a2020-11-18 13:39:35 -0800366 private static final int CMD_GET_SYSTEM_SELECTION_CHANNELS = 97;
367 private static final int EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE = 98;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800368 private static final int CMD_SET_DATA_THROTTLING = 99;
369 private static final int EVENT_SET_DATA_THROTTLING_DONE = 100;
Jordan Liu109698e2020-11-24 14:50:34 -0800370 private static final int CMD_SET_SIM_POWER = 101;
371 private static final int EVENT_SET_SIM_POWER_DONE = 102;
Rambo Wanga5cc9b72021-01-07 10:51:54 -0800372 private static final int CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST = 103;
373 private static final int EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE = 104;
374 private static final int CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST = 105;
375 private static final int EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE = 106;
SongFerngWang3ef3e072020-12-21 16:41:52 +0800376 private static final int CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON = 107;
377 private static final int EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE = 108;
Michele Berionne5e411512020-11-13 02:36:59 +0000378 private static final int CMD_PREPARE_UNATTENDED_REBOOT = 109;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +0800379 private static final int CMD_GET_SLICING_CONFIG = 110;
380 private static final int EVENT_GET_SLICING_CONFIG_DONE = 111;
Kai Shif70f46f2021-03-03 13:59:46 -0800381 private static final int CMD_ERASE_DATA_SHARED_PREFERENCES = 112;
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -0700382 private static final int CMD_ENABLE_VONR = 113;
383 private static final int EVENT_ENABLE_VONR_DONE = 114;
384 private static final int CMD_IS_VONR_ENABLED = 115;
385 private static final int EVENT_IS_VONR_ENABLED_DONE = 116;
Sarah Chin2ec39f62022-08-31 17:03:26 -0700386 private static final int CMD_PURCHASE_PREMIUM_CAPABILITY = 117;
387 private static final int EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE = 118;
Sarah Chineccfbd12023-01-20 19:00:35 -0800388 private static final int CMD_START_SATELLITE_POSITION_UPDATES = 119;
389 private static final int EVENT_START_SATELLITE_POSITION_UPDATES_DONE = 120;
390 private static final int CMD_STOP_SATELLITE_POSITION_UPDATES = 121;
391 private static final int EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE = 122;
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +0000392 private static final int CMD_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG = 123;
393 private static final int EVENT_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG_DONE = 124;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800394 private static final int CMD_PROVISION_SATELLITE_SERVICE = 125;
395 private static final int EVENT_PROVISION_SATELLITE_SERVICE_DONE = 126;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -0800396 private static final int CMD_DEPROVISION_SATELLITE_SERVICE = 127;
397 private static final int EVENT_DEPROVISION_SATELLITE_SERVICE_DONE = 128;
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800398 private static final int CMD_SET_SATELLITE_ENABLED = 129;
399 private static final int EVENT_SET_SATELLITE_ENABLED_DONE = 130;
400 private static final int CMD_IS_SATELLITE_ENABLED = 131;
401 private static final int EVENT_IS_SATELLITE_ENABLED_DONE = 132;
402 private static final int CMD_IS_SATELLITE_SUPPORTED = 133;
403 private static final int EVENT_IS_SATELLITE_SUPPORTED_DONE = 134;
404 private static final int CMD_GET_SATELLITE_CAPABILITIES = 135;
405 private static final int EVENT_GET_SATELLITE_CAPABILITIES_DONE = 136;
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000406 private static final int CMD_POLL_PENDING_SATELLITE_DATAGRAMS = 137;
407 private static final int EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE = 138;
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +0000408 private static final int CMD_SEND_SATELLITE_DATAGRAM = 139;
409 private static final int EVENT_SEND_SATELLITE_DATAGRAM_DONE = 140;
Sarah Chindf715ec2023-02-13 13:46:24 -0800410 private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 141;
411 private static final int EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE = 142;
412 private static final int CMD_GET_TIME_SATELLITE_NEXT_VISIBLE = 143;
413 private static final int EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE = 144;
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -0800414 // Parameters of select command.
415 private static final int SELECT_COMMAND = 0xA4;
416 private static final int SELECT_P1 = 0x04;
417 private static final int SELECT_P2 = 0;
418 private static final int SELECT_P3 = 0x10;
419
Gil Cukierman1c0eb932022-12-06 22:28:24 +0000420 // Toggling null cipher and integrity support was added in IRadioNetwork 2.1
421 private static final int MIN_NULL_CIPHER_AND_INTEGRITY_VERSION = 201;
422
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700423 /** The singleton instance. */
424 private static PhoneInterfaceManager sInstance;
Jack Nudelman644b91a2021-03-12 14:09:48 -0800425 private static List<String> sThermalMitigationAllowlistedPackages = new ArrayList<>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700426
Wink Saville3ab207e2014-11-20 13:07:20 -0800427 private PhoneGlobals mApp;
Wink Saville3ab207e2014-11-20 13:07:20 -0800428 private CallManager mCM;
Brad Ebinger24c29992019-12-05 13:03:21 -0800429 private ImsResolver mImsResolver;
Stuart Scott981d8582015-04-21 14:09:50 -0700430 private UserManager mUserManager;
Wink Saville3ab207e2014-11-20 13:07:20 -0800431 private AppOpsManager mAppOps;
Grace Jia0ddb3612021-04-22 13:35:26 -0700432 private PackageManager mPm;
Wink Saville3ab207e2014-11-20 13:07:20 -0800433 private MainThreadHandler mMainThreadHandler;
Jack Yue37dd262022-12-16 11:53:37 -0800434 private final SubscriptionController mSubscriptionController;
Wink Saville3ab207e2014-11-20 13:07:20 -0800435 private SharedPreferences mTelephonySharedPreferences;
Malcolm Chen2c63d402018-08-14 16:00:53 -0700436 private PhoneConfigurationManager mPhoneConfigurationManager;
Daniel Bright94f43662021-03-01 14:43:40 -0800437 private final RadioInterfaceCapabilityController mRadioInterfaceCapabilities;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700438
Peter Wangdafb9ac2020-01-15 14:13:38 -0800439 /** User Activity */
440 private AtomicBoolean mNotifyUserActivity;
Peter Wangdafb9ac2020-01-15 14:13:38 -0800441 private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
442
Jeff Davidson8ab02b22020-03-28 12:24:40 -0700443 private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800444
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800445 /**
446 * Map key: subId, value: callback to get error code of the provision request.
447 */
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800448 private final ConcurrentHashMap<Integer, Consumer<Integer>> mSatelliteProvisionCallbacks =
Sarah Chineccfbd12023-01-20 19:00:35 -0800449 new ConcurrentHashMap<>();
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800450 /**
451 * Map key: subId, value: SatellitePositionUpdateHandler to notify registrants.
452 */
453 private final ConcurrentHashMap<IBinder, SatellitePositionUpdateHandler>
454 mSatellitePositionUpdateHandlers = new ConcurrentHashMap<>();
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800455 /**
456 * Map key: subId, value: SatelliteProvisionStateChangedHandler to notify registrants.
457 */
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800458 private final ConcurrentHashMap<Integer, SatelliteProvisionStateChangedHandler>
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800459 mSatelliteProvisionStateChangedHandlers = new ConcurrentHashMap<>();
460
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800461 private Boolean mIsSatelliteSupported = null;
462 private final Object mIsSatelliteSupportedLock = new Object();
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800463 private final ResultReceiver mSatelliteSupportedReceiver;
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800464
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000465 /**
466 * Map key: subId, value: SatelliteStateChangeHandler to notify registrants.
467 */
468 private ConcurrentHashMap<Integer, SatelliteStateListenerHandler>
469 mSatelliteStateListenerHandlers = new ConcurrentHashMap<>();
470
471 /**
472 * Map key: subId, value: SatelliteDatagramListenerHandler to notify registrants.
473 */
474 private ConcurrentHashMap<Integer, SatelliteDatagramListenerHandler>
475 mSatelliteDatagramListenerHandlers = new ConcurrentHashMap<>();
476
Derek Tan97ebb422014-09-05 16:55:38 -0700477 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
478 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
Jeff Sharkey85190e62014-12-05 09:40:12 -0800479 private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
Brad Ebinger1c8542e2019-01-14 13:43:14 -0800480 private static final String PREF_PROVISION_IMS_MMTEL_PREFIX = "provision_ims_mmtel_";
Derek Tan89e89d42014-07-08 17:00:10 -0700481
Michelecea4cf22018-12-21 15:00:11 -0800482 // String to store multi SIM allowed
483 private static final String PREF_MULTI_SIM_RESTRICTED = "multisim_restricted";
484
Derek Tan740e1672017-06-27 14:56:27 -0700485 // The AID of ISD-R.
486 private static final String ISDR_AID = "A0000005591010FFFFFFFF8900000100";
487
yinxub1bed742017-04-17 11:45:04 -0700488 private NetworkScanRequestTracker mNetworkScanRequestTracker;
489
David Kelly5e06a7f2018-03-12 14:10:59 +0000490 private static final int TYPE_ALLOCATION_CODE_LENGTH = 8;
491 private static final int MANUFACTURER_CODE_LENGTH = 8;
492
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800493 private static final int SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS = -1;
Jack Nudelman5d6a98b2021-03-04 14:26:25 -0800494 private static final int MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE = -2;
Jack Nudelmanb0b87642020-11-12 15:04:39 -0800495
Sarah Chin2ec39f62022-08-31 17:03:26 -0700496 private static final String PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID =
497 "24bf97a6-e8a6-44d8-a6a4-255d7548733c";
498
Derek Tan89e89d42014-07-08 17:00:10 -0700499 /**
Naina Nallurid63128d2019-09-17 14:10:30 -0700500 * Experiment flag to enable erase modem config on reset network, default value is false
501 */
502 public static final String RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED =
503 "reset_network_erase_modem_config_enabled";
504
Rambo Wang0f050d82021-02-12 11:43:36 -0800505 private static final int SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS = 2000; // 2 seconds
Chen Xu540470b2021-12-14 17:15:47 -0800506
Gary Jian76280a42022-12-07 16:18:33 +0800507 private static final int MODEM_ACTIVITY_TIME_OFFSET_CORRECTION_MS = 50;
508
sandeepjsb6c87872021-09-27 15:34:44 +0000509 /**
510 * With support for MEP(multiple enabled profile) in Android T, a SIM card can have more than
511 * one ICCID active at the same time.
512 * Apps should use below API signatures if targeting SDK is T and beyond.
513 *
514 * @hide
515 */
516 @ChangeId
517 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
518 public static final long GET_API_SIGNATURES_FROM_UICC_PORT_INFO = 202110963L;
Rambo Wang0f050d82021-02-12 11:43:36 -0800519
Naina Nallurid63128d2019-09-17 14:10:30 -0700520 /**
Chen Xu540470b2021-12-14 17:15:47 -0800521 * Apps targeting on Android T and beyond will get exception whenever icc close channel
522 * operation fails.
523 */
524 @ChangeId
525 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
526 public static final long ICC_CLOSE_CHANNEL_EXCEPTION_ON_FAILURE = 208739934L;
527
528 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700529 * A request object to use for transmitting data to an ICC.
530 */
531 private static final class IccAPDUArgument {
532 public int channel, cla, command, p1, p2, p3;
533 public String data;
534
535 public IccAPDUArgument(int channel, int cla, int command,
536 int p1, int p2, int p3, String data) {
537 this.channel = channel;
538 this.cla = cla;
539 this.command = command;
540 this.p1 = p1;
541 this.p2 = p2;
542 this.p3 = p3;
543 this.data = data;
544 }
545 }
546
547 /**
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700548 * A request object to use for transmitting data to an ICC.
549 */
550 private static final class ManualNetworkSelectionArgument {
551 public OperatorInfo operatorInfo;
552 public boolean persistSelection;
553
554 public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
555 this.operatorInfo = operatorInfo;
556 this.persistSelection = persistSelection;
557 }
558 }
559
Sarah Chin71b3a852022-09-28 15:54:19 -0700560 private static final class PurchasePremiumCapabilityArgument {
561 public @TelephonyManager.PremiumCapability int capability;
Sarah Chin71b3a852022-09-28 15:54:19 -0700562 public @NonNull IIntegerConsumer callback;
563
564 PurchasePremiumCapabilityArgument(@TelephonyManager.PremiumCapability int capability,
Sarah Chinb8218c22023-01-04 13:35:29 -0800565 @NonNull IIntegerConsumer callback) {
Sarah Chin71b3a852022-09-28 15:54:19 -0700566 this.capability = capability;
Sarah Chin71b3a852022-09-28 15:54:19 -0700567 this.callback = callback;
568 }
569 }
570
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800571 private static final class ProvisionSatelliteServiceArgument {
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800572 public @NonNull String token;
573 public @NonNull Consumer<Integer> callback;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800574 public int subId;
575
Sarah Chin4a9e8b82023-02-10 21:10:57 -0800576 ProvisionSatelliteServiceArgument(String token, Consumer<Integer> callback, int subId) {
577 this.token = token;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800578 this.callback = callback;
579 this.subId = subId;
580 }
581 }
582
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +0000583 private static final class SendSatelliteDatagramArgument {
584 public @SatelliteManager.DatagramType int datagramType;
585 public @NonNull SatelliteDatagram datagram;
586 public @NonNull Consumer<Integer> callback;
587
588 SendSatelliteDatagramArgument(@SatelliteManager.DatagramType int datagramType,
589 SatelliteDatagram datagram, Consumer<Integer> callback) {
590 this.datagramType = datagramType;
591 this.datagram = datagram;
592 this.callback = callback;
593 }
594 }
595
Sarah Chineccfbd12023-01-20 19:00:35 -0800596 private static final class SatellitePositionUpdateHandler extends Handler {
597 public static final int EVENT_POSITION_UPDATE = 1;
598 public static final int EVENT_MESSAGE_TRANSFER_STATE_UPDATE = 2;
599
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800600 private final ISatelliteStateListener mCallback;
Sarah Chineccfbd12023-01-20 19:00:35 -0800601
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800602 SatellitePositionUpdateHandler(ISatelliteStateListener callback, Looper looper) {
Sarah Chineccfbd12023-01-20 19:00:35 -0800603 super(looper);
604 mCallback = callback;
605 }
606
607 @Override
608 public void handleMessage(@NonNull Message msg) {
609 switch (msg.what) {
610 case EVENT_POSITION_UPDATE: {
611 AsyncResult ar = (AsyncResult) msg.obj;
612 PointingInfo pointingInfo = (PointingInfo) ar.result;
613 try {
614 mCallback.onSatellitePositionUpdate(pointingInfo);
615 } catch (RemoteException e) {
616 loge("EVENT_POSITION_UPDATE RemoteException: " + e);
617 }
618 break;
619 }
620 case EVENT_MESSAGE_TRANSFER_STATE_UPDATE: {
621 AsyncResult ar = (AsyncResult) msg.obj;
622 int state = (int) ar.result;
623 try {
Sarah Chindf715ec2023-02-13 13:46:24 -0800624 // TODO: get correct responses back from indication
625 mCallback.onMessageTransferStateUpdate(state, 0, 0, 0);
Sarah Chineccfbd12023-01-20 19:00:35 -0800626 } catch (RemoteException e) {
627 loge("EVENT_MESSAGE_TRANSFER_STATE_UPDATE RemoteException: " + e);
628 }
629 break;
630 }
631 default:
632 loge("SatellitePositionUpdateHandler unknown event: " + msg.what);
633 }
634 }
635 }
636
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800637 private static final class SatelliteProvisionStateChangedHandler extends Handler {
638 public static final int EVENT_PROVISION_STATE_CHANGED = 1;
639
640 private ConcurrentHashMap<IBinder, ISatelliteStateListener> mListeners;
641 private final int mSubId;
642
643 SatelliteProvisionStateChangedHandler(Looper looper, int subId) {
644 super(looper);
645 mListeners = new ConcurrentHashMap<>();
646 mSubId = subId;
647 }
648
649 public void addListener(ISatelliteStateListener listener) {
650 mListeners.put(listener.asBinder(), listener);
651 }
652
653 public boolean removeListener(ISatelliteStateListener listener) {
654 return (mListeners.remove(listener.asBinder()) != null);
655 }
656
657 @Override
658 public void handleMessage(@NonNull Message msg) {
659 switch (msg.what) {
660 case EVENT_PROVISION_STATE_CHANGED: {
661 AsyncResult ar = (AsyncResult) msg.obj;
662 boolean provisioned = (boolean) ar.userObj;
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800663 log("Received EVENT_PROVISION_STATE_CHANGED for subId=" + mSubId
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800664 + ", provisioned=" + provisioned);
665 mListeners.values().forEach(listener -> {
666 try {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -0800667 listener.onSatelliteProvisionStateChanged(provisioned);
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800668 } catch (RemoteException e) {
669 log("EVENT_PROVISION_STATE_CHANGED RemoteException: " + e);
670 }
671 });
672
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800673 setSatelliteProvisioned(provisioned);
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800674 /**
675 * TODO: Take bugreport if provisioned is true and user did not initiate the
676 * provision procedure for the corresponding subscription.
677 */
678 break;
679 }
680 default:
681 loge("SatelliteProvisionStateChangedHandler unknown event: " + msg.what);
682 }
683 }
684
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800685 private void setSatelliteProvisioned(boolean isProvisioned) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800686 if (mSubId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
687 SubscriptionManager.setSubscriptionProperty(
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800688 mSubId, SubscriptionManager.SATELLITE_ENABLED, isProvisioned ? "1" : "0");
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800689 } else {
Thomas Nguyene77de6d2023-02-10 17:42:43 -0800690 //TODO (b/267826133): set via SatelliteController.
Thomas Nguyen8ee49682023-02-01 11:46:09 -0800691 }
692 }
693 }
694
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +0000695 private static final class SatelliteStateListenerHandler extends Handler {
696 public static final int EVENT_SATELLITE_MODEM_STATE_CHANGE = 1;
697 public static final int EVENT_PENDING_MESSAGE_COUNT = 2;
698
699 private ConcurrentHashMap<IBinder, ISatelliteStateListener> mListeners;
700 private final int mSubId;
701
702 SatelliteStateListenerHandler(Looper looper, int subId) {
703 super(looper);
704 mSubId = subId;
705 mListeners = new ConcurrentHashMap<>();
706 }
707
708 public void addListener(ISatelliteStateListener listener) {
709 mListeners.put(listener.asBinder(), listener);
710 }
711
712 public boolean removeListener(ISatelliteStateListener listener) {
713 return (mListeners.remove(listener.asBinder()) != null);
714 }
715
716 @Override
717 public void handleMessage(@NonNull Message msg) {
718 switch (msg.what) {
719 case EVENT_SATELLITE_MODEM_STATE_CHANGE : {
720 AsyncResult ar = (AsyncResult) msg.obj;
721 int state = (int) ar.result;
722 log("Received EVENT_SATELLITE_MODEM_STATE_CHANGE for subId=" + mSubId
723 + ", state=" + state);
724 mListeners.values().forEach(listener -> {
725 try {
726 listener.onSatelliteModemStateChange(state);
727 } catch (RemoteException e) {
728 log("EVENT_SATELLITE_MODEM_STATE_CHANGE RemoteException: " + e);
729 }
730 });
731 break;
732 }
733 case EVENT_PENDING_MESSAGE_COUNT: {
734 AsyncResult ar = (AsyncResult) msg.obj;
735 int count = (int) ar.result;
736 log("Received EVENT_PENDING_MESSAGE_COUNT for subId=" + mSubId
737 + ", count=" + count);
738 mListeners.values().forEach(listener -> {
739 try {
740 listener.onPendingMessageCount(count);
741 } catch (RemoteException e) {
742 log("EVENT_PENDING_MESSAGE_COUNT RemoteException: " + e);
743 }
744 });
745 break;
746 }
747 default:
748 loge("SatelliteStateListenerHandler unknown event: " + msg.what);
749 }
750 }
751 }
752
753 private static final class SatelliteDatagramListenerHandler extends Handler {
754 public static final int EVENT_SATELLITE_DATAGRAMS_RECEIVED = 1;
755
756 private ConcurrentHashMap<IBinder, ISatelliteStateListener> mListeners;
757 private final int mSubId;
758
759 SatelliteDatagramListenerHandler(Looper looper, int subId) {
760 super(looper);
761 mSubId = subId;
762 mListeners = new ConcurrentHashMap<>();
763 }
764
765 public void addListener(ISatelliteStateListener listener) {
766 mListeners.put(listener.asBinder(), listener);
767 }
768
769 public boolean removeListener(ISatelliteStateListener listener) {
770 return (mListeners.remove(listener.asBinder()) != null);
771 }
772
773 @Override
774 public void handleMessage(@NonNull Message msg) {
775 switch (msg.what) {
776 case EVENT_SATELLITE_DATAGRAMS_RECEIVED : {
777 AsyncResult ar = (AsyncResult) msg.obj;
778 byte[][] datagrams = (byte[][]) ar.result;
779 SatelliteDatagram[] satelliteDatagramArray =
780 convertToSatelliteDatagramArray(datagrams);
781
782 log("Received EVENT_SATELLITE_DATAGRAMS_RECEIVED for subId=" + mSubId);
783 mListeners.values().forEach(listener -> {
784 try {
785 listener.onSatelliteDatagrams(satelliteDatagramArray);
786 } catch (RemoteException e) {
787 log("EVENT_SATELLITE_DATAGRAMS_RECEIVED RemoteException: " + e);
788 }
789 });
790 break;
791 }
792 default:
793 loge("SatelliteDatagramListenerHandler unknown event: " + msg.what);
794 }
795 }
796 }
797
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700798 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700799 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
800 * request after sending. The main thread will notify the request when it is complete.
801 */
802 private static final class MainThreadRequest {
803 /** The argument to use for the request */
804 public Object argument;
805 /** The result of the request that is run on the main thread */
806 public Object result;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800807 // The subscriber id that this request applies to. Defaults to
808 // SubscriptionManager.INVALID_SUBSCRIPTION_ID
809 public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700810
Nathan Harold92bed182018-10-12 18:16:49 -0700811 // In cases where subId is unavailable, the caller needs to specify the phone.
812 public Phone phone;
813
vagdeviaf9a5b92018-08-15 16:01:53 -0700814 public WorkSource workSource;
815
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700816 public MainThreadRequest(Object argument) {
817 this.argument = argument;
818 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800819
Nathan Harold92bed182018-10-12 18:16:49 -0700820 MainThreadRequest(Object argument, Phone phone, WorkSource workSource) {
821 this.argument = argument;
822 if (phone != null) {
823 this.phone = phone;
824 }
825 this.workSource = workSource;
826 }
827
vagdeviaf9a5b92018-08-15 16:01:53 -0700828 MainThreadRequest(Object argument, Integer subId, WorkSource workSource) {
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800829 this.argument = argument;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800830 if (subId != null) {
831 this.subId = subId;
832 }
vagdeviaf9a5b92018-08-15 16:01:53 -0700833 this.workSource = workSource;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800834 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700835 }
836
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800837 private static final class IncomingThirdPartyCallArgs {
838 public final ComponentName component;
839 public final String callId;
840 public final String callerDisplayName;
841
842 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
843 String callerDisplayName) {
844 this.component = component;
845 this.callId = callId;
846 this.callerDisplayName = callerDisplayName;
847 }
848 }
849
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700850 /**
851 * A handler that processes messages on the main thread in the phone process. Since many
852 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
853 * inbound binder threads to the main thread in the phone process. The Binder thread
854 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
855 * on, which will be notified when the operation completes and will contain the result of the
856 * request.
857 *
858 * <p>If a MainThreadRequest object is provided in the msg.obj field,
859 * note that request.result must be set to something non-null for the calling thread to
860 * unblock.
861 */
862 private final class MainThreadHandler extends Handler {
863 @Override
864 public void handleMessage(Message msg) {
865 MainThreadRequest request;
866 Message onCompleted;
867 AsyncResult ar;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000868 UiccPort uiccPort;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700869 IccAPDUArgument iccArgument;
Nazanin Bakhshif782e562018-12-11 15:15:39 -0800870 final Phone defaultPhone = getDefaultPhone();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700871
872 switch (msg.what) {
Pengquan Menga1bb6272018-09-06 09:59:22 -0700873 case CMD_HANDLE_USSD_REQUEST: {
874 request = (MainThreadRequest) msg.obj;
875 final Phone phone = getPhoneFromRequest(request);
876 Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
Chen Xue9d737e2022-01-01 23:41:31 -0800877 String ussdRequest = ussdObject.first;
Pengquan Menga1bb6272018-09-06 09:59:22 -0700878 ResultReceiver wrappedCallback = ussdObject.second;
Tyler Gunn65d45c22017-06-05 11:22:26 -0700879
Pengquan Menga1bb6272018-09-06 09:59:22 -0700880 if (!isUssdApiAllowed(request.subId)) {
881 // Carrier does not support use of this API, return failure.
882 Rlog.w(LOG_TAG, "handleUssdRequest: carrier does not support USSD apis.");
883 UssdResponse response = new UssdResponse(ussdRequest, null);
884 Bundle returnData = new Bundle();
885 returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
886 wrappedCallback.send(TelephonyManager.USSD_RETURN_FAILURE, returnData);
Tyler Gunn65d45c22017-06-05 11:22:26 -0700887
Pengquan Menga1bb6272018-09-06 09:59:22 -0700888 request.result = true;
889 notifyRequester(request);
890 return;
891 }
Tyler Gunn65d45c22017-06-05 11:22:26 -0700892
Pengquan Menga1bb6272018-09-06 09:59:22 -0700893 try {
894 request.result = phone != null
895 ? phone.handleUssdRequest(ussdRequest, wrappedCallback) : false;
896 } catch (CallStateException cse) {
897 request.result = false;
898 }
899 // Wake up the requesting thread
900 notifyRequester(request);
901 break;
pkanwar32d516d2016-10-14 19:37:38 -0700902 }
903
Yorke Lee716f67e2015-06-17 15:39:16 -0700904 case CMD_HANDLE_PIN_MMI: {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700905 request = (MainThreadRequest) msg.obj;
Yorke Lee716f67e2015-06-17 15:39:16 -0700906 final Phone phone = getPhoneFromRequest(request);
907 request.result = phone != null ?
908 getPhoneFromRequest(request).handlePinMmi((String) request.argument)
909 : false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700910 // Wake up the requesting thread
Pengquan Menga1bb6272018-09-06 09:59:22 -0700911 notifyRequester(request);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700912 break;
Yorke Lee716f67e2015-06-17 15:39:16 -0700913 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700914
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700915 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700916 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700917 iccArgument = (IccAPDUArgument) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000918 uiccPort = getUiccPortFromRequest(request);
919 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700920 loge("iccTransmitApduLogicalChannel: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -0800921 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700922 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700923 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700924 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
Chen Xue9d737e2022-01-01 23:41:31 -0800925 request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000926 uiccPort.iccTransmitApduLogicalChannel(
Chen Xue9d737e2022-01-01 23:41:31 -0800927 iccArgument.channel, iccArgument.cla, iccArgument.command,
928 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
929 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700930 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700931 break;
932
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700933 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700934 ar = (AsyncResult) msg.obj;
935 request = (MainThreadRequest) ar.userObj;
936 if (ar.exception == null && ar.result != null) {
937 request.result = ar.result;
938 } else {
Chen Xue9d737e2022-01-01 23:41:31 -0800939 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700940 if (ar.result == null) {
941 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800942 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700943 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800944 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700945 } else {
946 loge("iccTransmitApduLogicalChannel: Unknown exception");
947 }
948 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700949 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700950 break;
951
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700952 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
953 request = (MainThreadRequest) msg.obj;
954 iccArgument = (IccAPDUArgument) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000955 uiccPort = getUiccPortFromRequest(request);
956 if (uiccPort == null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700957 loge("iccTransmitApduBasicChannel: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -0800958 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700959 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700960 } else {
961 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
Chen Xue9d737e2022-01-01 23:41:31 -0800962 request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000963 uiccPort.iccTransmitApduBasicChannel(
Chen Xue9d737e2022-01-01 23:41:31 -0800964 iccArgument.cla, iccArgument.command, iccArgument.p1,
965 iccArgument.p2,
966 iccArgument.p3, iccArgument.data, onCompleted);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700967 }
968 break;
969
970 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
971 ar = (AsyncResult) msg.obj;
972 request = (MainThreadRequest) ar.userObj;
973 if (ar.exception == null && ar.result != null) {
974 request.result = ar.result;
975 } else {
Chen Xue9d737e2022-01-01 23:41:31 -0800976 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700977 if (ar.result == null) {
978 loge("iccTransmitApduBasicChannel: Empty response");
979 } else if (ar.exception instanceof CommandException) {
980 loge("iccTransmitApduBasicChannel: CommandException: " +
981 ar.exception);
982 } else {
983 loge("iccTransmitApduBasicChannel: Unknown exception");
984 }
985 }
Pengquan Menga1bb6272018-09-06 09:59:22 -0700986 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700987 break;
988
989 case CMD_EXCHANGE_SIM_IO:
990 request = (MainThreadRequest) msg.obj;
991 iccArgument = (IccAPDUArgument) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +0000992 uiccPort = getUiccPortFromRequest(request);
993 if (uiccPort == null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700994 loge("iccExchangeSimIO: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -0800995 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -0700996 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700997 } else {
998 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
999 request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001000 uiccPort.iccExchangeSimIO(iccArgument.cla, /* fileID */
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001001 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
1002 iccArgument.data, onCompleted);
1003 }
1004 break;
1005
1006 case EVENT_EXCHANGE_SIM_IO_DONE:
1007 ar = (AsyncResult) msg.obj;
1008 request = (MainThreadRequest) ar.userObj;
1009 if (ar.exception == null && ar.result != null) {
1010 request.result = ar.result;
1011 } else {
Chen Xue9d737e2022-01-01 23:41:31 -08001012 request.result = new IccIoResult(0x6f, 0, (byte[]) null);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001013 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001014 notifyRequester(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001015 break;
1016
Derek Tan4d5e5c12014-02-04 11:54:58 -08001017 case CMD_SEND_ENVELOPE:
1018 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001019 uiccPort = getUiccPortFromRequest(request);
1020 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001021 loge("sendEnvelopeWithStatus: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -08001022 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001023 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001024 } else {
1025 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
Chen Xue9d737e2022-01-01 23:41:31 -08001026 uiccPort.sendEnvelopeWithStatus((String) request.argument, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001027 }
Derek Tan4d5e5c12014-02-04 11:54:58 -08001028 break;
1029
1030 case EVENT_SEND_ENVELOPE_DONE:
1031 ar = (AsyncResult) msg.obj;
1032 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -07001033 if (ar.exception == null && ar.result != null) {
1034 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -08001035 } else {
Chen Xue9d737e2022-01-01 23:41:31 -08001036 request.result = new IccIoResult(0x6F, 0, (byte[]) null);
Shishir Agrawal9f9877d2014-03-14 09:36:27 -07001037 if (ar.result == null) {
1038 loge("sendEnvelopeWithStatus: Empty response");
1039 } else if (ar.exception instanceof CommandException) {
1040 loge("sendEnvelopeWithStatus: CommandException: " +
1041 ar.exception);
1042 } else {
1043 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
1044 }
Derek Tan4d5e5c12014-02-04 11:54:58 -08001045 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001046 notifyRequester(request);
Derek Tan4d5e5c12014-02-04 11:54:58 -08001047 break;
1048
Shishir Agrawal566b7612013-10-28 14:41:00 -07001049 case CMD_OPEN_CHANNEL:
1050 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001051 uiccPort = getUiccPortFromRequest(request);
Rambo Wanga1782702021-11-10 20:15:19 -08001052 IccLogicalChannelRequest openChannelRequest =
1053 (IccLogicalChannelRequest) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001054 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001055 loge("iccOpenLogicalChannel: No UICC");
Shishir Agrawalfc0492a2016-02-17 11:15:33 -08001056 request.result = new IccOpenLogicalChannelResponse(-1,
Chen Xue9d737e2022-01-01 23:41:31 -08001057 IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001058 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001059 } else {
1060 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
Rambo Wanga1782702021-11-10 20:15:19 -08001061 uiccPort.iccOpenLogicalChannel(openChannelRequest.aid,
1062 openChannelRequest.p2, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001063 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001064 break;
1065
1066 case EVENT_OPEN_CHANNEL_DONE:
1067 ar = (AsyncResult) msg.obj;
1068 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001069 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -07001070 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001071 int[] result = (int[]) ar.result;
1072 int channelId = result[0];
1073 byte[] selectResponse = null;
1074 if (result.length > 1) {
1075 selectResponse = new byte[result.length - 1];
1076 for (int i = 1; i < result.length; ++i) {
1077 selectResponse[i - 1] = (byte) result[i];
1078 }
1079 }
1080 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Chen Xue9d737e2022-01-01 23:41:31 -08001081 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Rambo Wang3b77c4c2021-11-10 20:15:19 -08001082
1083 uiccPort = getUiccPortFromRequest(request);
Rambo Wange53e07d2022-05-10 13:01:13 -07001084 if (uiccPort == null) {
1085 loge("EVENT_OPEN_CHANNEL_DONE: UiccPort is null");
1086 } else {
1087 IccLogicalChannelRequest channelRequest =
1088 (IccLogicalChannelRequest) request.argument;
1089 channelRequest.channel = channelId;
1090 uiccPort.onLogicalChannelOpened(channelRequest);
1091 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001092 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -07001093 if (ar.result == null) {
1094 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -07001095 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001096 if (ar.exception != null) {
1097 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
1098 }
1099
Shishir Agrawal527e8bf2014-08-25 08:54:56 -07001100 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Junda Liua754ba12015-05-20 01:17:52 -07001101 if (ar.exception instanceof CommandException) {
1102 CommandException.Error error =
Chen Xue9d737e2022-01-01 23:41:31 -08001103 ((CommandException) (ar.exception)).getCommandError();
Junda Liua754ba12015-05-20 01:17:52 -07001104 if (error == CommandException.Error.MISSING_RESOURCE) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -07001105 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Junda Liua754ba12015-05-20 01:17:52 -07001106 } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -07001107 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001108 }
1109 }
1110 openChannelResp = new IccOpenLogicalChannelResponse(
Chen Xue9d737e2022-01-01 23:41:31 -08001111 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001112 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -07001113 request.result = openChannelResp;
Pengquan Menga1bb6272018-09-06 09:59:22 -07001114 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001115 break;
1116
1117 case CMD_CLOSE_CHANNEL:
1118 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001119 uiccPort = getUiccPortFromRequest(request);
1120 if (uiccPort == null) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001121 loge("iccCloseLogicalChannel: No UICC");
Chen Xua8f0dff2022-02-12 00:34:15 -08001122 request.result = new IllegalArgumentException(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001123 "iccCloseLogicalChannel: No UICC");
Chen Xue9d737e2022-01-01 23:41:31 -08001124 notifyRequester(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001125 } else {
1126 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001127 uiccPort.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001128 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001129 break;
1130
1131 case EVENT_CLOSE_CHANNEL_DONE:
Chen Xu540470b2021-12-14 17:15:47 -08001132 ar = (AsyncResult) msg.obj;
1133 request = (MainThreadRequest) ar.userObj;
1134 if (ar.exception == null) {
1135 request.result = true;
Rambo Wang3b77c4c2021-11-10 20:15:19 -08001136 uiccPort = getUiccPortFromRequest(request);
Rambo Wange53e07d2022-05-10 13:01:13 -07001137 if (uiccPort == null) {
1138 loge("EVENT_CLOSE_CHANNEL_DONE: UiccPort is null");
1139 } else {
1140 final int channelId = (Integer) request.argument;
1141 uiccPort.onLogicalChannelClosed(channelId);
1142 }
Chen Xu540470b2021-12-14 17:15:47 -08001143 } else {
1144 request.result = false;
Chen Xue9d737e2022-01-01 23:41:31 -08001145 Exception exception = null;
Chen Xu540470b2021-12-14 17:15:47 -08001146 if (ar.exception instanceof CommandException) {
1147 loge("iccCloseLogicalChannel: CommandException: " + ar.exception);
1148 CommandException.Error error =
1149 ((CommandException) (ar.exception)).getCommandError();
Chen Xue9d737e2022-01-01 23:41:31 -08001150 if (error == CommandException.Error.INVALID_ARGUMENTS) {
1151 // should only throw exceptions from the binder threads.
1152 exception = new IllegalArgumentException(
Chen Xu540470b2021-12-14 17:15:47 -08001153 "iccCloseLogicalChannel: invalid argument ");
1154 }
1155 } else {
1156 loge("iccCloseLogicalChannel: Unknown exception");
1157 }
Chen Xua8f0dff2022-02-12 00:34:15 -08001158 request.result = (exception != null) ? exception :
1159 new IllegalStateException(
1160 "exception from modem to close iccLogical Channel");
Chen Xu540470b2021-12-14 17:15:47 -08001161 }
1162 notifyRequester(request);
Jake Hambye994d462014-02-03 13:10:13 -08001163 break;
1164
1165 case CMD_NV_READ_ITEM:
1166 request = (MainThreadRequest) msg.obj;
1167 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001168 defaultPhone.nvReadItem((Integer) request.argument, onCompleted,
1169 request.workSource);
Jake Hambye994d462014-02-03 13:10:13 -08001170 break;
1171
1172 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -07001173 ar = (AsyncResult) msg.obj;
1174 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -08001175 if (ar.exception == null && ar.result != null) {
1176 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -07001177 } else {
Jake Hambye994d462014-02-03 13:10:13 -08001178 request.result = "";
1179 if (ar.result == null) {
1180 loge("nvReadItem: Empty response");
1181 } else if (ar.exception instanceof CommandException) {
1182 loge("nvReadItem: CommandException: " +
1183 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001184 } else {
Jake Hambye994d462014-02-03 13:10:13 -08001185 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -07001186 }
1187 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001188 notifyRequester(request);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001189 break;
1190
Jake Hambye994d462014-02-03 13:10:13 -08001191 case CMD_NV_WRITE_ITEM:
1192 request = (MainThreadRequest) msg.obj;
1193 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
1194 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001195 defaultPhone.nvWriteItem(idValue.first, idValue.second, onCompleted,
vagdeviaf9a5b92018-08-15 16:01:53 -07001196 request.workSource);
Jake Hambye994d462014-02-03 13:10:13 -08001197 break;
1198
1199 case EVENT_NV_WRITE_ITEM_DONE:
1200 handleNullReturnEvent(msg, "nvWriteItem");
1201 break;
1202
1203 case CMD_NV_WRITE_CDMA_PRL:
1204 request = (MainThreadRequest) msg.obj;
1205 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001206 defaultPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
Jake Hambye994d462014-02-03 13:10:13 -08001207 break;
1208
1209 case EVENT_NV_WRITE_CDMA_PRL_DONE:
1210 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
1211 break;
1212
chen xu6dac5ab2018-10-26 17:39:23 -07001213 case CMD_RESET_MODEM_CONFIG:
Jake Hambye994d462014-02-03 13:10:13 -08001214 request = (MainThreadRequest) msg.obj;
chen xu6dac5ab2018-10-26 17:39:23 -07001215 onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001216 defaultPhone.resetModemConfig(onCompleted);
Jake Hambye994d462014-02-03 13:10:13 -08001217 break;
1218
chen xu6dac5ab2018-10-26 17:39:23 -07001219 case EVENT_RESET_MODEM_CONFIG_DONE:
1220 handleNullReturnEvent(msg, "resetModemConfig");
Jake Hambye994d462014-02-03 13:10:13 -08001221 break;
1222
Sooraj Sasindran37444802020-08-11 10:40:43 -07001223 case CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED: {
1224 request = (MainThreadRequest) msg.obj;
1225 onCompleted = obtainMessage(EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE,
1226 request);
1227 Phone phone = getPhoneFromRequest(request);
1228 if (phone != null) {
1229 phone.isNrDualConnectivityEnabled(onCompleted, request.workSource);
1230 } else {
1231 loge("isNRDualConnectivityEnabled: No phone object");
1232 request.result = false;
1233 notifyRequester(request);
1234 }
1235 break;
1236 }
1237
1238 case EVENT_IS_NR_DUAL_CONNECTIVITY_ENABLED_DONE:
1239 ar = (AsyncResult) msg.obj;
1240 request = (MainThreadRequest) ar.userObj;
1241 if (ar.exception == null && ar.result != null) {
1242 request.result = ar.result;
1243 } else {
1244 // request.result must be set to something non-null
1245 // for the calling thread to unblock
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07001246 if (ar.result != null) {
Sooraj Sasindran37444802020-08-11 10:40:43 -07001247 request.result = ar.result;
1248 } else {
1249 request.result = false;
1250 }
1251 if (ar.result == null) {
1252 loge("isNRDualConnectivityEnabled: Empty response");
1253 } else if (ar.exception instanceof CommandException) {
1254 loge("isNRDualConnectivityEnabled: CommandException: "
1255 + ar.exception);
1256 } else {
1257 loge("isNRDualConnectivityEnabled: Unknown exception");
1258 }
1259 }
1260 notifyRequester(request);
1261 break;
1262
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07001263 case CMD_IS_VONR_ENABLED: {
1264 request = (MainThreadRequest) msg.obj;
1265 onCompleted = obtainMessage(EVENT_IS_VONR_ENABLED_DONE,
1266 request);
1267 Phone phone = getPhoneFromRequest(request);
1268 if (phone != null) {
1269 phone.isVoNrEnabled(onCompleted, request.workSource);
1270 } else {
1271 loge("isVoNrEnabled: No phone object");
1272 request.result = false;
1273 notifyRequester(request);
1274 }
1275 break;
1276 }
1277
1278 case EVENT_IS_VONR_ENABLED_DONE:
1279 ar = (AsyncResult) msg.obj;
1280 request = (MainThreadRequest) ar.userObj;
1281 if (ar.exception == null && ar.result != null) {
1282 request.result = ar.result;
1283 } else {
1284 // request.result must be set to something non-null
1285 // for the calling thread to unblock
1286 if (ar.result != null) {
1287 request.result = ar.result;
1288 } else {
1289 request.result = false;
1290 }
1291 if (ar.result == null) {
1292 loge("isVoNrEnabled: Empty response");
1293 } else if (ar.exception instanceof CommandException) {
1294 loge("isVoNrEnabled: CommandException: "
1295 + ar.exception);
1296 } else {
1297 loge("isVoNrEnabled: Unknown exception");
1298 }
1299 }
1300 notifyRequester(request);
1301 break;
1302
Sooraj Sasindran37444802020-08-11 10:40:43 -07001303 case CMD_ENABLE_NR_DUAL_CONNECTIVITY: {
1304 request = (MainThreadRequest) msg.obj;
1305 onCompleted = obtainMessage(EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE, request);
1306 Phone phone = getPhoneFromRequest(request);
1307 if (phone != null) {
1308 phone.setNrDualConnectivityState((int) request.argument, onCompleted,
1309 request.workSource);
1310 } else {
1311 loge("enableNrDualConnectivity: No phone object");
1312 request.result =
1313 TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
1314 notifyRequester(request);
1315 }
1316 break;
1317 }
1318
1319 case EVENT_ENABLE_NR_DUAL_CONNECTIVITY_DONE: {
1320 ar = (AsyncResult) msg.obj;
1321 request = (MainThreadRequest) ar.userObj;
1322 if (ar.exception == null) {
1323 request.result =
1324 TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_SUCCESS;
1325 } else {
1326 request.result =
1327 TelephonyManager
1328 .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_ERROR;
1329 if (ar.exception instanceof CommandException) {
1330 CommandException.Error error =
1331 ((CommandException) (ar.exception)).getCommandError();
1332 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
1333 request.result =
1334 TelephonyManager
1335 .ENABLE_NR_DUAL_CONNECTIVITY_RADIO_NOT_AVAILABLE;
Sooraj Sasindran29654162021-03-03 23:00:01 +00001336 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1337 request.result =
1338 TelephonyManager
1339 .ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED;
Sooraj Sasindran37444802020-08-11 10:40:43 -07001340 }
1341 loge("enableNrDualConnectivity" + ": CommandException: "
1342 + ar.exception);
1343 } else {
1344 loge("enableNrDualConnectivity" + ": Unknown exception");
1345 }
1346 }
1347 notifyRequester(request);
1348 break;
1349 }
1350
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07001351 case CMD_ENABLE_VONR: {
1352 request = (MainThreadRequest) msg.obj;
1353 onCompleted = obtainMessage(EVENT_ENABLE_VONR_DONE, request);
1354 Phone phone = getPhoneFromRequest(request);
1355 if (phone != null) {
1356 phone.setVoNrEnabled((boolean) request.argument, onCompleted,
1357 request.workSource);
1358 } else {
1359 loge("setVoNrEnabled: No phone object");
1360 request.result =
1361 TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
1362 notifyRequester(request);
1363 }
1364 break;
1365 }
1366
1367 case EVENT_ENABLE_VONR_DONE: {
1368 ar = (AsyncResult) msg.obj;
1369 request = (MainThreadRequest) ar.userObj;
1370 if (ar.exception == null) {
1371 request.result = TelephonyManager.ENABLE_VONR_SUCCESS;
1372 } else {
1373 request.result = TelephonyManager.ENABLE_VONR_RADIO_ERROR;
1374 if (ar.exception instanceof CommandException) {
1375 CommandException.Error error =
1376 ((CommandException) (ar.exception)).getCommandError();
1377 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
1378 request.result = TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
1379 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1380 request.result = TelephonyManager.ENABLE_VONR_REQUEST_NOT_SUPPORTED;
1381 } else {
1382 request.result = TelephonyManager.ENABLE_VONR_RADIO_ERROR;
1383 }
1384 loge("setVoNrEnabled" + ": CommandException: "
1385 + ar.exception);
1386 } else {
1387 loge("setVoNrEnabled" + ": Unknown exception");
1388 }
1389 }
1390 notifyRequester(request);
1391 break;
1392 }
1393
SongFerngWang3ef3e072020-12-21 16:41:52 +08001394 case CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK:
Jake Hamby7c27be32014-03-03 13:25:59 -08001395 request = (MainThreadRequest) msg.obj;
SongFerngWang3ef3e072020-12-21 16:41:52 +08001396 onCompleted = obtainMessage(EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE,
1397 request);
1398 getPhoneFromRequest(request).getAllowedNetworkTypesBitmask(onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -08001399 break;
1400
SongFerngWang3ef3e072020-12-21 16:41:52 +08001401 case EVENT_GET_ALLOWED_NETWORK_TYPES_BITMASK_DONE:
Jake Hamby7c27be32014-03-03 13:25:59 -08001402 ar = (AsyncResult) msg.obj;
1403 request = (MainThreadRequest) ar.userObj;
1404 if (ar.exception == null && ar.result != null) {
1405 request.result = ar.result; // Integer
1406 } else {
Nazish Tabassume8ba43a2020-07-28 14:49:25 +05301407 // request.result must be set to something non-null
1408 // for the calling thread to unblock
1409 request.result = new int[]{-1};
Jake Hamby7c27be32014-03-03 13:25:59 -08001410 if (ar.result == null) {
SongFerngWang3ef3e072020-12-21 16:41:52 +08001411 loge("getAllowedNetworkTypesBitmask: Empty response");
Jake Hamby7c27be32014-03-03 13:25:59 -08001412 } else if (ar.exception instanceof CommandException) {
SongFerngWang3ef3e072020-12-21 16:41:52 +08001413 loge("getAllowedNetworkTypesBitmask: CommandException: "
1414 + ar.exception);
Jake Hamby7c27be32014-03-03 13:25:59 -08001415 } else {
SongFerngWang3ef3e072020-12-21 16:41:52 +08001416 loge("getAllowedNetworkTypesBitmask: Unknown exception");
Jake Hamby7c27be32014-03-03 13:25:59 -08001417 }
1418 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001419 notifyRequester(request);
Jake Hamby7c27be32014-03-03 13:25:59 -08001420 break;
1421
SongFerngWang3ef3e072020-12-21 16:41:52 +08001422 case CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON:
Jake Hamby7c27be32014-03-03 13:25:59 -08001423 request = (MainThreadRequest) msg.obj;
SongFerngWang3ef3e072020-12-21 16:41:52 +08001424 onCompleted = obtainMessage(EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE,
1425 request);
1426 Pair<Integer, Long> reasonWithNetworkTypes =
1427 (Pair<Integer, Long>) request.argument;
1428 getPhoneFromRequest(request).setAllowedNetworkTypes(
1429 reasonWithNetworkTypes.first,
1430 reasonWithNetworkTypes.second,
1431 onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -08001432 break;
1433
SongFerngWang3ef3e072020-12-21 16:41:52 +08001434 case EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE:
1435 handleNullReturnEvent(msg, "setAllowedNetworkTypesForReason");
Jake Hamby7c27be32014-03-03 13:25:59 -08001436 break;
1437
Shuo Qian850e4d6a2018-04-25 21:02:08 +00001438 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
1439 request = (MainThreadRequest)msg.obj;
1440 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001441 defaultPhone.invokeOemRilRequestRaw((byte[]) request.argument, onCompleted);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00001442 break;
1443
1444 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
1445 ar = (AsyncResult)msg.obj;
1446 request = (MainThreadRequest)ar.userObj;
1447 request.result = ar;
Pengquan Menga1bb6272018-09-06 09:59:22 -07001448 notifyRequester(request);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00001449 break;
1450
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001451 case CMD_SET_VOICEMAIL_NUMBER:
1452 request = (MainThreadRequest) msg.obj;
1453 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
1454 Pair<String, String> tagNum = (Pair<String, String>) request.argument;
Stuart Scott584921c2015-01-15 17:10:34 -08001455 getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
1456 onCompleted);
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001457 break;
1458
1459 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
1460 handleNullReturnEvent(msg, "setVoicemailNumber");
1461 break;
1462
Stuart Scott54788802015-03-30 13:18:01 -07001463 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
1464 request = (MainThreadRequest) msg.obj;
1465 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
1466 request);
1467 getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
1468 break;
1469
1470 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
1471 handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
1472 break;
1473
Shishir Agrawal302c8692015-06-19 13:49:39 -07001474 case CMD_PERFORM_NETWORK_SCAN:
1475 request = (MainThreadRequest) msg.obj;
1476 onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
1477 getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
1478 break;
1479
Hall Liu27d24262020-09-18 19:04:59 -07001480 case CMD_GET_CALL_FORWARDING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001481 request = (MainThreadRequest) msg.obj;
1482 onCompleted = obtainMessage(EVENT_GET_CALL_FORWARDING_DONE, request);
Hall Liu27d24262020-09-18 19:04:59 -07001483 Pair<Integer, TelephonyManager.CallForwardingInfoCallback> args =
1484 (Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
1485 request.argument;
1486 int callForwardingReason = args.first;
1487 request.phone.getCallForwardingOption(callForwardingReason, onCompleted);
Shuo Qian4a594052020-01-23 11:59:30 -08001488 break;
Hall Liu27d24262020-09-18 19:04:59 -07001489 }
1490 case EVENT_GET_CALL_FORWARDING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001491 ar = (AsyncResult) msg.obj;
1492 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001493 TelephonyManager.CallForwardingInfoCallback callback =
1494 ((Pair<Integer, TelephonyManager.CallForwardingInfoCallback>)
1495 request.argument).second;
Shuo Qian4a594052020-01-23 11:59:30 -08001496 if (ar.exception == null && ar.result != null) {
Hall Liu27d24262020-09-18 19:04:59 -07001497 CallForwardingInfo callForwardingInfo = null;
Shuo Qian4a594052020-01-23 11:59:30 -08001498 CallForwardInfo[] callForwardInfos = (CallForwardInfo[]) ar.result;
1499 for (CallForwardInfo callForwardInfo : callForwardInfos) {
1500 // Service Class is a bit mask per 3gpp 27.007. Search for
1501 // any service for voice call.
1502 if ((callForwardInfo.serviceClass
1503 & CommandsInterface.SERVICE_CLASS_VOICE) > 0) {
Yuchen Dong69cc1412021-09-27 20:27:01 +08001504 callForwardingInfo = new CallForwardingInfo(
1505 callForwardInfo.status
1506 == CommandsInterface.CF_ACTION_ENABLE,
Hall Liu27d24262020-09-18 19:04:59 -07001507 callForwardInfo.reason,
1508 callForwardInfo.number,
1509 callForwardInfo.timeSeconds);
Shuo Qian4a594052020-01-23 11:59:30 -08001510 break;
1511 }
1512 }
1513 // Didn't find a call forward info for voice call.
1514 if (callForwardingInfo == null) {
Hall Liu27d24262020-09-18 19:04:59 -07001515 callForwardingInfo = new CallForwardingInfo(false /* enabled */,
1516 0 /* reason */, null /* number */, 0 /* timeout */);
Shuo Qian4a594052020-01-23 11:59:30 -08001517 }
Hall Liu27d24262020-09-18 19:04:59 -07001518 callback.onCallForwardingInfoAvailable(callForwardingInfo);
Shuo Qian4a594052020-01-23 11:59:30 -08001519 } else {
1520 if (ar.result == null) {
1521 loge("EVENT_GET_CALL_FORWARDING_DONE: Empty response");
1522 }
1523 if (ar.exception != null) {
1524 loge("EVENT_GET_CALL_FORWARDING_DONE: Exception: " + ar.exception);
1525 }
Hall Liu940c4ca2020-09-29 17:10:18 -07001526 int errorCode = TelephonyManager
1527 .CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN;
Shuo Qian4a594052020-01-23 11:59:30 -08001528 if (ar.exception instanceof CommandException) {
1529 CommandException.Error error =
1530 ((CommandException) (ar.exception)).getCommandError();
1531 if (error == CommandException.Error.FDN_CHECK_FAILURE) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001532 errorCode = TelephonyManager
1533 .CallForwardingInfoCallback.RESULT_ERROR_FDN_CHECK_FAILURE;
Shuo Qian4a594052020-01-23 11:59:30 -08001534 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001535 errorCode = TelephonyManager
1536 .CallForwardingInfoCallback.RESULT_ERROR_NOT_SUPPORTED;
Shuo Qian4a594052020-01-23 11:59:30 -08001537 }
1538 }
Hall Liu27d24262020-09-18 19:04:59 -07001539 callback.onError(errorCode);
Shuo Qian4a594052020-01-23 11:59:30 -08001540 }
Shuo Qian4a594052020-01-23 11:59:30 -08001541 break;
Hall Liu27d24262020-09-18 19:04:59 -07001542 }
Shuo Qian4a594052020-01-23 11:59:30 -08001543
Hall Liu27d24262020-09-18 19:04:59 -07001544 case CMD_SET_CALL_FORWARDING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001545 request = (MainThreadRequest) msg.obj;
1546 onCompleted = obtainMessage(EVENT_SET_CALL_FORWARDING_DONE, request);
Hall Liu27d24262020-09-18 19:04:59 -07001547 request = (MainThreadRequest) msg.obj;
Shuo Qian4a594052020-01-23 11:59:30 -08001548 CallForwardingInfo callForwardingInfoToSet =
Hall Liu27d24262020-09-18 19:04:59 -07001549 ((Pair<CallForwardingInfo, Consumer<Integer>>)
1550 request.argument).first;
1551 request.phone.setCallForwardingOption(
1552 callForwardingInfoToSet.isEnabled()
Calvin Pan258f1f72021-07-28 21:46:56 +08001553 ? CommandsInterface.CF_ACTION_REGISTRATION
Hall Liu27d24262020-09-18 19:04:59 -07001554 : CommandsInterface.CF_ACTION_DISABLE,
Shuo Qian4a594052020-01-23 11:59:30 -08001555 callForwardingInfoToSet.getReason(),
1556 callForwardingInfoToSet.getNumber(),
1557 callForwardingInfoToSet.getTimeoutSeconds(), onCompleted);
1558 break;
Hall Liu27d24262020-09-18 19:04:59 -07001559 }
Shuo Qian4a594052020-01-23 11:59:30 -08001560
Hall Liu27d24262020-09-18 19:04:59 -07001561 case EVENT_SET_CALL_FORWARDING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001562 ar = (AsyncResult) msg.obj;
1563 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001564 Consumer<Integer> callback =
1565 ((Pair<CallForwardingInfo, Consumer<Integer>>)
1566 request.argument).second;
1567 if (ar.exception != null) {
Shuo Qian4a594052020-01-23 11:59:30 -08001568 loge("setCallForwarding exception: " + ar.exception);
Hall Liu940c4ca2020-09-29 17:10:18 -07001569 int errorCode = TelephonyManager.CallForwardingInfoCallback
1570 .RESULT_ERROR_UNKNOWN;
Hall Liu27d24262020-09-18 19:04:59 -07001571 if (ar.exception instanceof CommandException) {
1572 CommandException.Error error =
1573 ((CommandException) (ar.exception)).getCommandError();
1574 if (error == CommandException.Error.FDN_CHECK_FAILURE) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001575 errorCode = TelephonyManager.CallForwardingInfoCallback
1576 .RESULT_ERROR_FDN_CHECK_FAILURE;
Hall Liu27d24262020-09-18 19:04:59 -07001577 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
Hall Liu940c4ca2020-09-29 17:10:18 -07001578 errorCode = TelephonyManager.CallForwardingInfoCallback
1579 .RESULT_ERROR_NOT_SUPPORTED;
Hall Liu27d24262020-09-18 19:04:59 -07001580 }
1581 }
1582 callback.accept(errorCode);
1583 } else {
Hall Liu940c4ca2020-09-29 17:10:18 -07001584 callback.accept(TelephonyManager.CallForwardingInfoCallback.RESULT_SUCCESS);
Shuo Qian4a594052020-01-23 11:59:30 -08001585 }
Shuo Qian4a594052020-01-23 11:59:30 -08001586 break;
Hall Liu27d24262020-09-18 19:04:59 -07001587 }
Shuo Qian4a594052020-01-23 11:59:30 -08001588
Hall Liu27d24262020-09-18 19:04:59 -07001589 case CMD_GET_CALL_WAITING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001590 request = (MainThreadRequest) msg.obj;
1591 onCompleted = obtainMessage(EVENT_GET_CALL_WAITING_DONE, request);
1592 getPhoneFromRequest(request).getCallWaiting(onCompleted);
1593 break;
Hall Liu27d24262020-09-18 19:04:59 -07001594 }
Shuo Qian4a594052020-01-23 11:59:30 -08001595
Hall Liu27d24262020-09-18 19:04:59 -07001596 case EVENT_GET_CALL_WAITING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001597 ar = (AsyncResult) msg.obj;
1598 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001599 Consumer<Integer> callback = (Consumer<Integer>) request.argument;
SongFerngWangebda2c52022-01-11 15:28:38 +08001600 int callWaitingStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
Shuo Qian4a594052020-01-23 11:59:30 -08001601 if (ar.exception == null && ar.result != null) {
Shuo Qiand6a0dba2020-02-18 18:13:49 -08001602 int[] callForwardResults = (int[]) ar.result;
Shuo Qian4a594052020-01-23 11:59:30 -08001603 // Service Class is a bit mask per 3gpp 27.007.
1604 // Search for any service for voice call.
Shuo Qiand6a0dba2020-02-18 18:13:49 -08001605 if (callForwardResults.length > 1
1606 && ((callForwardResults[1]
Hall Liu27d24262020-09-18 19:04:59 -07001607 & CommandsInterface.SERVICE_CLASS_VOICE) > 0)) {
SongFerngWangebda2c52022-01-11 15:28:38 +08001608 callWaitingStatus = callForwardResults[0] == 0
Hall Liu27d24262020-09-18 19:04:59 -07001609 ? TelephonyManager.CALL_WAITING_STATUS_DISABLED
1610 : TelephonyManager.CALL_WAITING_STATUS_ENABLED;
Shuo Qian4a594052020-01-23 11:59:30 -08001611 } else {
SongFerngWangebda2c52022-01-11 15:28:38 +08001612 callWaitingStatus = TelephonyManager.CALL_WAITING_STATUS_DISABLED;
Shuo Qian4a594052020-01-23 11:59:30 -08001613 }
1614 } else {
1615 if (ar.result == null) {
1616 loge("EVENT_GET_CALL_WAITING_DONE: Empty response");
1617 }
1618 if (ar.exception != null) {
1619 loge("EVENT_GET_CALL_WAITING_DONE: Exception: " + ar.exception);
1620 }
1621 if (ar.exception instanceof CommandException) {
1622 CommandException.Error error =
1623 ((CommandException) (ar.exception)).getCommandError();
1624 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
SongFerngWangebda2c52022-01-11 15:28:38 +08001625 callWaitingStatus =
Shuo Qian4a594052020-01-23 11:59:30 -08001626 TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED;
SongFerngWangebda2c52022-01-11 15:28:38 +08001627 } else if (error == CommandException.Error.FDN_CHECK_FAILURE) {
1628 callWaitingStatus =
1629 TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE;
Shuo Qian4a594052020-01-23 11:59:30 -08001630 }
1631 }
1632 }
SongFerngWangebda2c52022-01-11 15:28:38 +08001633 callback.accept(callWaitingStatus);
Shuo Qian4a594052020-01-23 11:59:30 -08001634 break;
Hall Liu27d24262020-09-18 19:04:59 -07001635 }
Shuo Qian4a594052020-01-23 11:59:30 -08001636
Hall Liu27d24262020-09-18 19:04:59 -07001637 case CMD_SET_CALL_WAITING: {
Shuo Qian4a594052020-01-23 11:59:30 -08001638 request = (MainThreadRequest) msg.obj;
1639 onCompleted = obtainMessage(EVENT_SET_CALL_WAITING_DONE, request);
Hall Liu27d24262020-09-18 19:04:59 -07001640 boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
1641 getPhoneFromRequest(request).setCallWaiting(enable, onCompleted);
Shuo Qian4a594052020-01-23 11:59:30 -08001642 break;
Hall Liu27d24262020-09-18 19:04:59 -07001643 }
Shuo Qian4a594052020-01-23 11:59:30 -08001644
Hall Liu27d24262020-09-18 19:04:59 -07001645 case EVENT_SET_CALL_WAITING_DONE: {
Shuo Qian4a594052020-01-23 11:59:30 -08001646 ar = (AsyncResult) msg.obj;
1647 request = (MainThreadRequest) ar.userObj;
Hall Liu27d24262020-09-18 19:04:59 -07001648 boolean enable = ((Pair<Boolean, Consumer<Integer>>) request.argument).first;
1649 Consumer<Integer> callback =
1650 ((Pair<Boolean, Consumer<Integer>>) request.argument).second;
1651 if (ar.exception != null) {
Shuo Qian4a594052020-01-23 11:59:30 -08001652 loge("setCallWaiting exception: " + ar.exception);
Hall Liu27d24262020-09-18 19:04:59 -07001653 if (ar.exception instanceof CommandException) {
1654 CommandException.Error error =
1655 ((CommandException) (ar.exception)).getCommandError();
1656 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1657 callback.accept(TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED);
SongFerngWangebda2c52022-01-11 15:28:38 +08001658 } else if (error == CommandException.Error.FDN_CHECK_FAILURE) {
1659 callback.accept(
1660 TelephonyManager.CALL_WAITING_STATUS_FDN_CHECK_FAILURE);
Hall Liu27d24262020-09-18 19:04:59 -07001661 } else {
1662 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
1663 }
1664 } else {
1665 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
1666 }
1667 } else {
1668 callback.accept(enable ? TelephonyManager.CALL_WAITING_STATUS_ENABLED
1669 : TelephonyManager.CALL_WAITING_STATUS_DISABLED);
Shuo Qian4a594052020-01-23 11:59:30 -08001670 }
Shuo Qian4a594052020-01-23 11:59:30 -08001671 break;
Hall Liu27d24262020-09-18 19:04:59 -07001672 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07001673 case EVENT_PERFORM_NETWORK_SCAN_DONE:
1674 ar = (AsyncResult) msg.obj;
1675 request = (MainThreadRequest) ar.userObj;
1676 CellNetworkScanResult cellScanResult;
1677 if (ar.exception == null && ar.result != null) {
1678 cellScanResult = new CellNetworkScanResult(
1679 CellNetworkScanResult.STATUS_SUCCESS,
1680 (List<OperatorInfo>) ar.result);
1681 } else {
1682 if (ar.result == null) {
1683 loge("getCellNetworkScanResults: Empty response");
1684 }
1685 if (ar.exception != null) {
1686 loge("getCellNetworkScanResults: Exception: " + ar.exception);
1687 }
1688 int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
1689 if (ar.exception instanceof CommandException) {
1690 CommandException.Error error =
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001691 ((CommandException) (ar.exception)).getCommandError();
Shishir Agrawal302c8692015-06-19 13:49:39 -07001692 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
1693 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
1694 } else if (error == CommandException.Error.GENERIC_FAILURE) {
1695 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
1696 }
1697 }
1698 cellScanResult = new CellNetworkScanResult(errorCode, null);
1699 }
1700 request.result = cellScanResult;
Pengquan Menga1bb6272018-09-06 09:59:22 -07001701 notifyRequester(request);
Shishir Agrawal302c8692015-06-19 13:49:39 -07001702 break;
1703
1704 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
1705 request = (MainThreadRequest) msg.obj;
Shishir Agrawal77ba3172015-09-10 14:50:19 -07001706 ManualNetworkSelectionArgument selArg =
1707 (ManualNetworkSelectionArgument) request.argument;
Shishir Agrawal302c8692015-06-19 13:49:39 -07001708 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
1709 request);
Shishir Agrawal77ba3172015-09-10 14:50:19 -07001710 getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
1711 selArg.persistSelection, onCompleted);
Shishir Agrawal302c8692015-06-19 13:49:39 -07001712 break;
1713
1714 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
Pengquan Menge3d01e22018-09-20 15:25:35 -07001715 ar = (AsyncResult) msg.obj;
1716 request = (MainThreadRequest) ar.userObj;
1717 if (ar.exception == null) {
1718 request.result = true;
1719 } else {
1720 request.result = false;
1721 loge("setNetworkSelectionModeManual " + ar.exception);
1722 }
1723 notifyRequester(request);
1724 mApp.onNetworkSelectionChanged(request.subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07001725 break;
1726
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001727 case CMD_GET_MODEM_ACTIVITY_INFO:
1728 request = (MainThreadRequest) msg.obj;
1729 onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
James Mattisab947702019-04-03 14:18:34 -07001730 if (defaultPhone != null) {
1731 defaultPhone.getModemActivityInfo(onCompleted, request.workSource);
Shuo Qian8f4750a2020-02-20 17:12:10 -08001732 } else {
1733 ResultReceiver result = (ResultReceiver) request.argument;
1734 Bundle bundle = new Bundle();
1735 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY,
Hall Liu49656c02020-10-09 19:00:11 -07001736 new ModemActivityInfo(0, 0, 0,
1737 new int[ModemActivityInfo.getNumTxPowerLevels()], 0));
Shuo Qian8f4750a2020-02-20 17:12:10 -08001738 result.send(0, bundle);
James Mattisab947702019-04-03 14:18:34 -07001739 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001740 break;
1741
Hall Liud0f208c2020-10-14 16:54:44 -07001742 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE: {
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001743 ar = (AsyncResult) msg.obj;
1744 request = (MainThreadRequest) ar.userObj;
Shuo Qian8f4750a2020-02-20 17:12:10 -08001745 ResultReceiver result = (ResultReceiver) request.argument;
Hall Liud0f208c2020-10-14 16:54:44 -07001746 int error = 0;
Kai Shi917fdc62022-11-28 14:01:02 -08001747 ModemActivityInfo ret = null;
Gary Jian3aa9a762022-01-24 16:41:19 +08001748 if (mLastModemActivityInfo == null) {
1749 mLastModemActivitySpecificInfo = new ActivityStatsTechSpecificInfo[1];
1750 mLastModemActivitySpecificInfo[0] =
1751 new ActivityStatsTechSpecificInfo(
1752 0,
1753 0,
1754 new int[ModemActivityInfo.getNumTxPowerLevels()],
1755 0);
1756 mLastModemActivityInfo =
1757 new ModemActivityInfo(0, 0, 0, mLastModemActivitySpecificInfo);
1758 }
1759
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001760 if (ar.exception == null && ar.result != null) {
Shuo Qian8f4750a2020-02-20 17:12:10 -08001761 // Update the last modem activity info and the result of the request.
1762 ModemActivityInfo info = (ModemActivityInfo) ar.result;
1763 if (isModemActivityInfoValid(info)) {
Gary Jian3aa9a762022-01-24 16:41:19 +08001764 mergeModemActivityInfo(info);
Gary Jian76280a42022-12-07 16:18:33 +08001765 } else {
1766 loge("queryModemActivityInfo: invalid response");
Shuo Qian8f4750a2020-02-20 17:12:10 -08001767 }
Kai Shi917fdc62022-11-28 14:01:02 -08001768 // This is needed to decouple ret from mLastModemActivityInfo
1769 // We don't want to return mLastModemActivityInfo which is updated
1770 // inside mergeModemActivityInfo()
1771 ret = new ModemActivityInfo(
1772 mLastModemActivityInfo.getTimestampMillis(),
1773 mLastModemActivityInfo.getSleepTimeMillis(),
1774 mLastModemActivityInfo.getIdleTimeMillis(),
1775 deepCopyModemActivitySpecificInfo(mLastModemActivitySpecificInfo));
Gary Jian3aa9a762022-01-24 16:41:19 +08001776
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001777 } else {
1778 if (ar.result == null) {
1779 loge("queryModemActivityInfo: Empty response");
Hall Liud0f208c2020-10-14 16:54:44 -07001780 error = TelephonyManager.ModemActivityInfoException
1781 .ERROR_INVALID_INFO_RECEIVED;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001782 } else if (ar.exception instanceof CommandException) {
Gary Jian3aa9a762022-01-24 16:41:19 +08001783 loge("queryModemActivityInfo: CommandException: " + ar.exception);
Hall Liud0f208c2020-10-14 16:54:44 -07001784 error = TelephonyManager.ModemActivityInfoException
1785 .ERROR_MODEM_RESPONSE_ERROR;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001786 } else {
1787 loge("queryModemActivityInfo: Unknown exception");
Hall Liud0f208c2020-10-14 16:54:44 -07001788 error = TelephonyManager.ModemActivityInfoException
1789 .ERROR_UNKNOWN;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001790 }
1791 }
Shuo Qian8f4750a2020-02-20 17:12:10 -08001792 Bundle bundle = new Bundle();
Kai Shi917fdc62022-11-28 14:01:02 -08001793 if (ret != null) {
Gary Jian3aa9a762022-01-24 16:41:19 +08001794 bundle.putParcelable(
1795 TelephonyManager.MODEM_ACTIVITY_RESULT_KEY,
Kai Shi917fdc62022-11-28 14:01:02 -08001796 ret);
Hall Liud0f208c2020-10-14 16:54:44 -07001797 } else {
1798 bundle.putInt(TelephonyManager.EXCEPTION_RESULT_KEY, error);
1799 }
Shuo Qian8f4750a2020-02-20 17:12:10 -08001800 result.send(0, bundle);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001801 notifyRequester(request);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001802 break;
Hall Liud0f208c2020-10-14 16:54:44 -07001803 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07001804
Sarah Chin4a9e8b82023-02-10 21:10:57 -08001805 case CMD_SET_ALLOWED_CARRIERS: {
Meng Wang1a7c35a2016-05-05 20:56:15 -07001806 request = (MainThreadRequest) msg.obj;
Michele Berionne482f8202018-11-27 18:57:59 -08001807 CarrierRestrictionRules argument =
1808 (CarrierRestrictionRules) request.argument;
Meng Wang1a7c35a2016-05-05 20:56:15 -07001809 onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
Michele Berionne482f8202018-11-27 18:57:59 -08001810 defaultPhone.setAllowedCarriers(argument, onCompleted, request.workSource);
Meng Wang1a7c35a2016-05-05 20:56:15 -07001811 break;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08001812 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07001813
1814 case EVENT_SET_ALLOWED_CARRIERS_DONE:
1815 ar = (AsyncResult) msg.obj;
1816 request = (MainThreadRequest) ar.userObj;
1817 if (ar.exception == null && ar.result != null) {
1818 request.result = ar.result;
1819 } else {
Michele Berionne482f8202018-11-27 18:57:59 -08001820 request.result = TelephonyManager.SET_CARRIER_RESTRICTION_ERROR;
1821 if (ar.exception instanceof CommandException) {
1822 loge("setAllowedCarriers: CommandException: " + ar.exception);
1823 CommandException.Error error =
1824 ((CommandException) (ar.exception)).getCommandError();
1825 if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
1826 request.result =
1827 TelephonyManager.SET_CARRIER_RESTRICTION_NOT_SUPPORTED;
1828 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07001829 } else {
1830 loge("setAllowedCarriers: Unknown exception");
1831 }
1832 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001833 notifyRequester(request);
Meng Wang1a7c35a2016-05-05 20:56:15 -07001834 break;
1835
1836 case CMD_GET_ALLOWED_CARRIERS:
1837 request = (MainThreadRequest) msg.obj;
1838 onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08001839 defaultPhone.getAllowedCarriers(onCompleted, request.workSource);
Meng Wang1a7c35a2016-05-05 20:56:15 -07001840 break;
1841
1842 case EVENT_GET_ALLOWED_CARRIERS_DONE:
1843 ar = (AsyncResult) msg.obj;
1844 request = (MainThreadRequest) ar.userObj;
1845 if (ar.exception == null && ar.result != null) {
1846 request.result = ar.result;
1847 } else {
Michele Berionne482f8202018-11-27 18:57:59 -08001848 request.result = new IllegalStateException(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001849 "Failed to get carrier restrictions");
Meng Wang1a7c35a2016-05-05 20:56:15 -07001850 if (ar.result == null) {
1851 loge("getAllowedCarriers: Empty response");
1852 } else if (ar.exception instanceof CommandException) {
1853 loge("getAllowedCarriers: CommandException: " +
1854 ar.exception);
1855 } else {
1856 loge("getAllowedCarriers: Unknown exception");
1857 }
1858 }
arunvoddud7401012022-12-15 16:08:12 +00001859 if (request.argument != null) {
1860 // This is for the implementation of carrierRestrictionStatus.
1861 CallerCallbackInfo callbackInfo = (CallerCallbackInfo) request.argument;
1862 Consumer<Integer> callback = callbackInfo.getConsumer();
1863 int callerCarrierId = callbackInfo.getCarrierId();
1864 int lockStatus = TelephonyManager.CARRIER_RESTRICTION_STATUS_UNKNOWN;
1865 if (ar.exception == null && ar.result instanceof CarrierRestrictionRules) {
1866 CarrierRestrictionRules carrierRestrictionRules =
1867 (CarrierRestrictionRules) ar.result;
1868 int carrierId = -1;
1869 try {
1870 CarrierIdentifier carrierIdentifier =
1871 carrierRestrictionRules.getAllowedCarriers().get(0);
1872 carrierId = CarrierResolver.getCarrierIdFromIdentifier(mApp,
1873 carrierIdentifier);
1874 } catch (NullPointerException | IndexOutOfBoundsException ex) {
1875 Rlog.e(LOG_TAG, "CarrierIdentifier exception = " + ex);
1876 }
1877 lockStatus = carrierRestrictionRules.getCarrierRestrictionStatus();
1878 if (carrierId != -1 && callerCarrierId == carrierId && lockStatus
1879 == TelephonyManager.CARRIER_RESTRICTION_STATUS_RESTRICTED) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001880 lockStatus = TelephonyManager
1881 .CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER;
arunvoddud7401012022-12-15 16:08:12 +00001882 }
1883 } else {
1884 Rlog.e(LOG_TAG,
1885 "getCarrierRestrictionStatus: exception ex = " + ar.exception);
1886 }
1887 callback.accept(lockStatus);
1888 } else {
1889 // This is for the implementation of getAllowedCarriers.
1890 notifyRequester(request);
1891 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07001892 break;
1893
Nathan Haroldb3014052017-01-25 15:57:32 -08001894 case EVENT_GET_FORBIDDEN_PLMNS_DONE:
1895 ar = (AsyncResult) msg.obj;
1896 request = (MainThreadRequest) ar.userObj;
1897 if (ar.exception == null && ar.result != null) {
1898 request.result = ar.result;
1899 } else {
1900 request.result = new IllegalArgumentException(
1901 "Failed to retrieve Forbidden Plmns");
1902 if (ar.result == null) {
1903 loge("getForbiddenPlmns: Empty response");
1904 } else {
1905 loge("getForbiddenPlmns: Unknown exception");
1906 }
1907 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001908 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -08001909 break;
1910
1911 case CMD_GET_FORBIDDEN_PLMNS:
1912 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001913 uiccPort = getUiccPortFromRequest(request);
1914 if (uiccPort == null) {
1915 loge("getForbiddenPlmns() UiccPort is null");
Nathan Haroldb3014052017-01-25 15:57:32 -08001916 request.result = new IllegalArgumentException(
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001917 "getForbiddenPlmns() UiccPort is null");
Pengquan Menga1bb6272018-09-06 09:59:22 -07001918 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -08001919 break;
1920 }
1921 Integer appType = (Integer) request.argument;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00001922 UiccCardApplication uiccApp = uiccPort.getApplicationByType(appType);
Nathan Haroldb3014052017-01-25 15:57:32 -08001923 if (uiccApp == null) {
1924 loge("getForbiddenPlmns() no app with specified type -- "
1925 + appType);
1926 request.result = new IllegalArgumentException("Failed to get UICC App");
Pengquan Menga1bb6272018-09-06 09:59:22 -07001927 notifyRequester(request);
Nathan Haroldb3014052017-01-25 15:57:32 -08001928 break;
1929 } else {
1930 if (DBG) logv("getForbiddenPlmns() found app " + uiccApp.getAid()
1931 + " specified type -- " + appType);
1932 }
1933 onCompleted = obtainMessage(EVENT_GET_FORBIDDEN_PLMNS_DONE, request);
1934 ((SIMRecords) uiccApp.getIccRecords()).getForbiddenPlmns(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08001935 onCompleted);
Nathan Haroldb3014052017-01-25 15:57:32 -08001936 break;
1937
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001938 case CMD_SWITCH_SLOTS:
1939 request = (MainThreadRequest) msg.obj;
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00001940 List<UiccSlotMapping> slotMapping = (List<UiccSlotMapping>) request.argument;
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001941 onCompleted = obtainMessage(EVENT_SWITCH_SLOTS_DONE, request);
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00001942 UiccController.getInstance().switchSlots(slotMapping, onCompleted);
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001943 break;
1944
1945 case EVENT_SWITCH_SLOTS_DONE:
1946 ar = (AsyncResult) msg.obj;
1947 request = (MainThreadRequest) ar.userObj;
1948 request.result = (ar.exception == null);
Pengquan Menga1bb6272018-09-06 09:59:22 -07001949 notifyRequester(request);
1950 break;
1951 case CMD_GET_NETWORK_SELECTION_MODE:
1952 request = (MainThreadRequest) msg.obj;
1953 onCompleted = obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, request);
1954 getPhoneFromRequest(request).getNetworkSelectionMode(onCompleted);
1955 break;
1956
1957 case EVENT_GET_NETWORK_SELECTION_MODE_DONE:
1958 ar = (AsyncResult) msg.obj;
1959 request = (MainThreadRequest) ar.userObj;
1960 if (ar.exception != null) {
1961 request.result = TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
1962 } else {
1963 int mode = ((int[]) ar.result)[0];
1964 if (mode == 0) {
1965 request.result = TelephonyManager.NETWORK_SELECTION_MODE_AUTO;
1966 } else {
1967 request.result = TelephonyManager.NETWORK_SELECTION_MODE_MANUAL;
1968 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00001969 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07001970 notifyRequester(request);
1971 break;
1972 case CMD_GET_CDMA_ROAMING_MODE:
1973 request = (MainThreadRequest) msg.obj;
1974 onCompleted = obtainMessage(EVENT_GET_CDMA_ROAMING_MODE_DONE, request);
1975 getPhoneFromRequest(request).queryCdmaRoamingPreference(onCompleted);
1976 break;
1977 case EVENT_GET_CDMA_ROAMING_MODE_DONE:
1978 ar = (AsyncResult) msg.obj;
1979 request = (MainThreadRequest) ar.userObj;
1980 if (ar.exception != null) {
1981 request.result = TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT;
1982 } else {
1983 request.result = ((int[]) ar.result)[0];
1984 }
1985 notifyRequester(request);
1986 break;
1987 case CMD_SET_CDMA_ROAMING_MODE:
1988 request = (MainThreadRequest) msg.obj;
1989 onCompleted = obtainMessage(EVENT_SET_CDMA_ROAMING_MODE_DONE, request);
1990 int mode = (int) request.argument;
1991 getPhoneFromRequest(request).setCdmaRoamingPreference(mode, onCompleted);
1992 break;
1993 case EVENT_SET_CDMA_ROAMING_MODE_DONE:
1994 ar = (AsyncResult) msg.obj;
1995 request = (MainThreadRequest) ar.userObj;
1996 request.result = ar.exception == null;
1997 notifyRequester(request);
1998 break;
Sarah Chinbaab1432020-10-28 13:46:24 -07001999 case CMD_GET_CDMA_SUBSCRIPTION_MODE:
2000 request = (MainThreadRequest) msg.obj;
2001 onCompleted = obtainMessage(EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE, request);
2002 getPhoneFromRequest(request).queryCdmaSubscriptionMode(onCompleted);
2003 break;
2004 case EVENT_GET_CDMA_SUBSCRIPTION_MODE_DONE:
2005 ar = (AsyncResult) msg.obj;
2006 request = (MainThreadRequest) ar.userObj;
2007 if (ar.exception != null) {
2008 request.result = TelephonyManager.CDMA_SUBSCRIPTION_RUIM_SIM;
2009 } else {
2010 request.result = ((int[]) ar.result)[0];
2011 }
2012 notifyRequester(request);
2013 break;
Pengquan Menga1bb6272018-09-06 09:59:22 -07002014 case CMD_SET_CDMA_SUBSCRIPTION_MODE:
2015 request = (MainThreadRequest) msg.obj;
2016 onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE, request);
2017 int subscriptionMode = (int) request.argument;
Sarah Chinbaab1432020-10-28 13:46:24 -07002018 getPhoneFromRequest(request).setCdmaSubscriptionMode(
2019 subscriptionMode, onCompleted);
Pengquan Menga1bb6272018-09-06 09:59:22 -07002020 break;
2021 case EVENT_SET_CDMA_SUBSCRIPTION_MODE_DONE:
2022 ar = (AsyncResult) msg.obj;
2023 request = (MainThreadRequest) ar.userObj;
2024 request.result = ar.exception == null;
2025 notifyRequester(request);
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00002026 break;
Nathan Harold3ff88932018-08-14 10:19:49 -07002027 case CMD_GET_ALL_CELL_INFO:
2028 request = (MainThreadRequest) msg.obj;
Nathan Harold3ff88932018-08-14 10:19:49 -07002029 onCompleted = obtainMessage(EVENT_GET_ALL_CELL_INFO_DONE, request);
Nathan Harold92bed182018-10-12 18:16:49 -07002030 request.phone.requestCellInfoUpdate(request.workSource, onCompleted);
Nathan Harold3ff88932018-08-14 10:19:49 -07002031 break;
Nathan Harold3ff88932018-08-14 10:19:49 -07002032 case EVENT_GET_ALL_CELL_INFO_DONE:
2033 ar = (AsyncResult) msg.obj;
2034 request = (MainThreadRequest) ar.userObj;
Nathan Harold8d0f1742018-10-02 12:14:47 -07002035 // If a timeout occurs, the response will be null
2036 request.result = (ar.exception == null && ar.result != null)
2037 ? ar.result : new ArrayList<CellInfo>();
Nathan Harold3ff88932018-08-14 10:19:49 -07002038 synchronized (request) {
2039 request.notifyAll();
2040 }
2041 break;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002042 case CMD_REQUEST_CELL_INFO_UPDATE:
2043 request = (MainThreadRequest) msg.obj;
2044 request.phone.requestCellInfoUpdate(request.workSource,
2045 obtainMessage(EVENT_REQUEST_CELL_INFO_UPDATE_DONE, request));
2046 break;
2047 case EVENT_REQUEST_CELL_INFO_UPDATE_DONE:
2048 ar = (AsyncResult) msg.obj;
2049 request = (MainThreadRequest) ar.userObj;
2050 ICellInfoCallback cb = (ICellInfoCallback) request.argument;
2051 try {
2052 if (ar.exception != null) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002053 Log.e(LOG_TAG, "Exception retrieving CellInfo=" + ar.exception);
Meng Wangd8921f42019-09-30 17:13:54 -07002054 cb.onError(
2055 TelephonyManager.CellInfoCallback.ERROR_MODEM_ERROR,
2056 ar.exception.getClass().getName(),
2057 ar.exception.toString());
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002058 } else if (ar.result == null) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002059 Log.w(LOG_TAG, "Timeout Waiting for CellInfo!");
Meng Wangd8921f42019-09-30 17:13:54 -07002060 cb.onError(TelephonyManager.CellInfoCallback.ERROR_TIMEOUT, null, null);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07002061 } else {
2062 // use the result as returned
2063 cb.onCellInfo((List<CellInfo>) ar.result);
2064 }
2065 } catch (RemoteException re) {
2066 Log.w(LOG_TAG, "Discarded CellInfo due to Callback RemoteException");
2067 }
2068 break;
Sarah Chin679c08a2020-11-18 13:39:35 -08002069 case CMD_GET_CELL_LOCATION: {
Nathan Harold3ff88932018-08-14 10:19:49 -07002070 request = (MainThreadRequest) msg.obj;
2071 WorkSource ws = (WorkSource) request.argument;
2072 Phone phone = getPhoneFromRequest(request);
Meng Wanga10e89e2019-12-09 13:13:01 -08002073 phone.getCellIdentity(ws, obtainMessage(EVENT_GET_CELL_LOCATION_DONE, request));
Nathan Harold3ff88932018-08-14 10:19:49 -07002074 break;
Sarah Chin679c08a2020-11-18 13:39:35 -08002075 }
2076 case EVENT_GET_CELL_LOCATION_DONE: {
Nathan Harold3ff88932018-08-14 10:19:49 -07002077 ar = (AsyncResult) msg.obj;
2078 request = (MainThreadRequest) ar.userObj;
2079 if (ar.exception == null) {
2080 request.result = ar.result;
2081 } else {
Sarah Chin679c08a2020-11-18 13:39:35 -08002082 Phone phone = getPhoneFromRequest(request);
Nathan Harold3ff88932018-08-14 10:19:49 -07002083 request.result = (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
Meng Wanga10e89e2019-12-09 13:13:01 -08002084 ? new CellIdentityCdma() : new CellIdentityGsm();
Nathan Harold3ff88932018-08-14 10:19:49 -07002085 }
2086
2087 synchronized (request) {
2088 request.notifyAll();
2089 }
2090 break;
Sarah Chin679c08a2020-11-18 13:39:35 -08002091 }
chen xu6dac5ab2018-10-26 17:39:23 -07002092 case CMD_MODEM_REBOOT:
2093 request = (MainThreadRequest) msg.obj;
2094 onCompleted = obtainMessage(EVENT_RESET_MODEM_CONFIG_DONE, request);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08002095 defaultPhone.rebootModem(onCompleted);
chen xu6dac5ab2018-10-26 17:39:23 -07002096 break;
chen xu6dac5ab2018-10-26 17:39:23 -07002097 case EVENT_CMD_MODEM_REBOOT_DONE:
2098 handleNullReturnEvent(msg, "rebootModem");
2099 break;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002100 case CMD_REQUEST_ENABLE_MODEM: {
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002101 request = (MainThreadRequest) msg.obj;
2102 boolean enable = (boolean) request.argument;
2103 onCompleted = obtainMessage(EVENT_ENABLE_MODEM_DONE, request);
Nazanin Bakhshi33d584b2019-02-27 10:44:32 -08002104 onCompleted.arg1 = enable ? 1 : 0;
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002105 PhoneConfigurationManager.getInstance()
2106 .enablePhone(request.phone, enable, onCompleted);
2107 break;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002108 }
Michele Berionne5e411512020-11-13 02:36:59 +00002109 case EVENT_ENABLE_MODEM_DONE: {
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002110 ar = (AsyncResult) msg.obj;
2111 request = (MainThreadRequest) ar.userObj;
2112 request.result = (ar.exception == null);
Nazanin Bakhshif71371d2019-04-29 17:29:44 -07002113 int phoneId = request.phone.getPhoneId();
Nazanin Bakhshi33d584b2019-02-27 10:44:32 -08002114 //update the cache as modem status has changed
Nazanin Bakhshif71371d2019-04-29 17:29:44 -07002115 if ((boolean) request.result) {
2116 mPhoneConfigurationManager.addToPhoneStatusCache(phoneId, msg.arg1 == 1);
2117 updateModemStateMetrics();
2118 } else {
2119 Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
2120 + ar.exception);
2121 }
2122 notifyRequester(request);
2123 break;
Michele Berionne5e411512020-11-13 02:36:59 +00002124 }
Nazanin Bakhshif71371d2019-04-29 17:29:44 -07002125 case CMD_GET_MODEM_STATUS:
2126 request = (MainThreadRequest) msg.obj;
2127 onCompleted = obtainMessage(EVENT_GET_MODEM_STATUS_DONE, request);
2128 PhoneConfigurationManager.getInstance()
2129 .getPhoneStatusFromModem(request.phone, onCompleted);
2130 break;
2131 case EVENT_GET_MODEM_STATUS_DONE:
2132 ar = (AsyncResult) msg.obj;
2133 request = (MainThreadRequest) ar.userObj;
2134 int id = request.phone.getPhoneId();
2135 if (ar.exception == null && ar.result != null) {
2136 request.result = ar.result;
2137 //update the cache as modem status has changed
2138 mPhoneConfigurationManager.addToPhoneStatusCache(id,
2139 (boolean) request.result);
2140 } else {
2141 // Return true if modem status cannot be retrieved. For most cases,
2142 // modem status is on. And for older version modems, GET_MODEM_STATUS
2143 // and disable modem are not supported. Modem is always on.
2144 // TODO: this should be fixed in R to support a third
2145 // status UNKNOWN b/131631629
2146 request.result = true;
2147 Log.e(LOG_TAG, msg.what + " failure. Not updating modem status."
2148 + ar.exception);
2149 }
Malcolm Chen8e4ed912019-01-15 20:22:16 -08002150 notifyRequester(request);
2151 break;
Hall Liu73f5d362020-01-20 13:42:00 -08002152 case CMD_SET_SYSTEM_SELECTION_CHANNELS: {
2153 request = (MainThreadRequest) msg.obj;
2154 onCompleted = obtainMessage(EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE, request);
2155 Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> args =
2156 (Pair<List<RadioAccessSpecifier>, Consumer<Boolean>>) request.argument;
2157 request.phone.setSystemSelectionChannels(args.first, onCompleted);
2158 break;
2159 }
2160 case EVENT_SET_SYSTEM_SELECTION_CHANNELS_DONE: {
2161 ar = (AsyncResult) msg.obj;
2162 request = (MainThreadRequest) ar.userObj;
2163 Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> args =
2164 (Pair<List<RadioAccessSpecifier>, Consumer<Boolean>>) request.argument;
2165 args.second.accept(ar.exception == null);
2166 notifyRequester(request);
2167 break;
2168 }
Sarah Chin679c08a2020-11-18 13:39:35 -08002169 case CMD_GET_SYSTEM_SELECTION_CHANNELS: {
2170 request = (MainThreadRequest) msg.obj;
2171 onCompleted = obtainMessage(EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE, request);
2172 Phone phone = getPhoneFromRequest(request);
2173 if (phone != null) {
2174 phone.getSystemSelectionChannels(onCompleted);
2175 } else {
2176 loge("getSystemSelectionChannels: No phone object");
2177 request.result = new ArrayList<RadioAccessSpecifier>();
2178 notifyRequester(request);
2179 }
2180 break;
2181 }
2182 case EVENT_GET_SYSTEM_SELECTION_CHANNELS_DONE:
2183 ar = (AsyncResult) msg.obj;
2184 request = (MainThreadRequest) ar.userObj;
2185 if (ar.exception == null && ar.result != null) {
2186 request.result = ar.result;
2187 } else {
Sarah Chin428d1d62021-03-13 03:17:40 -08002188 request.result = new IllegalStateException(
2189 "Failed to retrieve system selecton channels");
Sarah Chin679c08a2020-11-18 13:39:35 -08002190 if (ar.result == null) {
2191 loge("getSystemSelectionChannels: Empty response");
2192 } else {
2193 loge("getSystemSelectionChannels: Unknown exception");
2194 }
2195 }
2196 notifyRequester(request);
2197 break;
yincheng zhao2737e882019-09-06 17:06:54 -07002198 case EVENT_SET_FORBIDDEN_PLMNS_DONE:
2199 ar = (AsyncResult) msg.obj;
2200 request = (MainThreadRequest) ar.userObj;
2201 if (ar.exception == null && ar.result != null) {
2202 request.result = ar.result;
2203 } else {
2204 request.result = -1;
2205 loge("Failed to set Forbidden Plmns");
2206 if (ar.result == null) {
2207 loge("setForbidenPlmns: Empty response");
2208 } else if (ar.exception != null) {
2209 loge("setForbiddenPlmns: Exception: " + ar.exception);
2210 request.result = -1;
2211 } else {
2212 loge("setForbiddenPlmns: Unknown exception");
2213 }
2214 }
2215 notifyRequester(request);
2216 break;
2217 case CMD_SET_FORBIDDEN_PLMNS:
2218 request = (MainThreadRequest) msg.obj;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00002219 uiccPort = getUiccPortFromRequest(request);
2220 if (uiccPort == null) {
2221 loge("setForbiddenPlmns: UiccPort is null");
yincheng zhao2737e882019-09-06 17:06:54 -07002222 request.result = -1;
2223 notifyRequester(request);
2224 break;
2225 }
2226 Pair<Integer, List<String>> setFplmnsArgs =
2227 (Pair<Integer, List<String>>) request.argument;
2228 appType = setFplmnsArgs.first;
2229 List<String> fplmns = setFplmnsArgs.second;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00002230 uiccApp = uiccPort.getApplicationByType(appType);
yincheng zhao2737e882019-09-06 17:06:54 -07002231 if (uiccApp == null) {
2232 loge("setForbiddenPlmns: no app with specified type -- " + appType);
2233 request.result = -1;
2234 loge("Failed to get UICC App");
2235 notifyRequester(request);
2236 } else {
2237 onCompleted = obtainMessage(EVENT_SET_FORBIDDEN_PLMNS_DONE, request);
2238 ((SIMRecords) uiccApp.getIccRecords())
2239 .setForbiddenPlmns(onCompleted, fplmns);
2240 }
yinchengzhao4d163c02019-12-12 15:21:47 -08002241 break;
Naina Nallurid63128d2019-09-17 14:10:30 -07002242 case CMD_ERASE_MODEM_CONFIG:
2243 request = (MainThreadRequest) msg.obj;
2244 onCompleted = obtainMessage(EVENT_ERASE_MODEM_CONFIG_DONE, request);
2245 defaultPhone.eraseModemConfig(onCompleted);
2246 break;
2247 case EVENT_ERASE_MODEM_CONFIG_DONE:
2248 handleNullReturnEvent(msg, "eraseModemConfig");
yincheng zhao2737e882019-09-06 17:06:54 -07002249 break;
zoey chene02881a2019-12-30 16:11:23 +08002250
Kai Shif70f46f2021-03-03 13:59:46 -08002251 case CMD_ERASE_DATA_SHARED_PREFERENCES:
2252 request = (MainThreadRequest) msg.obj;
2253 request.result = defaultPhone.eraseDataInSharedPreferences();
2254 notifyRequester(request);
2255 break;
2256
zoey chene02881a2019-12-30 16:11:23 +08002257 case CMD_CHANGE_ICC_LOCK_PASSWORD:
2258 request = (MainThreadRequest) msg.obj;
2259 onCompleted = obtainMessage(EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE, request);
2260 Pair<String, String> changed = (Pair<String, String>) request.argument;
2261 getPhoneFromRequest(request).getIccCard().changeIccLockPassword(
2262 changed.first, changed.second, onCompleted);
2263 break;
2264 case EVENT_CHANGE_ICC_LOCK_PASSWORD_DONE:
2265 ar = (AsyncResult) msg.obj;
2266 request = (MainThreadRequest) ar.userObj;
2267 if (ar.exception == null) {
2268 request.result = TelephonyManager.CHANGE_ICC_LOCK_SUCCESS;
Michele Berionne5e411512020-11-13 02:36:59 +00002269 // If the operation is successful, update the PIN storage
2270 Pair<String, String> passwords = (Pair<String, String>) request.argument;
2271 int phoneId = getPhoneFromRequest(request).getPhoneId();
Jon Spivack9c3bc762021-10-06 20:53:09 +00002272 UiccController.getInstance().getPinStorage()
2273 .storePin(passwords.second, phoneId);
zoey chene02881a2019-12-30 16:11:23 +08002274 } else {
2275 request.result = msg.arg1;
2276 }
2277 notifyRequester(request);
2278 break;
2279
Michele Berionne5e411512020-11-13 02:36:59 +00002280 case CMD_SET_ICC_LOCK_ENABLED: {
zoey chene02881a2019-12-30 16:11:23 +08002281 request = (MainThreadRequest) msg.obj;
2282 onCompleted = obtainMessage(EVENT_SET_ICC_LOCK_ENABLED_DONE, request);
2283 Pair<Boolean, String> enabled = (Pair<Boolean, String>) request.argument;
2284 getPhoneFromRequest(request).getIccCard().setIccLockEnabled(
2285 enabled.first, enabled.second, onCompleted);
2286 break;
Michele Berionne5e411512020-11-13 02:36:59 +00002287 }
zoey chene02881a2019-12-30 16:11:23 +08002288 case EVENT_SET_ICC_LOCK_ENABLED_DONE:
2289 ar = (AsyncResult) msg.obj;
2290 request = (MainThreadRequest) ar.userObj;
2291 if (ar.exception == null) {
2292 request.result = TelephonyManager.CHANGE_ICC_LOCK_SUCCESS;
Michele Berionne5e411512020-11-13 02:36:59 +00002293 // If the operation is successful, update the PIN storage
2294 Pair<Boolean, String> enabled = (Pair<Boolean, String>) request.argument;
2295 int phoneId = getPhoneFromRequest(request).getPhoneId();
2296 if (enabled.first) {
Jon Spivack9c3bc762021-10-06 20:53:09 +00002297 UiccController.getInstance().getPinStorage()
2298 .storePin(enabled.second, phoneId);
Michele Berionne5e411512020-11-13 02:36:59 +00002299 } else {
2300 UiccController.getInstance().getPinStorage().clearPin(phoneId);
2301 }
zoey chene02881a2019-12-30 16:11:23 +08002302 } else {
2303 request.result = msg.arg1;
2304 }
Michele Berionne5e411512020-11-13 02:36:59 +00002305
2306
zoey chene02881a2019-12-30 16:11:23 +08002307 notifyRequester(request);
2308 break;
2309
Peter Wangdafb9ac2020-01-15 14:13:38 -08002310 case MSG_NOTIFY_USER_ACTIVITY:
2311 removeMessages(MSG_NOTIFY_USER_ACTIVITY);
Peter Wang59571be2020-01-27 12:35:15 +08002312 Intent intent = new Intent(TelephonyIntents.ACTION_USER_ACTIVITY_NOTIFICATION);
Peter Wangdafb9ac2020-01-15 14:13:38 -08002313 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2314 getDefaultPhone().getContext().sendBroadcastAsUser(
2315 intent, UserHandle.ALL, permission.USER_ACTIVITY);
2316 break;
Jack Nudelmanb0b87642020-11-12 15:04:39 -08002317
2318 case CMD_SET_DATA_THROTTLING: {
2319 request = (MainThreadRequest) msg.obj;
2320 onCompleted = obtainMessage(EVENT_SET_DATA_THROTTLING_DONE, request);
2321 DataThrottlingRequest dataThrottlingRequest =
2322 (DataThrottlingRequest) request.argument;
2323 Phone phone = getPhoneFromRequest(request);
2324 if (phone != null) {
2325 phone.setDataThrottling(onCompleted,
2326 request.workSource, dataThrottlingRequest.getDataThrottlingAction(),
2327 dataThrottlingRequest.getCompletionDurationMillis());
2328 } else {
2329 loge("setDataThrottling: No phone object");
2330 request.result =
2331 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
2332 notifyRequester(request);
2333 }
2334
2335 break;
2336 }
2337 case EVENT_SET_DATA_THROTTLING_DONE:
2338 ar = (AsyncResult) msg.obj;
2339 request = (MainThreadRequest) ar.userObj;
2340
2341 if (ar.exception == null) {
2342 request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
2343 } else if (ar.exception instanceof CommandException) {
2344 loge("setDataThrottling: CommandException: " + ar.exception);
2345 CommandException.Error error =
2346 ((CommandException) (ar.exception)).getCommandError();
2347
2348 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
2349 request.result = TelephonyManager
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002350 .THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -08002351 } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
2352 request.result = SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS;
Jack Nudelman5d6a98b2021-03-04 14:26:25 -08002353 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
2354 request.result = MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -08002355 } else {
2356 request.result =
2357 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
2358 }
2359 } else {
2360 request.result = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
2361 }
2362 Log.w(LOG_TAG, "DataThrottlingResult = " + request.result);
2363 notifyRequester(request);
2364 break;
Jordan Liu109698e2020-11-24 14:50:34 -08002365
2366 case CMD_SET_SIM_POWER: {
2367 request = (MainThreadRequest) msg.obj;
2368 onCompleted = obtainMessage(EVENT_SET_SIM_POWER_DONE, request);
2369 request = (MainThreadRequest) msg.obj;
2370 int stateToSet =
2371 ((Pair<Integer, IIntegerConsumer>)
2372 request.argument).first;
2373 request.phone.setSimPowerState(stateToSet, onCompleted, request.workSource);
2374 break;
2375 }
2376 case EVENT_SET_SIM_POWER_DONE: {
2377 ar = (AsyncResult) msg.obj;
2378 request = (MainThreadRequest) ar.userObj;
2379 IIntegerConsumer callback =
2380 ((Pair<Integer, IIntegerConsumer>) request.argument).second;
2381 if (ar.exception != null) {
2382 loge("setSimPower exception: " + ar.exception);
2383 int errorCode = TelephonyManager.CallForwardingInfoCallback
2384 .RESULT_ERROR_UNKNOWN;
2385 if (ar.exception instanceof CommandException) {
2386 CommandException.Error error =
2387 ((CommandException) (ar.exception)).getCommandError();
2388 if (error == CommandException.Error.SIM_ERR) {
2389 errorCode = TelephonyManager.SET_SIM_POWER_STATE_SIM_ERROR;
2390 } else if (error == CommandException.Error.INVALID_ARGUMENTS) {
2391 errorCode = TelephonyManager.SET_SIM_POWER_STATE_ALREADY_IN_STATE;
2392 } else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
2393 errorCode = TelephonyManager.SET_SIM_POWER_STATE_NOT_SUPPORTED;
2394 } else {
2395 errorCode = TelephonyManager.SET_SIM_POWER_STATE_MODEM_ERROR;
2396 }
2397 }
2398 try {
2399 callback.accept(errorCode);
2400 } catch (RemoteException e) {
2401 // Ignore if the remote process is no longer available to call back.
2402 Log.w(LOG_TAG, "setSimPower: callback not available.");
2403 }
2404 } else {
2405 try {
2406 callback.accept(TelephonyManager.SET_SIM_POWER_STATE_SUCCESS);
2407 } catch (RemoteException e) {
2408 // Ignore if the remote process is no longer available to call back.
2409 Log.w(LOG_TAG, "setSimPower: callback not available.");
2410 }
2411 }
2412 break;
2413 }
Rambo Wanga5cc9b72021-01-07 10:51:54 -08002414 case CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST: {
2415 request = (MainThreadRequest) msg.obj;
2416
2417 final Phone phone = getPhoneFromRequest(request);
2418 if (phone == null || phone.getServiceStateTracker() == null) {
2419 request.result = new IllegalStateException("Phone or SST is null");
2420 notifyRequester(request);
2421 break;
2422 }
2423
2424 Pair<Integer, SignalStrengthUpdateRequest> pair =
2425 (Pair<Integer, SignalStrengthUpdateRequest>) request.argument;
2426 onCompleted = obtainMessage(EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
2427 request);
Rambo Wang6568f172021-02-03 16:56:47 -08002428 phone.getSignalStrengthController().setSignalStrengthUpdateRequest(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002429 request.subId, pair.first /*callingUid*/,
2430 pair.second /*request*/, onCompleted);
Rambo Wanga5cc9b72021-01-07 10:51:54 -08002431 break;
2432 }
2433 case EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
2434 ar = (AsyncResult) msg.obj;
2435 request = (MainThreadRequest) ar.userObj;
2436 // request.result will be the exception of ar if present, true otherwise.
2437 // Be cautious not to leave result null which will wait() forever
2438 request.result = ar.exception != null ? ar.exception : true;
2439 notifyRequester(request);
2440 break;
2441 }
2442 case CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST: {
2443 request = (MainThreadRequest) msg.obj;
2444
2445 Phone phone = getPhoneFromRequest(request);
2446 if (phone == null || phone.getServiceStateTracker() == null) {
2447 request.result = new IllegalStateException("Phone or SST is null");
2448 notifyRequester(request);
2449 break;
2450 }
2451
2452 Pair<Integer, SignalStrengthUpdateRequest> pair =
2453 (Pair<Integer, SignalStrengthUpdateRequest>) request.argument;
2454 onCompleted = obtainMessage(EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
2455 request);
Rambo Wang6568f172021-02-03 16:56:47 -08002456 phone.getSignalStrengthController().clearSignalStrengthUpdateRequest(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002457 request.subId, pair.first /*callingUid*/,
2458 pair.second /*request*/, onCompleted);
Rambo Wanga5cc9b72021-01-07 10:51:54 -08002459 break;
2460 }
2461 case EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
2462 ar = (AsyncResult) msg.obj;
2463 request = (MainThreadRequest) ar.userObj;
2464 request.result = ar.exception != null ? ar.exception : true;
2465 notifyRequester(request);
2466 break;
2467 }
Jordan Liu109698e2020-11-24 14:50:34 -08002468
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002469 case CMD_GET_SLICING_CONFIG: {
2470 request = (MainThreadRequest) msg.obj;
2471 onCompleted = obtainMessage(EVENT_GET_SLICING_CONFIG_DONE, request);
2472 request.phone.getSlicingConfig(onCompleted);
2473 break;
2474 }
2475 case EVENT_GET_SLICING_CONFIG_DONE: {
2476 ar = (AsyncResult) msg.obj;
2477 request = (MainThreadRequest) ar.userObj;
2478 ResultReceiver result = (ResultReceiver) request.argument;
2479
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002480 NetworkSlicingConfig slicingConfig = null;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002481 Bundle bundle = new Bundle();
2482 int resultCode = 0;
2483 if (ar.exception != null) {
2484 Log.e(LOG_TAG, "Exception retrieving slicing configuration="
2485 + ar.exception);
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002486 resultCode = TelephonyManager.NetworkSlicingException.ERROR_MODEM_ERROR;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002487 } else if (ar.result == null) {
2488 Log.w(LOG_TAG, "Timeout Waiting for slicing configuration!");
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002489 resultCode = TelephonyManager.NetworkSlicingException.ERROR_TIMEOUT;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002490 } else {
2491 // use the result as returned
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002492 resultCode = TelephonyManager.NetworkSlicingException.SUCCESS;
2493 slicingConfig = (NetworkSlicingConfig) ar.result;
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002494 }
2495
2496 if (slicingConfig == null) {
Hongbo Zeng0e18b162021-04-07 16:52:18 +08002497 slicingConfig = new NetworkSlicingConfig();
Hongbo Zeng156aa4a2021-02-08 21:50:28 +08002498 }
2499 bundle.putParcelable(TelephonyManager.KEY_SLICING_CONFIG_HANDLE, slicingConfig);
2500 result.send(resultCode, bundle);
2501 notifyRequester(request);
2502 break;
2503 }
2504
Sarah Chin71b3a852022-09-28 15:54:19 -07002505 case CMD_PURCHASE_PREMIUM_CAPABILITY: {
Sarah Chin2ec39f62022-08-31 17:03:26 -07002506 request = (MainThreadRequest) msg.obj;
2507 onCompleted = obtainMessage(EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE, request);
Sarah Chin71b3a852022-09-28 15:54:19 -07002508 PurchasePremiumCapabilityArgument arg =
2509 (PurchasePremiumCapabilityArgument) request.argument;
Sarah Chin46355ba2022-11-01 23:51:16 -07002510 SlicePurchaseController.getInstance(request.phone).purchasePremiumCapability(
Sarah Chinb8218c22023-01-04 13:35:29 -08002511 arg.capability, onCompleted);
Sarah Chin2ec39f62022-08-31 17:03:26 -07002512 break;
Sarah Chin71b3a852022-09-28 15:54:19 -07002513 }
Sarah Chin2ec39f62022-08-31 17:03:26 -07002514
Sarah Chin71b3a852022-09-28 15:54:19 -07002515 case EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE: {
Sarah Chin2ec39f62022-08-31 17:03:26 -07002516 ar = (AsyncResult) msg.obj;
2517 request = (MainThreadRequest) ar.userObj;
Sarah Chin71b3a852022-09-28 15:54:19 -07002518 PurchasePremiumCapabilityArgument arg =
2519 (PurchasePremiumCapabilityArgument) request.argument;
Sarah Chin2ec39f62022-08-31 17:03:26 -07002520 try {
2521 int result = (int) ar.result;
Sarah Chin71b3a852022-09-28 15:54:19 -07002522 arg.callback.accept(result);
Sarah Chin2ec39f62022-08-31 17:03:26 -07002523 log("purchasePremiumCapability: capability="
Sarah Chin71b3a852022-09-28 15:54:19 -07002524 + TelephonyManager.convertPremiumCapabilityToString(arg.capability)
Sarah Chin2ec39f62022-08-31 17:03:26 -07002525 + ", result= "
2526 + TelephonyManager.convertPurchaseResultToString(result));
2527 } catch (RemoteException e) {
2528 String logStr = "Purchase premium capability "
Sarah Chin71b3a852022-09-28 15:54:19 -07002529 + TelephonyManager.convertPremiumCapabilityToString(arg.capability)
Sarah Chin2ec39f62022-08-31 17:03:26 -07002530 + " failed: " + e;
2531 if (DBG) log(logStr);
2532 AnomalyReporter.reportAnomaly(
2533 UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
2534 }
2535 break;
Sarah Chin71b3a852022-09-28 15:54:19 -07002536 }
Sarah Chin2ec39f62022-08-31 17:03:26 -07002537
Michele Berionne5e411512020-11-13 02:36:59 +00002538 case CMD_PREPARE_UNATTENDED_REBOOT:
2539 request = (MainThreadRequest) msg.obj;
2540 request.result =
Rafael Higuera Silvad9630642021-09-20 15:32:01 +00002541 UiccController.getInstance().getPinStorage()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002542 .prepareUnattendedReboot(request.workSource);
Michele Berionne5e411512020-11-13 02:36:59 +00002543 notifyRequester(request);
2544 break;
2545
Sarah Chineccfbd12023-01-20 19:00:35 -08002546 case CMD_START_SATELLITE_POSITION_UPDATES: {
2547 request = (MainThreadRequest) msg.obj;
2548 onCompleted =
2549 obtainMessage(EVENT_START_SATELLITE_POSITION_UPDATES_DONE, request);
2550 Phone phone = getPhoneFromRequest(request);
2551 if (phone != null) {
2552 phone.startSatellitePositionUpdates(onCompleted);
2553 } else {
2554 loge("startSatellitePositionUpdates: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002555 ((Consumer<Integer>) request.argument).accept(
2556 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Sarah Chineccfbd12023-01-20 19:00:35 -08002557 }
2558 break;
2559 }
2560
2561 case EVENT_START_SATELLITE_POSITION_UPDATES_DONE: {
2562 ar = (AsyncResult) msg.obj;
2563 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002564 int error = getSatelliteError(ar, "startSatellitePositionUpdates", false);
2565 ((Consumer<Integer>) request.argument).accept(error);
Sarah Chineccfbd12023-01-20 19:00:35 -08002566 break;
2567 }
2568
2569 case CMD_STOP_SATELLITE_POSITION_UPDATES: {
2570 request = (MainThreadRequest) msg.obj;
2571 onCompleted =
2572 obtainMessage(EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE, request);
2573 Phone phone = getPhoneFromRequest(request);
2574 if (phone != null) {
2575 phone.stopSatellitePositionUpdates(onCompleted);
2576 } else {
2577 loge("stopSatellitePositionUpdates: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002578 ((Consumer<Integer>) request.argument).accept(
2579 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Sarah Chineccfbd12023-01-20 19:00:35 -08002580 }
2581 break;
2582 }
2583
2584 case EVENT_STOP_SATELLITE_POSITION_UPDATES_DONE: {
2585 ar = (AsyncResult) msg.obj;
2586 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002587 int error = getSatelliteError(ar, "stopSatellitePositionUpdates", false);
2588 ((Consumer<Integer>) request.argument).accept(error);
Sarah Chineccfbd12023-01-20 19:00:35 -08002589 break;
2590 }
2591
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002592 case CMD_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG: {
2593 request = (MainThreadRequest) msg.obj;
2594 onCompleted = obtainMessage(EVENT_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG_DONE,
2595 request);
2596 Phone phone = getPhoneFromRequest(request);
2597 if (phone != null) {
2598 phone.getMaxCharactersPerSatelliteTextMessage(onCompleted);
2599 } else {
2600 loge("getMaxCharactersPerSatelliteTextMessage: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002601 ((ResultReceiver) request.argument).send(
2602 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002603 }
2604 break;
2605 }
2606
2607 case EVENT_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG_DONE: {
2608 ar = (AsyncResult) msg.obj;
2609 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002610 int error =
2611 getSatelliteError(ar, "getMaxCharactersPerSatelliteTextMessage", true);
2612 Bundle bundle = new Bundle();
2613 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002614 int maxCharLimit = ((int[]) ar.result)[0];
Sarah Chin503828c2023-02-01 23:54:20 -08002615 if (DBG) log("getMaxCharactersPerSatelliteTextMessage: " + maxCharLimit);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002616 bundle.putInt(SatelliteManager.KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT,
2617 maxCharLimit);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002618 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002619 ((ResultReceiver) request.argument).send(error, bundle);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00002620 break;
2621 }
2622
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002623 case CMD_PROVISION_SATELLITE_SERVICE: {
2624 request = (MainThreadRequest) msg.obj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002625 onCompleted = obtainMessage(EVENT_PROVISION_SATELLITE_SERVICE_DONE, request);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002626 Phone phone = getPhoneFromRequest(request);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002627 ProvisionSatelliteServiceArgument argument =
2628 (ProvisionSatelliteServiceArgument) request.argument;
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002629 if (phone != null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002630 handleCmdProvisionSatelliteService(argument, phone, onCompleted);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002631 } else {
2632 loge("provisionSatelliteService: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002633 argument.callback.accept(
2634 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002635 notifyRequester(request);
2636 }
2637 break;
2638 }
2639
2640 case EVENT_PROVISION_SATELLITE_SERVICE_DONE: {
2641 ar = (AsyncResult) msg.obj;
2642 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002643 int errorCode = getSatelliteError(ar, "provisionSatelliteService", false);
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002644 handleEventProvisionSatelliteServiceDone(
2645 (ProvisionSatelliteServiceArgument) request.argument, errorCode);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002646 notifyRequester(request);
2647 break;
2648 }
2649
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002650 case CMD_DEPROVISION_SATELLITE_SERVICE: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002651 request = (MainThreadRequest) msg.obj;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002652 onCompleted = obtainMessage(EVENT_DEPROVISION_SATELLITE_SERVICE_DONE, request);
2653 Phone phone = getPhoneFromRequest(request);
2654 ProvisionSatelliteServiceArgument argument =
2655 (ProvisionSatelliteServiceArgument) request.argument;
2656 if (phone != null) {
2657 handleCmdDeprovisionSatelliteService(argument, phone, onCompleted);
2658 } else {
2659 loge("deprovisionSatelliteService: No phone object");
2660 if (argument.callback != null) {
2661 argument.callback.accept(
2662 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
2663 }
2664 notifyRequester(request);
2665 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002666 break;
2667 }
2668
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002669 case EVENT_DEPROVISION_SATELLITE_SERVICE_DONE: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002670 ar = (AsyncResult) msg.obj;
2671 request = (MainThreadRequest) ar.userObj;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -08002672 int errorCode = getSatelliteError(ar, "deprovisionSatelliteService", false);
2673 handleEventDeprovisionSatelliteServiceDone(
2674 (ProvisionSatelliteServiceArgument) request.argument, errorCode);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002675 notifyRequester(request);
2676 break;
2677 }
2678
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002679 case CMD_SET_SATELLITE_ENABLED: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002680 request = (MainThreadRequest) msg.obj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002681 onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request);
2682 Pair<Boolean, Consumer<Integer>> argument =
2683 (Pair<Boolean, Consumer<Integer>>) request.argument;
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002684 Phone phone = getPhoneFromRequest(request);
2685 if (phone != null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002686 boolean enable = argument.first.booleanValue();
2687 phone.setSatellitePower(onCompleted, enable);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002688 } else {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002689 loge("setSatelliteEnabled: No phone object");
2690 argument.second.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002691 notifyRequester(request);
2692 }
2693 break;
2694 }
2695
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002696 case EVENT_SET_SATELLITE_ENABLED_DONE: {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002697 ar = (AsyncResult) msg.obj;
2698 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002699 Pair<Boolean, Consumer<Integer>> argument =
2700 (Pair<Boolean, Consumer<Integer>>) request.argument;
2701 int error = getSatelliteError(ar, "setSatelliteEnabled", false);
2702 argument.second.accept(error);
Thomas Nguyen8ee49682023-02-01 11:46:09 -08002703 break;
2704 }
2705
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002706 case CMD_IS_SATELLITE_ENABLED: {
Sarah Chin503828c2023-02-01 23:54:20 -08002707 request = (MainThreadRequest) msg.obj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002708 onCompleted = obtainMessage(EVENT_IS_SATELLITE_ENABLED_DONE, request);
Sarah Chin503828c2023-02-01 23:54:20 -08002709 Phone phone = getPhoneFromRequest(request);
2710 if (phone != null) {
2711 phone.isSatellitePowerOn(onCompleted);
2712 } else {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002713 loge("isSatelliteEnabled: No phone object");
2714 ((ResultReceiver) request.argument).send(
2715 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Sarah Chin503828c2023-02-01 23:54:20 -08002716 }
2717 break;
2718 }
2719
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002720 case EVENT_IS_SATELLITE_ENABLED_DONE: {
Sarah Chin503828c2023-02-01 23:54:20 -08002721 ar = (AsyncResult) msg.obj;
2722 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002723 int error = getSatelliteError(ar, "isSatelliteEnabled", true);
2724 Bundle bundle = new Bundle();
2725 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2726 boolean enabled = ((int[]) ar.result)[0] == 1;
2727 if (DBG) log("isSatelliteEnabled: " + enabled);
2728 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled);
Sarah Chin503828c2023-02-01 23:54:20 -08002729 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002730 ((ResultReceiver) request.argument).send(error, bundle);
Sarah Chin503828c2023-02-01 23:54:20 -08002731 break;
2732 }
2733
2734 case CMD_IS_SATELLITE_SUPPORTED: {
2735 request = (MainThreadRequest) msg.obj;
2736 onCompleted = obtainMessage(EVENT_IS_SATELLITE_SUPPORTED_DONE, request);
2737 Phone phone = getPhoneFromRequest(request);
2738 if (phone != null) {
2739 phone.isSatelliteSupported(onCompleted);
2740 } else {
2741 loge("isSatelliteSupported: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002742 ((ResultReceiver) request.argument).send(
2743 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Sarah Chin503828c2023-02-01 23:54:20 -08002744 }
2745 break;
2746 }
2747
2748 case EVENT_IS_SATELLITE_SUPPORTED_DONE: {
2749 ar = (AsyncResult) msg.obj;
2750 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002751 int error = getSatelliteError(ar, "isSatelliteSupported", true);
2752 Bundle bundle = new Bundle();
2753 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2754 boolean supported = ((int[]) ar.result)[0] == 1;
2755 if (DBG) log("isSatelliteSupported: " + supported);
2756 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported);
Thomas Nguyene77de6d2023-02-10 17:42:43 -08002757 synchronized (mIsSatelliteSupportedLock) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002758 mIsSatelliteSupported = supported;
2759 }
2760 } else {
2761 synchronized (mIsSatelliteSupportedLock) {
2762 mIsSatelliteSupported = null;
Thomas Nguyene77de6d2023-02-10 17:42:43 -08002763 }
Sarah Chin503828c2023-02-01 23:54:20 -08002764 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002765 ((ResultReceiver) request.argument).send(error, bundle);
Sarah Chin503828c2023-02-01 23:54:20 -08002766 break;
2767 }
2768
2769 case CMD_GET_SATELLITE_CAPABILITIES: {
2770 request = (MainThreadRequest) msg.obj;
2771 onCompleted = obtainMessage(EVENT_GET_SATELLITE_CAPABILITIES_DONE, request);
2772 Phone phone = getPhoneFromRequest(request);
2773 if (phone != null) {
2774 phone.getSatelliteCapabilities(onCompleted);
2775 } else {
2776 loge("getSatelliteCapabilities: No phone object");
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002777 ((ResultReceiver) request.argument).send(
2778 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
Sarah Chin503828c2023-02-01 23:54:20 -08002779 }
2780 break;
2781 }
2782
2783 case EVENT_GET_SATELLITE_CAPABILITIES_DONE: {
2784 ar = (AsyncResult) msg.obj;
2785 request = (MainThreadRequest) ar.userObj;
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002786 int error = getSatelliteError(ar, "getSatelliteCapabilities", true);
2787 Bundle bundle = new Bundle();
2788 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
Sarah Chin503828c2023-02-01 23:54:20 -08002789 SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result;
2790 if (DBG) log("getSatelliteCapabilities: " + capabilities);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002791 bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
2792 capabilities);
Sarah Chin503828c2023-02-01 23:54:20 -08002793 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -08002794 ((ResultReceiver) request.argument).send(error, bundle);
Sarah Chin503828c2023-02-01 23:54:20 -08002795 break;
2796 }
2797
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +00002798 case CMD_POLL_PENDING_SATELLITE_DATAGRAMS: {
2799 request = (MainThreadRequest) msg.obj;
2800 onCompleted = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE,
2801 request);
2802 Phone phone = getPhoneFromRequest(request);
2803 if (phone != null) {
2804 phone.pollPendingSatelliteDatagrams(onCompleted);
2805 } else {
2806 loge("pollPendingSatelliteDatagrams: No phone object");
2807 request.result = SatelliteManager
2808 .SATELLITE_INVALID_TELEPHONY_STATE;
2809 notifyRequester(request);
2810 }
2811 break;
2812 }
2813
2814 case EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE: {
2815 ar = (AsyncResult) msg.obj;
2816 request = (MainThreadRequest) ar.userObj;
2817 if (ar.exception != null) {
2818 request.result = SatelliteManager.SATELLITE_SERVICE_ERROR;
2819 if (ar.exception instanceof CommandException) {
2820 CommandException.Error error =
2821 ((CommandException) (ar.exception)).getCommandError();
2822 request.result = RILUtils.convertToSatelliteError(error);
2823 loge("pollPendingSatelliteDatagrams: "
2824 + "CommandException: " + ar.exception);
2825 } else {
2826 loge("pollPendingSatelliteDatagrams: "
2827 + "unknown exception:" + ar.exception);
2828 }
2829 } else if (ar.result == null) {
2830 request.result = SatelliteManager
2831 .SATELLITE_INVALID_TELEPHONY_STATE;
2832 loge("pollPendingSatelliteDatagrams: result is null");
2833 } else {
2834 request.result = SatelliteManager.SATELLITE_ERROR_NONE;
2835 }
2836 notifyRequester(request);
2837 break;
2838 }
2839
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +00002840 case CMD_SEND_SATELLITE_DATAGRAM: {
2841 request = (MainThreadRequest) msg.obj;
2842 onCompleted =
2843 obtainMessage(EVENT_SEND_SATELLITE_DATAGRAM_DONE, request);
2844 Phone phone = getPhoneFromRequest(request);
2845 SendSatelliteDatagramArgument argument =
2846 (SendSatelliteDatagramArgument) request.argument;
2847 if (phone != null) {
2848 phone.sendSatelliteDatagram(onCompleted, argument.datagram);
2849 } else {
2850 loge("sendSatelliteDatagram: No phone object");
2851 argument.callback
2852 .accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
2853 }
2854 break;
2855 }
2856
2857 case EVENT_SEND_SATELLITE_DATAGRAM_DONE: {
2858 ar = (AsyncResult) msg.obj;
2859 request = (MainThreadRequest) ar.userObj;
2860 int error = getSatelliteError(ar, "sendSatelliteDatagram",
2861 false);
2862 SendSatelliteDatagramArgument argument =
2863 (SendSatelliteDatagramArgument) request.argument;
2864 argument.callback.accept(error);
2865 break;
2866 }
2867
Sarah Chindf715ec2023-02-13 13:46:24 -08002868 case CMD_IS_SATELLITE_COMMUNICATION_ALLOWED: {
2869 request = (MainThreadRequest) msg.obj;
2870 onCompleted = obtainMessage(EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE,
2871 request);
2872 Phone phone = getPhoneFromRequest(request);
2873 if (phone != null) {
2874 phone.isSatelliteCommunicationAllowedForCurrentLocation(onCompleted);
2875 } else {
2876 loge("isSatelliteCommunicationAllowedForCurrentLocation: No phone object");
2877 ((ResultReceiver) request.argument).send(
2878 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
2879 }
2880 break;
2881 }
2882
2883 case EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE: {
2884 ar = (AsyncResult) msg.obj;
2885 request = (MainThreadRequest) ar.userObj;
2886 int error = getSatelliteError(
2887 ar, "isSatelliteCommunicationAllowedForCurrentLocation", true);
2888 Bundle bundle = new Bundle();
2889 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2890 boolean communicationAllowed = ((int[]) ar.result)[0] == 1;
2891 if (DBG) {
2892 log("isSatelliteCommunicationAllowedForCurrentLocation: "
2893 + communicationAllowed);
2894 }
2895 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED,
2896 communicationAllowed);
2897 }
2898 ((ResultReceiver) request.argument).send(error, bundle);
2899 break;
2900 }
2901
2902 case CMD_GET_TIME_SATELLITE_NEXT_VISIBLE: {
2903 request = (MainThreadRequest) msg.obj;
2904 onCompleted = obtainMessage(EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE,
2905 request);
2906 Phone phone = getPhoneFromRequest(request);
2907 if (phone != null) {
2908 phone.requestTimeForNextSatelliteVisibility(onCompleted);
2909 } else {
2910 loge("requestTimeForNextSatelliteVisibility: No phone object");
2911 ((ResultReceiver) request.argument).send(
2912 SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
2913 }
2914 break;
2915 }
2916
2917 case EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE: {
2918 ar = (AsyncResult) msg.obj;
2919 request = (MainThreadRequest) ar.userObj;
2920 int error =
2921 getSatelliteError(ar, "requestTimeForNextSatelliteVisibility", true);
2922 Bundle bundle = new Bundle();
2923 if (error == SatelliteManager.SATELLITE_ERROR_NONE) {
2924 int nextVisibilityDuration = ((int[]) ar.result)[0];
2925 if (DBG) {
2926 log("requestTimeForNextSatelliteVisibility: " + nextVisibilityDuration);
2927 }
2928 bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY,
2929 nextVisibilityDuration);
2930 }
2931 ((ResultReceiver) request.argument).send(error, bundle);
2932 break;
2933 }
2934
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002935 default:
2936 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
2937 break;
2938 }
2939 }
Jake Hambye994d462014-02-03 13:10:13 -08002940
Pengquan Menga1bb6272018-09-06 09:59:22 -07002941 private void notifyRequester(MainThreadRequest request) {
2942 synchronized (request) {
2943 request.notifyAll();
2944 }
2945 }
2946
Jake Hambye994d462014-02-03 13:10:13 -08002947 private void handleNullReturnEvent(Message msg, String command) {
2948 AsyncResult ar = (AsyncResult) msg.obj;
2949 MainThreadRequest request = (MainThreadRequest) ar.userObj;
2950 if (ar.exception == null) {
2951 request.result = true;
2952 } else {
2953 request.result = false;
2954 if (ar.exception instanceof CommandException) {
2955 loge(command + ": CommandException: " + ar.exception);
2956 } else {
2957 loge(command + ": Unknown exception");
2958 }
2959 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07002960 notifyRequester(request);
Jake Hambye994d462014-02-03 13:10:13 -08002961 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002962 }
2963
2964 /**
2965 * Posts the specified command to be executed on the main thread,
2966 * waits for the request to complete, and returns the result.
2967 * @see #sendRequestAsync
2968 */
2969 private Object sendRequest(int command, Object argument) {
Rambo Wang0f050d82021-02-12 11:43:36 -08002970 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, null,
2971 null, -1 /*timeoutInMs*/);
vagdeviaf9a5b92018-08-15 16:01:53 -07002972 }
2973
2974 /**
2975 * Posts the specified command to be executed on the main thread,
2976 * waits for the request to complete, and returns the result.
2977 * @see #sendRequestAsync
2978 */
2979 private Object sendRequest(int command, Object argument, WorkSource workSource) {
2980 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
Rambo Wang0f050d82021-02-12 11:43:36 -08002981 null, workSource, -1 /*timeoutInMs*/);
Wink Saville36469e72014-06-11 15:17:00 -07002982 }
2983
2984 /**
2985 * Posts the specified command to be executed on the main thread,
2986 * waits for the request to complete, and returns the result.
2987 * @see #sendRequestAsync
2988 */
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002989 private Object sendRequest(int command, Object argument, Integer subId) {
Rambo Wang0f050d82021-02-12 11:43:36 -08002990 return sendRequest(command, argument, subId, null, null, -1 /*timeoutInMs*/);
2991 }
2992
2993 /**
2994 * Posts the specified command to be executed on the main thread,
2995 * waits for the request to complete for at most {@code timeoutInMs}, and returns the result
2996 * if not timeout or null otherwise.
2997 * @see #sendRequestAsync
2998 */
2999 private @Nullable Object sendRequest(int command, Object argument, Integer subId,
3000 long timeoutInMs) {
3001 return sendRequest(command, argument, subId, null, null, timeoutInMs);
vagdeviaf9a5b92018-08-15 16:01:53 -07003002 }
3003
3004 /**
3005 * Posts the specified command to be executed on the main thread,
3006 * waits for the request to complete, and returns the result.
3007 * @see #sendRequestAsync
3008 */
Nathan Harold92bed182018-10-12 18:16:49 -07003009 private Object sendRequest(int command, Object argument, int subId, WorkSource workSource) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003010 return sendRequest(command, argument, subId, null, workSource, -1 /*timeoutInMs*/);
Nathan Harold92bed182018-10-12 18:16:49 -07003011 }
3012
3013 /**
3014 * Posts the specified command to be executed on the main thread,
3015 * waits for the request to complete, and returns the result.
3016 * @see #sendRequestAsync
3017 */
3018 private Object sendRequest(int command, Object argument, Phone phone, WorkSource workSource) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003019 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID, phone,
3020 workSource, -1 /*timeoutInMs*/);
Nathan Harold92bed182018-10-12 18:16:49 -07003021 }
3022
3023 /**
Rambo Wang0f050d82021-02-12 11:43:36 -08003024 * Posts the specified command to be executed on the main thread. If {@code timeoutInMs} is
3025 * negative, waits for the request to complete, and returns the result. Otherwise, wait for
3026 * maximum of {@code timeoutInMs} milliseconds, interrupt and return null.
Nathan Harold92bed182018-10-12 18:16:49 -07003027 * @see #sendRequestAsync
3028 */
Rambo Wang0f050d82021-02-12 11:43:36 -08003029 private @Nullable Object sendRequest(int command, Object argument, Integer subId, Phone phone,
3030 WorkSource workSource, long timeoutInMs) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003031 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
3032 throw new RuntimeException("This method will deadlock if called from the main thread.");
3033 }
3034
Nathan Harold92bed182018-10-12 18:16:49 -07003035 MainThreadRequest request = null;
3036 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID && phone != null) {
3037 throw new IllegalArgumentException("subId and phone cannot both be specified!");
3038 } else if (phone != null) {
3039 request = new MainThreadRequest(argument, phone, workSource);
3040 } else {
3041 request = new MainThreadRequest(argument, subId, workSource);
3042 }
3043
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003044 Message msg = mMainThreadHandler.obtainMessage(command, request);
3045 msg.sendToTarget();
3046
Rambo Wang0f050d82021-02-12 11:43:36 -08003047
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003048 synchronized (request) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003049 if (timeoutInMs >= 0) {
3050 // Wait for at least timeoutInMs before returning null request result
3051 long now = SystemClock.elapsedRealtime();
3052 long deadline = now + timeoutInMs;
Grace Jia8a0a1e82021-05-23 22:59:52 -07003053 while (request.result == null && now < deadline) {
Rambo Wang0f050d82021-02-12 11:43:36 -08003054 try {
3055 request.wait(deadline - now);
3056 } catch (InterruptedException e) {
3057 // Do nothing, go back and check if request is completed or timeout
3058 } finally {
3059 now = SystemClock.elapsedRealtime();
3060 }
3061 }
3062 } else {
3063 // Wait for the request to complete
3064 while (request.result == null) {
3065 try {
3066 request.wait();
3067 } catch (InterruptedException e) {
3068 // Do nothing, go back and wait until the request is complete
3069 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003070 }
3071 }
3072 }
Rambo Wang0f050d82021-02-12 11:43:36 -08003073 if (request.result == null) {
3074 Log.wtf(LOG_TAG,
3075 "sendRequest: Blocking command timed out. Something has gone terribly wrong.");
3076 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003077 return request.result;
3078 }
3079
3080 /**
3081 * Asynchronous ("fire and forget") version of sendRequest():
3082 * Posts the specified command to be executed on the main thread, and
3083 * returns immediately.
3084 * @see #sendRequest
3085 */
3086 private void sendRequestAsync(int command) {
3087 mMainThreadHandler.sendEmptyMessage(command);
3088 }
3089
3090 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07003091 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07003092 * @see {@link #sendRequest(int)}
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07003093 */
3094 private void sendRequestAsync(int command, Object argument) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07003095 sendRequestAsync(command, argument, null, null);
3096 }
3097
3098 /**
3099 * Same as {@link #sendRequestAsync(int,Object)} except it takes a Phone and WorkSource.
3100 * @see {@link #sendRequest(int,Object)}
3101 */
3102 private void sendRequestAsync(
3103 int command, Object argument, Phone phone, WorkSource workSource) {
3104 MainThreadRequest request = new MainThreadRequest(argument, phone, workSource);
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07003105 Message msg = mMainThreadHandler.obtainMessage(command, request);
3106 msg.sendToTarget();
3107 }
3108
3109 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003110 * Initialize the singleton PhoneInterfaceManager instance.
3111 * This is only done once, at startup, from PhoneApp.onCreate().
3112 */
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003113 /* package */ static PhoneInterfaceManager init(PhoneGlobals app) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003114 synchronized (PhoneInterfaceManager.class) {
3115 if (sInstance == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003116 sInstance = new PhoneInterfaceManager(app);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003117 } else {
3118 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
3119 }
3120 return sInstance;
3121 }
3122 }
3123
3124 /** Private constructor; @see init() */
Jordan Liu1979a042020-03-20 21:39:35 +00003125 private PhoneInterfaceManager(PhoneGlobals app) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003126 mApp = app;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003127 mCM = PhoneGlobals.getInstance().mCM;
Brad Ebingerd1947d82021-05-17 20:54:49 +00003128 mImsResolver = ImsResolver.getInstance();
Stuart Scott981d8582015-04-21 14:09:50 -07003129 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003130 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
Grace Jia0ddb3612021-04-22 13:35:26 -07003131 mPm = app.getSystemService(PackageManager.class);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003132 mMainThreadHandler = new MainThreadHandler();
Jack Yue37dd262022-12-16 11:53:37 -08003133 if (!PhoneFactory.isSubscriptionManagerServiceEnabled()) {
3134 mSubscriptionController = SubscriptionController.getInstance();
3135 } else {
3136 mSubscriptionController = null;
3137 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003138 mTelephonySharedPreferences =
3139 PreferenceManager.getDefaultSharedPreferences(mApp);
yinxub1bed742017-04-17 11:45:04 -07003140 mNetworkScanRequestTracker = new NetworkScanRequestTracker();
Malcolm Chen2c63d402018-08-14 16:00:53 -07003141 mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
Daniel Bright94f43662021-03-01 14:43:40 -08003142 mRadioInterfaceCapabilities = RadioInterfaceCapabilityController.getInstance();
Peter Wanga3cf4ac2020-01-27 09:39:46 +08003143 mNotifyUserActivity = new AtomicBoolean(false);
Tyler Gunn64144d92022-03-17 14:16:41 -07003144 PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003145 publish();
arunvoddud7401012022-12-15 16:08:12 +00003146 CarrierAllowListInfo.loadInstance(mApp);
Sarah Chin4a9e8b82023-02-10 21:10:57 -08003147 mSatelliteSupportedReceiver = new ResultReceiver(mMainThreadHandler) {
3148 @Override
3149 protected void onReceiveResult(int resultCode, Bundle resultData) {
3150 if (resultCode == SatelliteManager.SATELLITE_ERROR_NONE
3151 && resultData.containsKey(SatelliteManager.KEY_SATELLITE_SUPPORTED)) {
3152 synchronized (mIsSatelliteSupportedLock) {
3153 mIsSatelliteSupported = resultData.getBoolean(
3154 SatelliteManager.KEY_SATELLITE_SUPPORTED);
3155 }
3156 } else {
3157 synchronized (mIsSatelliteSupportedLock) {
3158 mIsSatelliteSupported = null;
3159 }
3160 }
3161 }
3162 };
3163 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
3164 mSatelliteSupportedReceiver);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003165 }
3166
Gil Cukierman1c0eb932022-12-06 22:28:24 +00003167 @VisibleForTesting
3168 public SharedPreferences getSharedPreferences() {
3169 return mTelephonySharedPreferences;
3170 }
3171
Gil Cukierman92cc7db2023-01-06 19:25:53 +00003172 /**
3173 * Get the default phone for this device.
3174 */
3175 @VisibleForTesting
3176 public Phone getDefaultPhone() {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003177 Phone thePhone = getPhone(getDefaultSubscription());
3178 return (thePhone != null) ? thePhone : PhoneFactory.getDefaultPhone();
3179 }
3180
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003181 private void publish() {
3182 if (DBG) log("publish: " + this);
3183
Peter Wangc035ce42020-01-08 21:00:22 -08003184 TelephonyFrameworkInitializer
3185 .getTelephonyServiceManager()
3186 .getTelephonyServiceRegisterer()
3187 .register(this);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003188 }
3189
Stuart Scott584921c2015-01-15 17:10:34 -08003190 private Phone getPhoneFromRequest(MainThreadRequest request) {
Jordan Liu4c733742019-02-28 12:03:40 -08003191 if (request.phone != null) {
3192 return request.phone;
3193 } else {
3194 return getPhoneFromSubId(request.subId);
3195 }
3196 }
3197
3198 private Phone getPhoneFromSubId(int subId) {
3199 return (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
3200 ? getDefaultPhone() : getPhone(subId);
Stuart Scott584921c2015-01-15 17:10:34 -08003201 }
3202
Aishwarya Mallampati5e581e12023-01-17 21:57:06 +00003203 /**
3204 * Get phone object associated with a subscription.
3205 * Return default phone if phone object associated with subscription is null
3206 * @param subId - subscriptionId
3207 * @return phone object associated with a subscription or default phone if null.
3208 */
3209 private Phone getPhoneFromSubIdOrDefault(int subId) {
3210 Phone phone = getPhoneFromSubId(subId);
3211 if (phone == null) {
3212 phone = getDefaultPhone();
3213 }
3214 return phone;
3215 }
3216
Rambo Wange53e07d2022-05-10 13:01:13 -07003217 @Nullable
3218 private UiccPort getUiccPortFromRequest(@NonNull MainThreadRequest request) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003219 Phone phone = getPhoneFromRequest(request);
3220 return phone == null ? null :
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00003221 UiccController.getInstance().getUiccPort(phone.getPhoneId());
Shishir Agrawalc04d9752016-02-19 10:41:00 -08003222 }
3223
Wink Saville36469e72014-06-11 15:17:00 -07003224 // returns phone associated with the subId.
Wink Savilleb564aae2014-10-23 10:18:09 -07003225 private Phone getPhone(int subId) {
Jack Yu285100e2022-12-02 22:48:35 -08003226 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -07003227 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003228
Kai Shif70f46f2021-03-03 13:59:46 -08003229 private void sendEraseModemConfig(@NonNull Phone phone) {
3230 Boolean success = (Boolean) sendRequest(CMD_ERASE_MODEM_CONFIG, null);
3231 if (DBG) log("eraseModemConfig:" + ' ' + (success ? "ok" : "fail"));
3232 }
3233
3234 private void sendEraseDataInSharedPreferences(@NonNull Phone phone) {
3235 Boolean success = (Boolean) sendRequest(CMD_ERASE_DATA_SHARED_PREFERENCES, null);
3236 if (DBG) log("eraseDataInSharedPreferences:" + ' ' + (success ? "ok" : "fail"));
Naina Nallurid63128d2019-09-17 14:10:30 -07003237 }
3238
Peter Wang44b186e2020-01-13 23:33:09 -08003239 private boolean isImsAvailableOnDevice() {
3240 PackageManager pm = getDefaultPhone().getContext().getPackageManager();
3241 if (pm == null) {
3242 // For some reason package manger is not available.. This will fail internally anyway,
3243 // so do not throw error and allow.
3244 return true;
3245 }
3246 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
3247 }
3248
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003249 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003250 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -07003251 }
3252
Wink Savilleb564aae2014-10-23 10:18:09 -07003253 public void dialForSubscriber(int subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003254 if (DBG) log("dial: " + number);
3255 // No permission check needed here: This is just a wrapper around the
3256 // ACTION_DIAL intent, which is available to any app since it puts up
3257 // the UI before it does anything.
3258
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003259 final long identity = Binder.clearCallingIdentity();
3260 try {
3261 String url = createTelUrl(number);
3262 if (url == null) {
3263 return;
3264 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003265
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003266 // PENDING: should we just silently fail if phone is offhook or ringing?
3267 PhoneConstants.State state = mCM.getState(subId);
3268 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
3269 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
3270 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3271 mApp.startActivity(intent);
3272 }
3273 } finally {
3274 Binder.restoreCallingIdentity(identity);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003275 }
3276 }
3277
3278 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003279 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -07003280 }
3281
Wink Savilleb564aae2014-10-23 10:18:09 -07003282 public void callForSubscriber(int subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003283 if (DBG) log("call: " + number);
3284
3285 // This is just a wrapper around the ACTION_CALL intent, but we still
3286 // need to do a permission check since we're calling startActivity()
3287 // from the context of the phone app.
3288 enforceCallPermission();
3289
Jordan Liu1617b712019-07-10 15:06:26 -07003290 if (mAppOps.noteOp(AppOpsManager.OPSTR_CALL_PHONE, Binder.getCallingUid(), callingPackage)
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003291 != AppOpsManager.MODE_ALLOWED) {
3292 return;
3293 }
3294
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003295 final long identity = Binder.clearCallingIdentity();
3296 try {
3297 String url = createTelUrl(number);
3298 if (url == null) {
3299 return;
3300 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003301
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003302 boolean isValid = false;
3303 final List<SubscriptionInfo> slist = getActiveSubscriptionInfoListPrivileged();
3304 if (slist != null) {
3305 for (SubscriptionInfo subInfoRecord : slist) {
3306 if (subInfoRecord.getSubscriptionId() == subId) {
3307 isValid = true;
3308 break;
3309 }
Wink Saville3ab207e2014-11-20 13:07:20 -08003310 }
Wink Saville08874612014-08-31 19:19:58 -07003311 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003312 if (!isValid) {
3313 return;
3314 }
Wink Saville08874612014-08-31 19:19:58 -07003315
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003316 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
3317 intent.putExtra(SUBSCRIPTION_KEY, subId);
3318 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
3319 mApp.startActivity(intent);
3320 } finally {
3321 Binder.restoreCallingIdentity(identity);
3322 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003323 }
3324
Wink Savilleb564aae2014-10-23 10:18:09 -07003325 public boolean supplyPinForSubscriber(int subId, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003326 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07003327 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
3328 }
3329
Wink Savilleb564aae2014-10-23 10:18:09 -07003330 public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003331 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07003332 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
3333 }
3334
Wink Savilleb564aae2014-10-23 10:18:09 -07003335 public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003336 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003337
3338 final long identity = Binder.clearCallingIdentity();
3339 try {
Michele Berionne5e411512020-11-13 02:36:59 +00003340 Phone phone = getPhone(subId);
3341 final UnlockSim checkSimPin = new UnlockSim(phone.getPhoneId(), phone.getIccCard());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003342 checkSimPin.start();
3343 return checkSimPin.unlockSim(null, pin);
3344 } finally {
3345 Binder.restoreCallingIdentity(identity);
3346 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003347 }
3348
Wink Savilleb564aae2014-10-23 10:18:09 -07003349 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003350 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003351
3352 final long identity = Binder.clearCallingIdentity();
3353 try {
Michele Berionne5e411512020-11-13 02:36:59 +00003354 Phone phone = getPhone(subId);
3355 final UnlockSim checkSimPuk = new UnlockSim(phone.getPhoneId(), phone.getIccCard());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003356 checkSimPuk.start();
3357 return checkSimPuk.unlockSim(puk, pin);
3358 } finally {
3359 Binder.restoreCallingIdentity(identity);
3360 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003361 }
3362
3363 /**
Wink Saville9de0f752013-10-22 19:04:03 -07003364 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003365 * a synchronous one.
3366 */
3367 private static class UnlockSim extends Thread {
3368
3369 private final IccCard mSimCard;
Michele Berionne5e411512020-11-13 02:36:59 +00003370 private final int mPhoneId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003371
3372 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -07003373 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
3374 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003375
3376 // For replies from SimCard interface
3377 private Handler mHandler;
3378
3379 // For async handler to identify request type
3380 private static final int SUPPLY_PIN_COMPLETE = 100;
3381
Michele Berionne5e411512020-11-13 02:36:59 +00003382 UnlockSim(int phoneId, IccCard simCard) {
3383 mPhoneId = phoneId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003384 mSimCard = simCard;
3385 }
3386
3387 @Override
3388 public void run() {
3389 Looper.prepare();
3390 synchronized (UnlockSim.this) {
3391 mHandler = new Handler() {
3392 @Override
3393 public void handleMessage(Message msg) {
3394 AsyncResult ar = (AsyncResult) msg.obj;
3395 switch (msg.what) {
3396 case SUPPLY_PIN_COMPLETE:
3397 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
3398 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -07003399 mRetryCount = msg.arg1;
3400 if (ar.exception != null) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -08003401 CommandException.Error error = null;
3402 if (ar.exception instanceof CommandException) {
3403 error = ((CommandException) (ar.exception))
3404 .getCommandError();
3405 }
3406 if (error == CommandException.Error.PASSWORD_INCORRECT) {
Wink Saville9de0f752013-10-22 19:04:03 -07003407 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
Thomas Nguyen8ee49682023-02-01 11:46:09 -08003408 } else if (error == CommandException.Error.ABORTED) {
3409 /* When UiccCardApp dispose, handle message and return
3410 exception */
vivi.lib5e9ada2019-09-12 16:04:24 +08003411 mResult = PhoneConstants.PIN_OPERATION_ABORTED;
Wink Saville9de0f752013-10-22 19:04:03 -07003412 } else {
3413 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
3414 }
3415 } else {
3416 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
3417 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003418 mDone = true;
3419 UnlockSim.this.notifyAll();
3420 }
3421 break;
3422 }
3423 }
3424 };
3425 UnlockSim.this.notifyAll();
3426 }
3427 Looper.loop();
3428 }
3429
3430 /*
3431 * Use PIN or PUK to unlock SIM card
3432 *
3433 * If PUK is null, unlock SIM card with PIN
3434 *
3435 * If PUK is not null, unlock SIM card with PUK and set PIN code
3436 */
Wink Saville9de0f752013-10-22 19:04:03 -07003437 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003438
3439 while (mHandler == null) {
3440 try {
3441 wait();
3442 } catch (InterruptedException e) {
3443 Thread.currentThread().interrupt();
3444 }
3445 }
3446 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
3447
3448 if (puk == null) {
3449 mSimCard.supplyPin(pin, callback);
3450 } else {
3451 mSimCard.supplyPuk(puk, pin, callback);
3452 }
3453
3454 while (!mDone) {
3455 try {
3456 Log.d(LOG_TAG, "wait for done");
3457 wait();
3458 } catch (InterruptedException e) {
3459 // Restore the interrupted status
3460 Thread.currentThread().interrupt();
3461 }
3462 }
3463 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07003464 int[] resultArray = new int[2];
3465 resultArray[0] = mResult;
3466 resultArray[1] = mRetryCount;
Michele Berionne5e411512020-11-13 02:36:59 +00003467
3468 if (mResult == PhoneConstants.PIN_RESULT_SUCCESS && pin.length() > 0) {
Jon Spivack9c3bc762021-10-06 20:53:09 +00003469 UiccController.getInstance().getPinStorage().storePin(pin, mPhoneId);
Michele Berionne5e411512020-11-13 02:36:59 +00003470 }
3471
Wink Saville9de0f752013-10-22 19:04:03 -07003472 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003473 }
3474 }
3475
Nathan Harold7c8d0f12020-05-28 20:40:31 -07003476 /**
3477 * This method has been removed due to privacy and stability concerns.
3478 */
3479 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003480 public void updateServiceLocation() {
Nathan Harold7c8d0f12020-05-28 20:40:31 -07003481 Log.e(LOG_TAG, "Call to unsupported method updateServiceLocation()");
3482 return;
Wink Saville36469e72014-06-11 15:17:00 -07003483 }
3484
Nathan Harold1f889d82020-06-04 17:05:26 -07003485 @Override
3486 public void updateServiceLocationWithPackageName(String callingPackage) {
3487 mApp.getSystemService(AppOpsManager.class)
3488 .checkPackage(Binder.getCallingUid(), callingPackage);
3489
Nathan Haroldf096d982020-11-18 17:18:06 -08003490 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Harold1f889d82020-06-04 17:05:26 -07003491 if (targetSdk > android.os.Build.VERSION_CODES.R) {
3492 // Callers targeting S have no business invoking this method.
3493 return;
3494 }
3495
3496 LocationAccessPolicy.LocationPermissionResult locationResult =
3497 LocationAccessPolicy.checkLocationPermission(mApp,
3498 new LocationAccessPolicy.LocationPermissionQuery.Builder()
3499 .setCallingPackage(callingPackage)
3500 .setCallingFeatureId(null)
3501 .setCallingPid(Binder.getCallingPid())
3502 .setCallingUid(Binder.getCallingUid())
3503 .setMethod("updateServiceLocation")
3504 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
3505 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
3506 .build());
3507 // Apps that lack location permission have no business calling this method;
3508 // however, because no permission was declared in the public API, denials must
3509 // all be "soft".
3510 switch (locationResult) {
3511 case DENIED_HARD: /* fall through */
3512 case DENIED_SOFT:
3513 return;
3514 }
3515
3516 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003517 final long identity = Binder.clearCallingIdentity();
3518 try {
Nathan Harold1f889d82020-06-04 17:05:26 -07003519 final Phone phone = getPhone(getDefaultSubscription());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003520 if (phone != null) {
Nathan Harold1f889d82020-06-04 17:05:26 -07003521 phone.updateServiceLocation(workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003522 }
3523 } finally {
3524 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003525 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003526 }
3527
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003528 @Deprecated
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003529 @Override
3530 public boolean isRadioOn(String callingPackage) {
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003531 return isRadioOnWithFeature(callingPackage, null);
3532 }
3533
3534
3535 @Override
3536 public boolean isRadioOnWithFeature(String callingPackage, String callingFeatureId) {
3537 return isRadioOnForSubscriberWithFeature(getDefaultSubscription(), callingPackage,
3538 callingFeatureId);
3539 }
3540
3541 @Deprecated
3542 @Override
3543 public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
3544 return isRadioOnForSubscriberWithFeature(subId, callingPackage, null);
Wink Saville36469e72014-06-11 15:17:00 -07003545 }
3546
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003547 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003548 public boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage,
3549 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08003550 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07003551 mApp, subId, callingPackage, callingFeatureId, "isRadioOnForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003552 return false;
3553 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003554
3555 final long identity = Binder.clearCallingIdentity();
3556 try {
3557 return isRadioOnForSubscriber(subId);
3558 } finally {
3559 Binder.restoreCallingIdentity(identity);
3560 }
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003561 }
3562
3563 private boolean isRadioOnForSubscriber(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003564 final long identity = Binder.clearCallingIdentity();
3565 try {
3566 final Phone phone = getPhone(subId);
3567 if (phone != null) {
3568 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
3569 } else {
3570 return false;
3571 }
3572 } finally {
3573 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003574 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003575 }
3576
3577 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003578 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003579 }
Wink Saville36469e72014-06-11 15:17:00 -07003580
Wink Savilleb564aae2014-10-23 10:18:09 -07003581 public void toggleRadioOnOffForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -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 phone.setRadioPower(!isRadioOnForSubscriber(subId));
3589 }
3590 } finally {
3591 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003592 }
Wink Saville36469e72014-06-11 15:17:00 -07003593 }
3594
3595 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003596 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07003597 }
3598
Wink Savilleb564aae2014-10-23 10:18:09 -07003599 public boolean setRadioForSubscriber(int subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07003600 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003601
3602 final long identity = Binder.clearCallingIdentity();
3603 try {
3604 final Phone phone = getPhone(subId);
3605 if (phone == null) {
3606 return false;
3607 }
3608 if ((phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF) != turnOn) {
3609 toggleRadioOnOffForSubscriber(subId);
3610 }
3611 return true;
3612 } finally {
3613 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003614 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003615 }
Wink Saville36469e72014-06-11 15:17:00 -07003616
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003617 public boolean needMobileRadioShutdown() {
Shuo Qianfa7b6b32019-12-10 10:40:38 -08003618 enforceReadPrivilegedPermission("needMobileRadioShutdown");
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003619 /*
3620 * If any of the Radios are available, it will need to be
3621 * shutdown. So return true if any Radio is available.
3622 */
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003623 final long identity = Binder.clearCallingIdentity();
3624 try {
3625 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
3626 Phone phone = PhoneFactory.getPhone(i);
3627 if (phone != null && phone.isRadioAvailable()) return true;
3628 }
3629 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
3630 return false;
3631 } finally {
3632 Binder.restoreCallingIdentity(identity);
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003633 }
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003634 }
3635
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003636 @Override
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003637 public void shutdownMobileRadios() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003638 enforceModifyPermission();
3639
3640 final long identity = Binder.clearCallingIdentity();
3641 try {
3642 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
3643 logv("Shutting down Phone " + i);
3644 shutdownRadioUsingPhoneId(i);
3645 }
3646 } finally {
3647 Binder.restoreCallingIdentity(identity);
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003648 }
3649 }
3650
3651 private void shutdownRadioUsingPhoneId(int phoneId) {
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07003652 Phone phone = PhoneFactory.getPhone(phoneId);
3653 if (phone != null && phone.isRadioAvailable()) {
3654 phone.shutdownRadio();
3655 }
3656 }
3657
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003658 public boolean setRadioPower(boolean turnOn) {
Jack Yub4e16162017-05-15 12:48:40 -07003659 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003660
Ling Ma83dc5ea2023-01-12 15:06:04 -08003661 if (!turnOn) {
3662 log("setRadioPower off: callingPackage=" + getCurrentPackageName());
3663 }
3664
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003665 final long identity = Binder.clearCallingIdentity();
3666 try {
3667 final Phone defaultPhone = PhoneFactory.getDefaultPhone();
3668 if (defaultPhone != null) {
3669 defaultPhone.setRadioPower(turnOn);
3670 return true;
3671 } else {
3672 loge("There's no default phone.");
3673 return false;
3674 }
3675 } finally {
3676 Binder.restoreCallingIdentity(identity);
Wei Liu9ae2a062016-08-08 11:09:34 -07003677 }
Wink Saville36469e72014-06-11 15:17:00 -07003678 }
3679
Wink Savilleb564aae2014-10-23 10:18:09 -07003680 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003681 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003682
Ling Ma83dc5ea2023-01-12 15:06:04 -08003683 if (!turnOn) {
3684 log("setRadioPowerForSubscriber off: subId=" + subId
3685 + ",callingPackage=" + getCurrentPackageName());
3686 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003687 final long identity = Binder.clearCallingIdentity();
3688 try {
3689 final Phone phone = getPhone(subId);
3690 if (phone != null) {
3691 phone.setRadioPower(turnOn);
3692 return true;
3693 } else {
3694 return false;
3695 }
3696 } finally {
3697 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003698 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003699 }
3700
Thomas Nguyenfd0572f2022-07-15 22:28:49 +00003701 /**
3702 * Vote on powering off the radio for a reason. The radio will be turned on only when there is
3703 * no reason to power it off. When any of the voters want to power it off, it will be turned
3704 * off. In case of emergency, the radio will be turned on even if there are some reasons for
3705 * powering it off, and these radio off votes will be cleared.
3706 * Multiple apps can vote for the same reason and the last vote will take effect. Each app is
3707 * responsible for its vote. A powering-off vote of a reason will be maintained until it is
3708 * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call
3709 * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make
3710 * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to
3711 * check its vote.
3712 *
3713 * @param subId The subscription ID.
3714 * @param reason The reason for powering off radio.
3715 * @return true on success and false on failure.
3716 */
3717 public boolean requestRadioPowerOffForReason(int subId,
3718 @TelephonyManager.RadioPowerReason int reason) {
3719 enforceModifyPermission();
3720
Ling Ma83dc5ea2023-01-12 15:06:04 -08003721 log("requestRadioPowerOffForReason: subId=" + subId
3722 + ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
Thomas Nguyenfd0572f2022-07-15 22:28:49 +00003723 final long identity = Binder.clearCallingIdentity();
3724 try {
3725 final Phone phone = getPhone(subId);
3726 if (phone != null) {
3727 phone.setRadioPowerForReason(false, reason);
3728 return true;
3729 } else {
3730 return false;
3731 }
3732 } finally {
3733 Binder.restoreCallingIdentity(identity);
3734 }
3735 }
3736
3737 /**
3738 * Remove the vote on powering off the radio for a reason, as requested by
3739 * {@link requestRadioPowerOffForReason}.
3740 *
3741 * @param subId The subscription ID.
3742 * @param reason The reason for powering off radio.
3743 * @return true on success and false on failure.
3744 */
3745 public boolean clearRadioPowerOffForReason(int subId,
3746 @TelephonyManager.RadioPowerReason int reason) {
3747 enforceModifyPermission();
3748
3749 final long identity = Binder.clearCallingIdentity();
3750 try {
3751 final Phone phone = getPhone(subId);
3752 if (phone != null) {
3753 phone.setRadioPowerForReason(true, reason);
3754 return true;
3755 } else {
3756 return false;
3757 }
3758 } finally {
3759 Binder.restoreCallingIdentity(identity);
3760 }
3761 }
3762
3763 /**
3764 * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}.
3765 *
3766 * @param subId The subscription ID.
3767 * @param callingPackage The package making the call.
3768 * @param callingFeatureId The feature in the package.
3769 * @return List of reasons for powering off radio.
3770 */
3771 public List getRadioPowerOffReasons(int subId, String callingPackage, String callingFeatureId) {
3772 enforceReadPrivilegedPermission("getRadioPowerOffReasons");
3773
3774 final long identity = Binder.clearCallingIdentity();
3775 List result = new ArrayList();
3776 try {
3777 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId,
3778 callingPackage, callingFeatureId, "getRadioPowerOffReasons")) {
3779 return result;
3780 }
3781
3782 final Phone phone = getPhone(subId);
3783 if (phone != null) {
3784 result.addAll(phone.getRadioPowerOffReasons());
3785 }
3786 } finally {
3787 Binder.restoreCallingIdentity(identity);
3788 }
3789 return result;
3790 }
3791
Wink Saville36469e72014-06-11 15:17:00 -07003792 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07003793 @Override
Sarah Chinecc78c42022-03-31 21:16:48 -07003794 public boolean enableDataConnectivity(String callingPackage) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003795 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003796
3797 final long identity = Binder.clearCallingIdentity();
3798 try {
Jack Yu285100e2022-12-02 22:48:35 -08003799 int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003800 final Phone phone = getPhone(subId);
3801 if (phone != null) {
Jack Yu7968c6d2022-07-31 00:43:21 -07003802 phone.getDataSettingsManager().setDataEnabled(
3803 TelephonyManager.DATA_ENABLED_REASON_USER, true, callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003804 return true;
3805 } else {
3806 return false;
3807 }
3808 } finally {
3809 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003810 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003811 }
3812
Wink Saville36469e72014-06-11 15:17:00 -07003813 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07003814 @Override
Sarah Chinecc78c42022-03-31 21:16:48 -07003815 public boolean disableDataConnectivity(String callingPackage) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003816 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003817
3818 final long identity = Binder.clearCallingIdentity();
3819 try {
Jack Yu285100e2022-12-02 22:48:35 -08003820 int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003821 final Phone phone = getPhone(subId);
3822 if (phone != null) {
Jack Yu7968c6d2022-07-31 00:43:21 -07003823 phone.getDataSettingsManager().setDataEnabled(
3824 TelephonyManager.DATA_ENABLED_REASON_USER, false, callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003825 return true;
3826 } else {
3827 return false;
3828 }
3829 } finally {
3830 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003831 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003832 }
3833
Sanket Padawe356d7632015-06-22 14:03:32 -07003834 @Override
Jack Yuacf8a132017-05-01 17:00:48 -07003835 public boolean isDataConnectivityPossible(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003836 final long identity = Binder.clearCallingIdentity();
3837 try {
3838 final Phone phone = getPhone(subId);
3839 if (phone != null) {
Jack Yu59824e12022-03-23 01:42:44 -07003840 return phone.isDataAllowed();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003841 } else {
3842 return false;
3843 }
3844 } finally {
3845 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003846 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003847 }
3848
3849 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07003850 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07003851 }
3852
pkanwarae03a6b2016-11-06 20:37:09 -08003853 public void handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003854 enforceCallPermission();
3855
3856 final long identity = Binder.clearCallingIdentity();
3857 try {
3858 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3859 return;
3860 }
3861 Pair<String, ResultReceiver> ussdObject = new Pair(ussdRequest, wrappedCallback);
3862 sendRequest(CMD_HANDLE_USSD_REQUEST, ussdObject, subId);
3863 } finally {
3864 Binder.restoreCallingIdentity(identity);
3865 }
pkanwar32d516d2016-10-14 19:37:38 -07003866 };
3867
Wink Savilleb564aae2014-10-23 10:18:09 -07003868 public boolean handlePinMmiForSubscriber(int subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003869 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003870
3871 final long identity = Binder.clearCallingIdentity();
3872 try {
3873 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3874 return false;
3875 }
3876 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
3877 } finally {
3878 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003879 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003880 }
3881
Brad Ebinger4f6208e2021-03-23 21:04:45 +00003882 /**
3883 * @deprecated This method is deprecated and is only being kept due to an UnsupportedAppUsage
3884 * tag on getCallState Binder call.
3885 */
3886 @Deprecated
3887 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003888 public int getCallState() {
Brad Ebinger4f6208e2021-03-23 21:04:45 +00003889 if (CompatChanges.isChangeEnabled(
3890 TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION,
3891 Binder.getCallingUid())) {
3892 // Do not allow this API to be called on API version 31+, it should only be
3893 // called on old apps using this Binder call directly.
3894 throw new SecurityException("This method can only be used for applications "
3895 + "targeting API version 30 or less.");
3896 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003897 final long identity = Binder.clearCallingIdentity();
3898 try {
Brad Ebinger4f6208e2021-03-23 21:04:45 +00003899 Phone phone = getPhone(getDefaultSubscription());
3900 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
3901 PhoneConstantConversions.convertCallState(phone.getState());
3902 } finally {
3903 Binder.restoreCallingIdentity(identity);
3904 }
3905 }
3906
3907 @Override
3908 public int getCallStateForSubscription(int subId, String callingPackage, String featureId) {
3909 if (CompatChanges.isChangeEnabled(
3910 TelecomManager.ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION,
3911 Binder.getCallingUid())) {
3912 // Check READ_PHONE_STATE for API version 31+
3913 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId, callingPackage,
3914 featureId, "getCallStateForSubscription")) {
3915 throw new SecurityException("getCallState requires READ_PHONE_STATE for apps "
3916 + "targeting API level 31+.");
3917 }
3918 }
3919 final long identity = Binder.clearCallingIdentity();
3920 try {
3921 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003922 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
3923 PhoneConstantConversions.convertCallState(phone.getState());
3924 } finally {
3925 Binder.restoreCallingIdentity(identity);
3926 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003927 }
3928
Sanket Padawe356d7632015-06-22 14:03:32 -07003929 @Override
Nathan Harolde037c472019-06-26 00:41:07 +00003930 public int getDataState() {
Jack Yu285100e2022-12-02 22:48:35 -08003931 return getDataStateForSubId(SubscriptionManager.getDefaultDataSubscriptionId());
Nathan Haroldc4689b12019-06-14 16:58:30 -07003932 }
3933
3934 @Override
3935 public int getDataStateForSubId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003936 final long identity = Binder.clearCallingIdentity();
3937 try {
Nathan Haroldc4689b12019-06-14 16:58:30 -07003938 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003939 if (phone != null) {
Jack Yu7968c6d2022-07-31 00:43:21 -07003940 return phone.getDataNetworkController().getInternetDataNetworkState();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003941 } else {
3942 return PhoneConstantConversions.convertDataState(
3943 PhoneConstants.DataState.DISCONNECTED);
3944 }
3945 } finally {
3946 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003947 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003948 }
3949
Sanket Padawe356d7632015-06-22 14:03:32 -07003950 @Override
Jack Yu0eda6842022-04-18 00:34:46 -07003951 public @DataActivityType int getDataActivity() {
Jack Yu285100e2022-12-02 22:48:35 -08003952 return getDataActivityForSubId(SubscriptionManager.getDefaultDataSubscriptionId());
Nathan Haroldc4689b12019-06-14 16:58:30 -07003953 }
3954
3955 @Override
Jack Yu0eda6842022-04-18 00:34:46 -07003956 public @DataActivityType int getDataActivityForSubId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003957 final long identity = Binder.clearCallingIdentity();
3958 try {
Nathan Haroldc4689b12019-06-14 16:58:30 -07003959 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003960 if (phone != null) {
Jack Yu0eda6842022-04-18 00:34:46 -07003961 return phone.getDataActivityState();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003962 } else {
3963 return TelephonyManager.DATA_ACTIVITY_NONE;
3964 }
3965 } finally {
3966 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07003967 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003968 }
3969
3970 @Override
Meng Wanga10e89e2019-12-09 13:13:01 -08003971 public CellIdentity getCellLocation(String callingPackage, String callingFeatureId) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08003972 mApp.getSystemService(AppOpsManager.class)
Hall Liu1aa510f2017-11-22 17:40:08 -08003973 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08003974
3975 LocationAccessPolicy.LocationPermissionResult locationResult =
3976 LocationAccessPolicy.checkLocationPermission(mApp,
3977 new LocationAccessPolicy.LocationPermissionQuery.Builder()
3978 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07003979 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08003980 .setCallingPid(Binder.getCallingPid())
3981 .setCallingUid(Binder.getCallingUid())
3982 .setMethod("getCellLocation")
Hall Liu773ba022020-01-24 18:07:12 -08003983 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08003984 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
3985 .build());
3986 switch (locationResult) {
3987 case DENIED_HARD:
3988 throw new SecurityException("Not allowed to access cell location");
3989 case DENIED_SOFT:
Meng Wanga10e89e2019-12-09 13:13:01 -08003990 return (getDefaultPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA)
3991 ? new CellIdentityCdma() : new CellIdentityGsm();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003992 }
3993
Narayan Kamathf04b5a12018-01-09 11:47:15 +00003994 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08003995 final long identity = Binder.clearCallingIdentity();
3996 try {
3997 if (DBG_LOC) log("getCellLocation: is active user");
Jack Yu285100e2022-12-02 22:48:35 -08003998 int subId = SubscriptionManager.getDefaultDataSubscriptionId();
Meng Wanga10e89e2019-12-09 13:13:01 -08003999 return (CellIdentity) sendRequest(CMD_GET_CELL_LOCATION, workSource, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004000 } finally {
4001 Binder.restoreCallingIdentity(identity);
4002 }
Svetoslav64fad262015-04-14 14:35:21 -07004003 }
4004
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004005 @Override
Jack Yueb1e7fe2020-02-22 19:38:58 -08004006 public String getNetworkCountryIsoForPhone(int phoneId) {
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004007 // Reporting the correct network country is ambiguous when IWLAN could conflict with
4008 // registered cell info, so return a NULL country instead.
4009 final long identity = Binder.clearCallingIdentity();
4010 try {
Malcolm Chen3732c2b2018-07-18 20:15:24 -07004011 if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
4012 // Get default phone in this case.
4013 phoneId = SubscriptionManager.DEFAULT_PHONE_INDEX;
4014 }
Jack Yu285100e2022-12-02 22:48:35 -08004015 final int subId = SubscriptionManager.getSubscriptionId(phoneId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004016 Phone phone = PhoneFactory.getPhone(phoneId);
Nathan Harold532f51c2020-04-21 19:31:10 -07004017 if (phone == null) return "";
4018 ServiceStateTracker sst = phone.getServiceStateTracker();
4019 if (sst == null) return "";
4020 LocaleTracker lt = sst.getLocaleTracker();
4021 if (lt == null) return "";
Shuo Qian9418a922021-03-09 11:21:16 -08004022 return lt.getCurrentCountry();
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004023 } finally {
4024 Binder.restoreCallingIdentity(identity);
4025 }
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004026 }
4027
Nathan Harold7c8d0f12020-05-28 20:40:31 -07004028 /**
4029 * This method was removed due to potential issues caused by performing partial
4030 * updates of service state, and lack of a credible use case.
4031 *
4032 * This has the ability to break the telephony implementation by disabling notification of
4033 * changes in device connectivity. DO NOT USE THIS!
4034 */
Jonathan Basseribf5362b2017-07-19 12:22:35 -07004035 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004036 public void enableLocationUpdates() {
4037 mApp.enforceCallingOrSelfPermission(
4038 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004039 }
4040
Nathan Harold7c8d0f12020-05-28 20:40:31 -07004041 /**
4042 * This method was removed due to potential issues caused by performing partial
4043 * updates of service state, and lack of a credible use case.
4044 *
4045 * This has the ability to break the telephony implementation by disabling notification of
4046 * changes in device connectivity. DO NOT USE THIS!
4047 */
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004048 @Override
4049 public void disableLocationUpdates() {
4050 mApp.enforceCallingOrSelfPermission(
4051 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004052 }
4053
4054 @Override
4055 @SuppressWarnings("unchecked")
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004056 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage,
4057 String callingFeatureId) {
Nathan Haroldb55f63b2021-07-27 11:27:38 -07004058 try {
4059 mApp.getSystemService(AppOpsManager.class)
4060 .checkPackage(Binder.getCallingUid(), callingPackage);
4061 } catch (SecurityException e) {
4062 EventLog.writeEvent(0x534e4554, "190619791", Binder.getCallingUid());
4063 throw e;
4064 }
4065
Nathan Haroldf096d982020-11-18 17:18:06 -08004066 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Harolddbea45a2018-08-30 14:35:07 -07004067 if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
4068 throw new SecurityException(
4069 "getNeighboringCellInfo() is unavailable to callers targeting Q+ SDK levels.");
4070 }
Nathan Haroldb4d55612018-07-20 13:13:08 -07004071
Jordan Liu1617b712019-07-10 15:06:26 -07004072 if (mAppOps.noteOp(AppOpsManager.OPSTR_NEIGHBORING_CELLS, Binder.getCallingUid(),
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004073 callingPackage) != AppOpsManager.MODE_ALLOWED) {
4074 return null;
4075 }
Svetoslav64fad262015-04-14 14:35:21 -07004076
Svetoslav Ganov4a9d4482017-06-20 19:53:35 -07004077 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004078
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004079 List<CellInfo> info = getAllCellInfo(callingPackage, callingFeatureId);
Nathan Haroldf180aac2018-06-01 18:43:55 -07004080 if (info == null) return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004081
Nathan Haroldf180aac2018-06-01 18:43:55 -07004082 List<NeighboringCellInfo> neighbors = new ArrayList<NeighboringCellInfo>();
4083 for (CellInfo ci : info) {
4084 if (ci instanceof CellInfoGsm) {
4085 neighbors.add(new NeighboringCellInfo((CellInfoGsm) ci));
4086 } else if (ci instanceof CellInfoWcdma) {
4087 neighbors.add(new NeighboringCellInfo((CellInfoWcdma) ci));
4088 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004089 }
Nathan Haroldf180aac2018-06-01 18:43:55 -07004090 return (neighbors.size()) > 0 ? neighbors : null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004091 }
4092
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004093 private List<CellInfo> getCachedCellInfo() {
4094 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
4095 for (Phone phone : PhoneFactory.getPhones()) {
4096 List<CellInfo> info = phone.getAllCellInfo();
4097 if (info != null) cellInfos.addAll(info);
4098 }
4099 return cellInfos;
4100 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004101
4102 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004103 public List<CellInfo> getAllCellInfo(String callingPackage, String callingFeatureId) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004104 mApp.getSystemService(AppOpsManager.class)
Hall Liu1aa510f2017-11-22 17:40:08 -08004105 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08004106
4107 LocationAccessPolicy.LocationPermissionResult locationResult =
4108 LocationAccessPolicy.checkLocationPermission(mApp,
4109 new LocationAccessPolicy.LocationPermissionQuery.Builder()
4110 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004111 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08004112 .setCallingPid(Binder.getCallingPid())
4113 .setCallingUid(Binder.getCallingUid())
4114 .setMethod("getAllCellInfo")
Nathan Harold5ae50b52019-02-20 15:46:36 -08004115 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08004116 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
4117 .build());
4118 switch (locationResult) {
4119 case DENIED_HARD:
4120 throw new SecurityException("Not allowed to access cell info");
4121 case DENIED_SOFT:
4122 return new ArrayList<>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004123 }
4124
Nathan Haroldf096d982020-11-18 17:18:06 -08004125 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004126 if (targetSdk >= android.os.Build.VERSION_CODES.Q) {
4127 return getCachedCellInfo();
4128 }
4129
Svetoslav Ganov4a9d4482017-06-20 19:53:35 -07004130 if (DBG_LOC) log("getAllCellInfo: is active user");
Narayan Kamathf04b5a12018-01-09 11:47:15 +00004131 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004132 final long identity = Binder.clearCallingIdentity();
4133 try {
4134 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
4135 for (Phone phone : PhoneFactory.getPhones()) {
Nathan Harold3ff88932018-08-14 10:19:49 -07004136 final List<CellInfo> info = (List<CellInfo>) sendRequest(
Nathan Harold92bed182018-10-12 18:16:49 -07004137 CMD_GET_ALL_CELL_INFO, null, phone, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004138 if (info != null) cellInfos.addAll(info);
4139 }
4140 return cellInfos;
4141 } finally {
4142 Binder.restoreCallingIdentity(identity);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004143 }
4144 }
4145
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07004146 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004147 public void requestCellInfoUpdate(int subId, ICellInfoCallback cb, String callingPackage,
4148 String callingFeatureId) {
4149 requestCellInfoUpdateInternal(subId, cb, callingPackage, callingFeatureId,
4150 getWorkSource(Binder.getCallingUid()));
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004151 }
4152
4153 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004154 public void requestCellInfoUpdateWithWorkSource(int subId, ICellInfoCallback cb,
4155 String callingPackage, String callingFeatureId, WorkSource workSource) {
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004156 enforceModifyPermission();
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004157 requestCellInfoUpdateInternal(subId, cb, callingPackage, callingFeatureId, workSource);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004158 }
4159
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004160 private void requestCellInfoUpdateInternal(int subId, ICellInfoCallback cb,
4161 String callingPackage, String callingFeatureId, WorkSource workSource) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004162 mApp.getSystemService(AppOpsManager.class)
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004163 .checkPackage(Binder.getCallingUid(), callingPackage);
Hall Liuf19c44f2018-11-27 14:38:17 -08004164
4165 LocationAccessPolicy.LocationPermissionResult locationResult =
4166 LocationAccessPolicy.checkLocationPermission(mApp,
4167 new LocationAccessPolicy.LocationPermissionQuery.Builder()
4168 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07004169 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08004170 .setCallingPid(Binder.getCallingPid())
4171 .setCallingUid(Binder.getCallingUid())
4172 .setMethod("requestCellInfoUpdate")
Hall Liud60acc92020-05-21 17:09:35 -07004173 .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
4174 .setMinSdkVersionForFine(Build.VERSION_CODES.BASE)
Hall Liuf19c44f2018-11-27 14:38:17 -08004175 .build());
4176 switch (locationResult) {
4177 case DENIED_HARD:
Nathan Haroldf096d982020-11-18 17:18:06 -08004178 if (TelephonyPermissions
4179 .getTargetSdk(mApp, callingPackage) < Build.VERSION_CODES.Q) {
Hall Liud60acc92020-05-21 17:09:35 -07004180 // Safetynet logging for b/154934934
4181 EventLog.writeEvent(0x534e4554, "154934934", Binder.getCallingUid());
4182 }
Hall Liuf19c44f2018-11-27 14:38:17 -08004183 throw new SecurityException("Not allowed to access cell info");
4184 case DENIED_SOFT:
Nathan Haroldf096d982020-11-18 17:18:06 -08004185 if (TelephonyPermissions
4186 .getTargetSdk(mApp, callingPackage) < Build.VERSION_CODES.Q) {
Hall Liud60acc92020-05-21 17:09:35 -07004187 // Safetynet logging for b/154934934
4188 EventLog.writeEvent(0x534e4554, "154934934", Binder.getCallingUid());
4189 }
Nathan Harold5320c422019-05-09 10:26:08 -07004190 try {
4191 cb.onCellInfo(new ArrayList<CellInfo>());
4192 } catch (RemoteException re) {
4193 // Drop without consequences
4194 }
Hall Liuf19c44f2018-11-27 14:38:17 -08004195 return;
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004196 }
4197
Nathan Harolda939a962019-05-09 10:13:47 -07004198
4199 final Phone phone = getPhoneFromSubId(subId);
Nathan Haroldfa8da0f2018-09-27 18:51:29 -07004200 if (phone == null) throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
4201
4202 sendRequestAsync(CMD_REQUEST_CELL_INFO_UPDATE, cb, phone, workSource);
4203 }
4204
4205 @Override
Aishwarya Mallampati0603fb12022-08-24 21:16:56 +00004206 public void setCellInfoListRate(int rateInMillis, int subId) {
Jack Yua8d8cb82017-01-16 10:15:34 -08004207 enforceModifyPermission();
Narayan Kamathf04b5a12018-01-09 11:47:15 +00004208 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004209
4210 final long identity = Binder.clearCallingIdentity();
4211 try {
Aishwarya Mallampati0603fb12022-08-24 21:16:56 +00004212 Phone phone = getPhone(subId);
4213 if (phone == null) {
4214 getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
4215 } else {
4216 phone.setCellInfoListRate(rateInMillis, workSource);
4217 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004218 } finally {
4219 Binder.restoreCallingIdentity(identity);
4220 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004221 }
4222
Shishir Agrawala9f32182016-04-12 12:00:16 -07004223 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004224 public String getImeiForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004225 Phone phone = PhoneFactory.getPhone(slotIndex);
4226 if (phone == null) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004227 return null;
4228 }
Jeff Davidson913390f2018-02-23 17:11:49 -08004229 int subId = phone.getSubId();
Grace Jia0ddb3612021-04-22 13:35:26 -07004230 enforceCallingPackage(callingPackage, Binder.getCallingUid(), "getImeiForSlot");
Michael Groover70af6dc2018-10-01 16:23:15 -07004231 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004232 callingPackage, callingFeatureId, "getImeiForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004233 return null;
4234 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004235
4236 final long identity = Binder.clearCallingIdentity();
4237 try {
4238 return phone.getImei();
4239 } finally {
4240 Binder.restoreCallingIdentity(identity);
4241 }
Shishir Agrawala9f32182016-04-12 12:00:16 -07004242 }
4243
4244 @Override
arunvoddud5c6ce02022-12-11 06:03:12 +00004245 public String getPrimaryImei(String callingPackage, String callingFeatureId) {
4246 enforceCallingPackage(callingPackage, Binder.getCallingUid(), "getPrimaryImei");
4247 if (!checkCallingOrSelfReadDeviceIdentifiersForAnySub(mApp, callingPackage,
4248 callingFeatureId, "getPrimaryImei")) {
4249 throw new SecurityException("Caller does not have permission");
4250 }
4251 final long identity = Binder.clearCallingIdentity();
4252 try {
4253 for (Phone phone : PhoneFactory.getPhones()) {
4254 if (phone.getImeiType() == Phone.IMEI_TYPE_PRIMARY) {
4255 return phone.getImei();
4256 }
4257 }
4258 throw new UnsupportedOperationException("Operation not supported");
4259 } finally {
4260 Binder.restoreCallingIdentity(identity);
4261 }
4262 }
4263
4264 @Override
David Kelly5e06a7f2018-03-12 14:10:59 +00004265 public String getTypeAllocationCodeForSlot(int slotIndex) {
4266 Phone phone = PhoneFactory.getPhone(slotIndex);
4267 String tac = null;
4268 if (phone != null) {
4269 String imei = phone.getImei();
Vala Zadehab005552021-09-21 15:54:29 -07004270 try {
4271 tac = imei == null ? null : imei.substring(0, TYPE_ALLOCATION_CODE_LENGTH);
4272 } catch (IndexOutOfBoundsException e) {
4273 Log.e(LOG_TAG, "IMEI length shorter than upper index.");
4274 return null;
4275 }
David Kelly5e06a7f2018-03-12 14:10:59 +00004276 }
4277 return tac;
4278 }
4279
4280 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004281 public String getMeidForSlot(int slotIndex, String callingPackage, String callingFeatureId) {
Shuo Qian13d89152021-05-10 23:58:11 -07004282 try {
4283 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4284 } catch (SecurityException se) {
4285 EventLog.writeEvent(0x534e4554, "186530496", Binder.getCallingUid());
4286 throw new SecurityException("Package " + callingPackage + " does not belong to "
4287 + Binder.getCallingUid());
4288 }
Jeff Davidson913390f2018-02-23 17:11:49 -08004289 Phone phone = PhoneFactory.getPhone(slotIndex);
4290 if (phone == null) {
Jack Yu2af8d712017-03-15 17:14:14 -07004291 return null;
4292 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004293
Jeff Davidson913390f2018-02-23 17:11:49 -08004294 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07004295 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004296 callingPackage, callingFeatureId, "getMeidForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004297 return null;
4298 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004299
4300 final long identity = Binder.clearCallingIdentity();
4301 try {
4302 return phone.getMeid();
4303 } finally {
4304 Binder.restoreCallingIdentity(identity);
4305 }
Jack Yu2af8d712017-03-15 17:14:14 -07004306 }
4307
4308 @Override
David Kelly5e06a7f2018-03-12 14:10:59 +00004309 public String getManufacturerCodeForSlot(int slotIndex) {
4310 Phone phone = PhoneFactory.getPhone(slotIndex);
4311 String manufacturerCode = null;
4312 if (phone != null) {
4313 String meid = phone.getMeid();
Vala Zadehab005552021-09-21 15:54:29 -07004314 try {
4315 manufacturerCode =
4316 meid == null ? null : meid.substring(0, MANUFACTURER_CODE_LENGTH);
4317 } catch (IndexOutOfBoundsException e) {
4318 Log.e(LOG_TAG, "MEID length shorter than upper index.");
4319 return null;
4320 }
David Kelly5e06a7f2018-03-12 14:10:59 +00004321 }
4322 return manufacturerCode;
4323 }
4324
4325 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004326 public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage,
4327 String callingFeatureId) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004328 Phone phone = PhoneFactory.getPhone(slotIndex);
4329 if (phone == null) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004330 return null;
4331 }
Jeff Davidson913390f2018-02-23 17:11:49 -08004332 int subId = phone.getSubId();
4333 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004334 mApp, subId, callingPackage, callingFeatureId,
4335 "getDeviceSoftwareVersionForSlot")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08004336 return null;
4337 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004338
4339 final long identity = Binder.clearCallingIdentity();
4340 try {
4341 return phone.getDeviceSvn();
4342 } finally {
4343 Binder.restoreCallingIdentity(identity);
4344 }
Shishir Agrawala9f32182016-04-12 12:00:16 -07004345 }
4346
fionaxu43304da2017-11-27 22:51:16 -08004347 @Override
4348 public int getSubscriptionCarrierId(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004349 final long identity = Binder.clearCallingIdentity();
4350 try {
4351 final Phone phone = getPhone(subId);
4352 return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID : phone.getCarrierId();
4353 } finally {
4354 Binder.restoreCallingIdentity(identity);
4355 }
fionaxu43304da2017-11-27 22:51:16 -08004356 }
4357
4358 @Override
4359 public String getSubscriptionCarrierName(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004360 final long identity = Binder.clearCallingIdentity();
4361 try {
4362 final Phone phone = getPhone(subId);
4363 return phone == null ? null : phone.getCarrierName();
4364 } finally {
4365 Binder.restoreCallingIdentity(identity);
4366 }
fionaxu43304da2017-11-27 22:51:16 -08004367 }
4368
calvinpanffe225e2018-11-01 19:43:06 +08004369 @Override
chen xu0026ca62019-03-06 15:28:50 -08004370 public int getSubscriptionSpecificCarrierId(int subId) {
chen xu25637222018-11-04 17:17:00 -08004371 final long identity = Binder.clearCallingIdentity();
4372 try {
4373 final Phone phone = getPhone(subId);
4374 return phone == null ? TelephonyManager.UNKNOWN_CARRIER_ID
chen xu0026ca62019-03-06 15:28:50 -08004375 : phone.getSpecificCarrierId();
chen xu25637222018-11-04 17:17:00 -08004376 } finally {
4377 Binder.restoreCallingIdentity(identity);
4378 }
4379 }
4380
4381 @Override
chen xu0026ca62019-03-06 15:28:50 -08004382 public String getSubscriptionSpecificCarrierName(int subId) {
chen xu25637222018-11-04 17:17:00 -08004383 final long identity = Binder.clearCallingIdentity();
4384 try {
4385 final Phone phone = getPhone(subId);
chen xu0026ca62019-03-06 15:28:50 -08004386 return phone == null ? null : phone.getSpecificCarrierName();
chen xu25637222018-11-04 17:17:00 -08004387 } finally {
4388 Binder.restoreCallingIdentity(identity);
4389 }
4390 }
4391
chen xu651eec72018-11-11 19:03:44 -08004392 @Override
chen xu864e11c2018-12-06 22:10:03 -08004393 public int getCarrierIdFromMccMnc(int slotIndex, String mccmnc, boolean isSubscriptionMccMnc) {
4394 if (!isSubscriptionMccMnc) {
4395 enforceReadPrivilegedPermission("getCarrierIdFromMccMnc");
4396 }
chen xu651eec72018-11-11 19:03:44 -08004397 final Phone phone = PhoneFactory.getPhone(slotIndex);
4398 if (phone == null) {
4399 return TelephonyManager.UNKNOWN_CARRIER_ID;
4400 }
4401 final long identity = Binder.clearCallingIdentity();
4402 try {
4403 return CarrierResolver.getCarrierIdFromMccMnc(phone.getContext(), mccmnc);
4404 } finally {
4405 Binder.restoreCallingIdentity(identity);
4406 }
4407 }
4408
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004409 //
4410 // Internal helper methods.
4411 //
4412
Sanket Padaweee13a9b2016-03-08 17:30:28 -08004413 /**
Grace Jia0ddb3612021-04-22 13:35:26 -07004414 * Make sure the caller is the calling package itself
4415 *
4416 * @throws SecurityException if the caller is not the calling package
4417 */
4418 private void enforceCallingPackage(String callingPackage, int callingUid, String message) {
4419 int packageUid = -1;
Grace Jiadbefca02021-04-26 15:13:31 -07004420 PackageManager pm = mApp.getBaseContext().createContextAsUser(
4421 UserHandle.getUserHandleForUid(callingUid), 0).getPackageManager();
Grace Jia0ddb3612021-04-22 13:35:26 -07004422 try {
Grace Jiadbefca02021-04-26 15:13:31 -07004423 packageUid = pm.getPackageUid(callingPackage, 0);
Grace Jia0ddb3612021-04-22 13:35:26 -07004424 } catch (PackageManager.NameNotFoundException e) {
4425 // packageUid is -1
4426 }
4427 if (packageUid != callingUid) {
4428 throw new SecurityException(message + ": Package " + callingPackage
4429 + " does not belong to " + callingUid);
4430 }
4431 }
4432
4433 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004434 * Make sure the caller has the MODIFY_PHONE_STATE permission.
4435 *
4436 * @throws SecurityException if the caller does not have the required permission
4437 */
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004438 @VisibleForTesting
4439 public void enforceModifyPermission() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004440 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
4441 }
4442
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004443 /**
arunvoddud7401012022-12-15 16:08:12 +00004444 * Make sure the caller has the READ_PHONE_STATE permission.
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004445 *
4446 * @throws SecurityException if the caller does not have the required permission
4447 */
4448 @VisibleForTesting
4449 public void enforceReadPermission() {
arunvoddud7401012022-12-15 16:08:12 +00004450 enforceReadPermission(null);
4451 }
4452
4453 /**
4454 * Make sure the caller has the READ_PHONE_STATE permissions.
4455 *
4456 * @throws SecurityException if the caller does not have the READ_PHONE_STATE permission.
4457 */
4458 @VisibleForTesting
4459 public void enforceReadPermission(String msg) {
4460 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, msg);
Gil Cukierman1c0eb932022-12-06 22:28:24 +00004461 }
4462
Shuo Qian3b6ee772019-11-13 17:43:31 -08004463 private void enforceActiveEmergencySessionPermission() {
4464 mApp.enforceCallingOrSelfPermission(
4465 android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
4466 }
4467
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004468 /**
4469 * Make sure the caller has the CALL_PHONE permission.
4470 *
4471 * @throws SecurityException if the caller does not have the required permission
4472 */
4473 private void enforceCallPermission() {
4474 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
4475 }
4476
paulhu5a773602019-08-23 19:17:33 +08004477 private void enforceSettingsPermission() {
4478 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.NETWORK_SETTINGS, null);
Stuart Scott8eef64f2015-04-08 15:13:54 -07004479 }
4480
Michele Berionne5e411512020-11-13 02:36:59 +00004481 private void enforceRebootPermission() {
4482 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
4483 }
4484
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +00004485 /**
4486 * Make sure the caller has SATELLITE_COMMUNICATION permission.
4487 * @param message - log message to print.
4488 * @throws SecurityException if the caller does not have the required permission
4489 */
4490 private void enforceSatelliteCommunicationPermission(String message) {
4491 mApp.enforceCallingOrSelfPermission(permission.SATELLITE_COMMUNICATION, message);
4492 }
4493
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004494 private String createTelUrl(String number) {
4495 if (TextUtils.isEmpty(number)) {
4496 return null;
4497 }
4498
Jake Hambye994d462014-02-03 13:10:13 -08004499 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004500 }
4501
Ihab Awadf9e92732013-12-05 18:02:52 -08004502 private static void log(String msg) {
Ling Ma83dc5ea2023-01-12 15:06:04 -08004503 Log.d(LOG_TAG, msg);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004504 }
4505
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07004506 private static void logv(String msg) {
4507 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
4508 }
4509
Ihab Awadf9e92732013-12-05 18:02:52 -08004510 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004511 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
4512 }
4513
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004514 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004515 public int getActivePhoneType() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07004516 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07004517 }
4518
Sanket Padawe356d7632015-06-22 14:03:32 -07004519 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07004520 public int getActivePhoneTypeForSlot(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004521 final long identity = Binder.clearCallingIdentity();
4522 try {
4523 final Phone phone = PhoneFactory.getPhone(slotIndex);
4524 if (phone == null) {
4525 return PhoneConstants.PHONE_TYPE_NONE;
4526 } else {
4527 return phone.getPhoneType();
4528 }
4529 } finally {
4530 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004531 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004532 }
4533
4534 /**
4535 * Returns the CDMA ERI icon index to display
4536 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004537 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004538 public int getCdmaEriIconIndex(String callingPackage, String callingFeatureId) {
4539 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage,
4540 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07004541 }
4542
Sanket Padawe356d7632015-06-22 14:03:32 -07004543 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004544 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage,
4545 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004546 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004547 mApp, subId, callingPackage, callingFeatureId,
4548 "getCdmaEriIconIndexForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004549 return -1;
4550 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004551
4552 final long identity = Binder.clearCallingIdentity();
4553 try {
4554 final Phone phone = getPhone(subId);
4555 if (phone != null) {
4556 return phone.getCdmaEriIconIndex();
4557 } else {
4558 return -1;
4559 }
4560 } finally {
4561 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004562 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004563 }
4564
4565 /**
4566 * Returns the CDMA ERI icon mode,
4567 * 0 - ON
4568 * 1 - FLASHING
4569 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004570 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004571 public int getCdmaEriIconMode(String callingPackage, String callingFeatureId) {
4572 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage,
4573 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07004574 }
4575
Sanket Padawe356d7632015-06-22 14:03:32 -07004576 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004577 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage,
4578 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004579 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004580 mApp, subId, callingPackage, callingFeatureId,
4581 "getCdmaEriIconModeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004582 return -1;
4583 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004584
4585 final long identity = Binder.clearCallingIdentity();
4586 try {
4587 final Phone phone = getPhone(subId);
4588 if (phone != null) {
4589 return phone.getCdmaEriIconMode();
4590 } else {
4591 return -1;
4592 }
4593 } finally {
4594 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004595 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004596 }
4597
4598 /**
4599 * Returns the CDMA ERI text,
4600 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004601 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004602 public String getCdmaEriText(String callingPackage, String callingFeatureId) {
4603 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage,
4604 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07004605 }
4606
Sanket Padawe356d7632015-06-22 14:03:32 -07004607 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004608 public String getCdmaEriTextForSubscriber(int subId, String callingPackage,
4609 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004610 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004611 mApp, subId, callingPackage, callingFeatureId,
4612 "getCdmaEriIconTextForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07004613 return null;
4614 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004615
4616 final long identity = Binder.clearCallingIdentity();
4617 try {
4618 final Phone phone = getPhone(subId);
4619 if (phone != null) {
4620 return phone.getCdmaEriText();
4621 } else {
4622 return null;
4623 }
4624 } finally {
4625 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004626 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004627 }
4628
4629 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07004630 * Returns the CDMA MDN.
4631 */
Sanket Padawe356d7632015-06-22 14:03:32 -07004632 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07004633 public String getCdmaMdn(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004634 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4635 mApp, subId, "getCdmaMdn");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004636
4637 final long identity = Binder.clearCallingIdentity();
4638 try {
4639 final Phone phone = getPhone(subId);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004640 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004641 return phone.getLine1Number();
4642 } else {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004643 loge("getCdmaMdn: no phone found. Invalid subId: " + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004644 return null;
4645 }
4646 } finally {
4647 Binder.restoreCallingIdentity(identity);
Junda Liuca05d5d2014-08-14 22:36:34 -07004648 }
4649 }
4650
4651 /**
4652 * Returns the CDMA MIN.
4653 */
Sanket Padawe356d7632015-06-22 14:03:32 -07004654 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07004655 public String getCdmaMin(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004656 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4657 mApp, subId, "getCdmaMin");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004658
4659 final long identity = Binder.clearCallingIdentity();
4660 try {
4661 final Phone phone = getPhone(subId);
4662 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
4663 return phone.getCdmaMin();
4664 } else {
4665 return null;
4666 }
4667 } finally {
4668 Binder.restoreCallingIdentity(identity);
Junda Liuca05d5d2014-08-14 22:36:34 -07004669 }
4670 }
4671
Hall Liud892bec2018-11-30 14:51:45 -08004672 @Override
4673 public void requestNumberVerification(PhoneNumberRange range, long timeoutMillis,
4674 INumberVerificationCallback callback, String callingPackage) {
4675 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
4676 != PERMISSION_GRANTED) {
4677 throw new SecurityException("Caller must hold the MODIFY_PHONE_STATE permission");
4678 }
4679 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
4680
4681 String authorizedPackage = NumberVerificationManager.getAuthorizedPackage(mApp);
4682 if (!TextUtils.equals(callingPackage, authorizedPackage)) {
Hall Liub9d8feb2021-01-13 10:28:04 -08004683 throw new SecurityException("Calling package must be configured in the device config: "
4684 + "calling package: " + callingPackage
4685 + ", configured package: " + authorizedPackage);
Hall Liud892bec2018-11-30 14:51:45 -08004686 }
4687
4688 if (range == null) {
4689 throw new NullPointerException("Range must be non-null");
4690 }
4691
4692 timeoutMillis = Math.min(timeoutMillis,
Hall Liubd069e32019-02-28 18:56:30 -08004693 TelephonyManager.getMaxNumberVerificationTimeoutMillis());
Hall Liud892bec2018-11-30 14:51:45 -08004694
4695 NumberVerificationManager.getInstance().requestVerification(range, callback, timeoutMillis);
4696 }
4697
Junda Liuca05d5d2014-08-14 22:36:34 -07004698 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004699 * Returns true if CDMA provisioning needs to run.
4700 */
4701 public boolean needsOtaServiceProvisioning() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004702 final long identity = Binder.clearCallingIdentity();
4703 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004704 return getDefaultPhone().needsOtaServiceProvisioning();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004705 } finally {
4706 Binder.restoreCallingIdentity(identity);
4707 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004708 }
4709
4710 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08004711 * Sets the voice mail number of a given subId.
4712 */
4713 @Override
4714 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08004715 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
4716 mApp, subId, "setVoiceMailNumber");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004717
4718 final long identity = Binder.clearCallingIdentity();
4719 try {
4720 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
4721 new Pair<String, String>(alphaTag, number), new Integer(subId));
4722 return success;
4723 } finally {
4724 Binder.restoreCallingIdentity(identity);
4725 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08004726 }
4727
Ta-wei Yen87c49842016-05-13 21:19:52 -07004728 @Override
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004729 public Bundle getVisualVoicemailSettings(String callingPackage, int subId) {
4730 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07004731 TelecomManager tm = mApp.getSystemService(TelecomManager.class);
4732 String systemDialer = tm.getSystemDialerPackage();
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004733 if (!TextUtils.equals(callingPackage, systemDialer)) {
4734 throw new SecurityException("caller must be system dialer");
4735 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004736
4737 final long identity = Binder.clearCallingIdentity();
4738 try {
4739 PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(subId);
4740 if (phoneAccountHandle == null) {
4741 return null;
4742 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004743 return VisualVoicemailSettingsUtil.dump(mApp, phoneAccountHandle);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004744 } finally {
4745 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004746 }
Ta-wei Yenc9df0432017-04-17 17:09:07 -07004747 }
4748
4749 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004750 public String getVisualVoicemailPackageName(String callingPackage, String callingFeatureId,
4751 int subId) {
Ta-wei Yendca928f2017-01-10 16:17:08 -08004752 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jeff Davidson7e17e312018-02-13 18:17:36 -08004753 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004754 mApp, subId, callingPackage, callingFeatureId,
4755 "getVisualVoicemailPackageName")) {
Ta-wei Yendca928f2017-01-10 16:17:08 -08004756 return null;
4757 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004758
Jeff Davidsona8e4e242018-03-15 17:16:18 -07004759 final long identity = Binder.clearCallingIdentity();
4760 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004761 return RemoteVvmTaskManager.getRemotePackage(mApp, subId).getPackageName();
Jeff Davidsona8e4e242018-03-15 17:16:18 -07004762 } finally {
4763 Binder.restoreCallingIdentity(identity);
4764 }
Ta-wei Yendca928f2017-01-10 16:17:08 -08004765 }
4766
4767 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07004768 public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
4769 VisualVoicemailSmsFilterSettings settings) {
4770 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004771
4772 final long identity = Binder.clearCallingIdentity();
4773 try {
4774 VisualVoicemailSmsFilterConfig.enableVisualVoicemailSmsFilter(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004775 mApp, callingPackage, subId, settings);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004776 } finally {
4777 Binder.restoreCallingIdentity(identity);
4778 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07004779 }
4780
4781 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07004782 public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
4783 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004784
4785 final long identity = Binder.clearCallingIdentity();
4786 try {
4787 VisualVoicemailSmsFilterConfig.disableVisualVoicemailSmsFilter(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004788 mApp, callingPackage, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004789 } finally {
4790 Binder.restoreCallingIdentity(identity);
4791 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07004792 }
4793
4794 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07004795 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
4796 String callingPackage, int subId) {
4797 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004798
4799 final long identity = Binder.clearCallingIdentity();
4800 try {
4801 return VisualVoicemailSmsFilterConfig.getVisualVoicemailSmsFilterSettings(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004802 mApp, callingPackage, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004803 } finally {
4804 Binder.restoreCallingIdentity(identity);
4805 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07004806 }
4807
4808 @Override
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004809 public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07004810 enforceReadPrivilegedPermission("getActiveVisualVoicemailSmsFilterSettings");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004811
4812 final long identity = Binder.clearCallingIdentity();
4813 try {
4814 return VisualVoicemailSmsFilterConfig.getActiveVisualVoicemailSmsFilterSettings(
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004815 mApp, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004816 } finally {
4817 Binder.restoreCallingIdentity(identity);
4818 }
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004819 }
4820
4821 @Override
Philip P. Moltmann2f6f8ce2020-03-18 18:17:02 -07004822 public void sendVisualVoicemailSmsForSubscriber(String callingPackage,
4823 String callingAttributionTag, int subId, String number, int port, String text,
4824 PendingIntent sentIntent) {
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004825 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen527a9c02017-01-06 15:29:25 -08004826 enforceVisualVoicemailPackage(callingPackage, subId);
Ta-wei Yen30a69c82016-12-27 14:52:32 -08004827 enforceSendSmsPermission();
Amit Mahajandccb3f12019-05-13 13:48:32 -07004828 SmsController smsController = PhoneFactory.getSmsController();
Philip P. Moltmann2f6f8ce2020-03-18 18:17:02 -07004829 smsController.sendVisualVoicemailSmsForSubscriber(callingPackage, callingAttributionTag,
4830 subId, number, port, text, sentIntent);
Ta-wei Yen87c49842016-05-13 21:19:52 -07004831 }
Amit Mahajandccb3f12019-05-13 13:48:32 -07004832
Shishir Agrawal76d5da92014-11-09 16:17:25 -08004833 /**
fionaxu0152e512016-11-14 13:36:14 -08004834 * Sets the voice activation state of a given subId.
4835 */
4836 @Override
4837 public void setVoiceActivationState(int subId, int activationState) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004838 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4839 mApp, subId, "setVoiceActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004840
4841 final long identity = Binder.clearCallingIdentity();
4842 try {
4843 final Phone phone = getPhone(subId);
4844 if (phone != null) {
4845 phone.setVoiceActivationState(activationState);
4846 } else {
4847 loge("setVoiceActivationState fails with invalid subId: " + subId);
4848 }
4849 } finally {
4850 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004851 }
4852 }
4853
4854 /**
4855 * Sets the data activation state of a given subId.
4856 */
4857 @Override
4858 public void setDataActivationState(int subId, int activationState) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08004859 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
4860 mApp, subId, "setDataActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004861
4862 final long identity = Binder.clearCallingIdentity();
4863 try {
4864 final Phone phone = getPhone(subId);
4865 if (phone != null) {
4866 phone.setDataActivationState(activationState);
4867 } else {
Taesu Leef8fbed92019-10-07 18:47:02 +09004868 loge("setDataActivationState fails with invalid subId: " + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004869 }
4870 } finally {
4871 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004872 }
4873 }
4874
4875 /**
4876 * Returns the voice activation state of a given subId.
4877 */
4878 @Override
4879 public int getVoiceActivationState(int subId, String callingPackage) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07004880 enforceReadPrivilegedPermission("getVoiceActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004881
fionaxu0152e512016-11-14 13:36:14 -08004882 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004883 final long identity = Binder.clearCallingIdentity();
4884 try {
4885 if (phone != null) {
4886 return phone.getVoiceActivationState();
4887 } else {
4888 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
4889 }
4890 } finally {
4891 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004892 }
4893 }
4894
4895 /**
4896 * Returns the data activation state of a given subId.
4897 */
4898 @Override
4899 public int getDataActivationState(int subId, String callingPackage) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07004900 enforceReadPrivilegedPermission("getDataActivationState");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004901
fionaxu0152e512016-11-14 13:36:14 -08004902 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004903 final long identity = Binder.clearCallingIdentity();
4904 try {
4905 if (phone != null) {
4906 return phone.getDataActivationState();
4907 } else {
4908 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
4909 }
4910 } finally {
4911 Binder.restoreCallingIdentity(identity);
fionaxu0152e512016-11-14 13:36:14 -08004912 }
4913 }
4914
4915 /**
Wink Saville36469e72014-06-11 15:17:00 -07004916 * Returns the unread count of voicemails for a subId
4917 */
Sanket Padawe356d7632015-06-22 14:03:32 -07004918 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004919 public int getVoiceMessageCountForSubscriber(int subId, String callingPackage,
4920 String callingFeatureId) {
Brad Ebingerf7664ba2018-11-29 12:43:38 -08004921 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07004922 mApp, subId, callingPackage, callingFeatureId,
4923 "getVoiceMessageCountForSubscriber")) {
Brad Ebingerf7664ba2018-11-29 12:43:38 -08004924 return 0;
4925 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004926 final long identity = Binder.clearCallingIdentity();
4927 try {
4928 final Phone phone = getPhone(subId);
4929 if (phone != null) {
4930 return phone.getVoiceMessageCount();
4931 } else {
4932 return 0;
4933 }
4934 } finally {
4935 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07004936 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07004937 }
4938
4939 /**
Thomas Nguyen8ee49682023-02-01 11:46:09 -08004940 * returns true, if the device is in a state where both voice and data
4941 * are supported simultaneously. This can change based on location or network condition.
pkanwar8a4dcfb2017-01-19 13:43:16 -08004942 */
4943 @Override
4944 public boolean isConcurrentVoiceAndDataAllowed(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004945 final long identity = Binder.clearCallingIdentity();
4946 try {
4947 final Phone phone = getPhone(subId);
4948 return (phone == null ? false : phone.isConcurrentVoiceAndDataAllowed());
4949 } finally {
4950 Binder.restoreCallingIdentity(identity);
4951 }
pkanwar8a4dcfb2017-01-19 13:43:16 -08004952 }
4953
4954 /**
fionaxu235cc5e2017-03-06 22:25:57 -08004955 * Send the dialer code if called from the current default dialer or the caller has
4956 * carrier privilege.
4957 * @param inputCode The dialer code to send
4958 */
4959 @Override
4960 public void sendDialerSpecialCode(String callingPackage, String inputCode) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004961 final Phone defaultPhone = getDefaultPhone();
fionaxu235cc5e2017-03-06 22:25:57 -08004962 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07004963 TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
4964 String defaultDialer = tm.getDefaultDialerPackage();
fionaxu235cc5e2017-03-06 22:25:57 -08004965 if (!TextUtils.equals(callingPackage, defaultDialer)) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08004966 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
Jeff Davidson7e17e312018-02-13 18:17:36 -08004967 getDefaultSubscription(), "sendDialerSpecialCode");
fionaxu235cc5e2017-03-06 22:25:57 -08004968 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004969
4970 final long identity = Binder.clearCallingIdentity();
4971 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08004972 defaultPhone.sendDialerSpecialCode(inputCode);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08004973 } finally {
4974 Binder.restoreCallingIdentity(identity);
4975 }
fionaxu235cc5e2017-03-06 22:25:57 -08004976 }
4977
Pengquan Menga1bb6272018-09-06 09:59:22 -07004978 @Override
4979 public int getNetworkSelectionMode(int subId) {
shilufc958392020-01-20 11:36:01 -08004980 TelephonyPermissions
Thomas Nguyen8ee49682023-02-01 11:46:09 -08004981 .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
4982 mApp, subId, "getNetworkSelectionMode");
shilufc958392020-01-20 11:36:01 -08004983 final long identity = Binder.clearCallingIdentity();
4984 try {
4985 if (!isActiveSubscription(subId)) {
4986 return TelephonyManager.NETWORK_SELECTION_MODE_UNKNOWN;
4987 }
4988 return (int) sendRequest(CMD_GET_NETWORK_SELECTION_MODE, null /* argument */, subId);
4989 } finally {
4990 Binder.restoreCallingIdentity(identity);
Pengquan Menge92a50d2018-09-21 15:54:48 -07004991 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07004992 }
4993
Brad Ebinger35c841c2018-10-01 10:40:55 -07004994 @Override
Brad Ebingerb2b65522019-03-15 13:48:47 -07004995 public boolean isInEmergencySmsMode() {
4996 enforceReadPrivilegedPermission("isInEmergencySmsMode");
4997 final long identity = Binder.clearCallingIdentity();
4998 try {
4999 for (Phone phone : PhoneFactory.getPhones()) {
5000 if (phone.isInEmergencySmsMode()) {
5001 return true;
5002 }
5003 }
5004 } finally {
5005 Binder.restoreCallingIdentity(identity);
5006 }
5007 return false;
5008 }
5009
shilu366312e2019-12-17 09:28:10 -08005010 /**
5011 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5012 * @param subId The subscription to use to check the configuration.
5013 * @param c The callback that will be used to send the result.
5014 */
Brad Ebingerb2b65522019-03-15 13:48:47 -07005015 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005016 public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback c)
5017 throws RemoteException {
Nathan Harold62c68512021-04-06 11:26:02 -07005018 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005019 mApp, subId, "registerImsRegistrationCallback");
Brad Ebingera2628302022-02-18 03:44:55 +00005020
5021 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5022 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5023 "IMS not available on device.");
5024 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005025 final long token = Binder.clearCallingIdentity();
5026 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005027 int slotId = getSlotIndexOrException(subId);
5028 verifyImsMmTelConfiguredOrThrow(slotId);
joonhunshin49f0aed2022-08-05 08:33:05 +00005029
5030 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5031 if (controller != null) {
5032 ImsManager imsManager = controller.getImsManager(subId);
5033 if (imsManager != null) {
5034 imsManager.addRegistrationCallbackForSubscription(c, subId);
5035 } else {
5036 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
5037 }
5038 } else {
5039 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5040 }
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005041 } catch (ImsException e) {
5042 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005043 } finally {
5044 Binder.restoreCallingIdentity(token);
5045 }
5046 }
5047
shilu366312e2019-12-17 09:28:10 -08005048 /**
5049 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5050 * @param subId The subscription to use to check the configuration.
5051 * @param c The callback that will be used to send the result.
5052 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005053 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005054 public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c) {
Nathan Harold62c68512021-04-06 11:26:02 -07005055 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005056 mApp, subId, "unregisterImsRegistrationCallback");
Brad Ebinger4ae57f92019-01-09 16:51:30 -08005057 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5058 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5059 }
Meng Wangafbc5852019-09-19 17:37:13 -07005060 final long token = Binder.clearCallingIdentity();
joonhunshin49f0aed2022-08-05 08:33:05 +00005061
Meng Wangafbc5852019-09-19 17:37:13 -07005062 try {
joonhunshin49f0aed2022-08-05 08:33:05 +00005063 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5064 if (controller != null) {
5065 ImsManager imsManager = controller.getImsManager(subId);
5066 if (imsManager != null) {
5067 imsManager.removeRegistrationCallbackForSubscription(c, subId);
5068 } else {
5069 Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
5070 + "is inactive, ignoring unregister.");
5071 // If the ImsManager is not valid, just return, since the callback
5072 // will already have been removed internally.
5073 }
5074 }
Meng Wangafbc5852019-09-19 17:37:13 -07005075 } finally {
5076 Binder.restoreCallingIdentity(token);
5077 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005078 }
5079
Brad Ebingera34a6c22019-10-22 17:36:18 -07005080 /**
5081 * Get the IMS service registration state for the MmTelFeature associated with this sub id.
5082 */
5083 @Override
5084 public void getImsMmTelRegistrationState(int subId, IIntegerConsumer consumer) {
5085 enforceReadPrivilegedPermission("getImsMmTelRegistrationState");
5086 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5087 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5088 "IMS not available on device.");
5089 }
5090 final long token = Binder.clearCallingIdentity();
5091 try {
5092 Phone phone = getPhone(subId);
5093 if (phone == null) {
5094 Log.w(LOG_TAG, "getImsMmTelRegistrationState: called with an invalid subscription '"
5095 + subId + "'");
5096 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5097 }
5098 phone.getImsRegistrationState(regState -> {
5099 try {
5100 consumer.accept((regState == null)
5101 ? RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED : regState);
5102 } catch (RemoteException e) {
5103 // Ignore if the remote process is no longer available to call back.
5104 Log.w(LOG_TAG, "getImsMmTelRegistrationState: callback not available.");
5105 }
5106 });
5107 } finally {
5108 Binder.restoreCallingIdentity(token);
5109 }
5110 }
5111
5112 /**
5113 * Get the transport type for the IMS service registration state.
5114 */
5115 @Override
5116 public void getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer) {
Nathan Harold62c68512021-04-06 11:26:02 -07005117 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005118 mApp, subId, "getImsMmTelRegistrationTransportType");
Brad Ebingera34a6c22019-10-22 17:36:18 -07005119 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5120 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5121 "IMS not available on device.");
5122 }
5123 final long token = Binder.clearCallingIdentity();
5124 try {
5125 Phone phone = getPhone(subId);
5126 if (phone == null) {
5127 Log.w(LOG_TAG, "getImsMmTelRegistrationState: called with an invalid subscription '"
5128 + subId + "'");
5129 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5130 }
5131 phone.getImsRegistrationTech(regTech -> {
5132 // Convert registration tech from ImsRegistrationImplBase -> RegistrationManager
5133 int regTechConverted = (regTech == null)
5134 ? ImsRegistrationImplBase.REGISTRATION_TECH_NONE : regTech;
5135 regTechConverted = RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(
5136 regTechConverted);
5137 try {
5138 consumer.accept(regTechConverted);
5139 } catch (RemoteException e) {
5140 // Ignore if the remote process is no longer available to call back.
5141 Log.w(LOG_TAG, "getImsMmTelRegistrationState: callback not available.");
5142 }
5143 });
5144 } finally {
5145 Binder.restoreCallingIdentity(token);
5146 }
5147 }
5148
shilu366312e2019-12-17 09:28:10 -08005149 /**
5150 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5151 * @param subId The subscription to use to check the configuration.
5152 * @param c The callback that will be used to send the result.
5153 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005154 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005155 public void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c)
5156 throws RemoteException {
Nathan Harold62c68512021-04-06 11:26:02 -07005157 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005158 mApp, subId, "registerMmTelCapabilityCallback");
Brad Ebingera2628302022-02-18 03:44:55 +00005159 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5160 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5161 "IMS not available on device.");
5162 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005163 final long token = Binder.clearCallingIdentity();
5164 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005165 int slotId = getSlotIndexOrException(subId);
5166 verifyImsMmTelConfiguredOrThrow(slotId);
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005167
5168 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5169 if (controller != null) {
5170 ImsManager imsManager = controller.getImsManager(subId);
5171 if (imsManager != null) {
5172 imsManager.addCapabilitiesCallbackForSubscription(c, subId);
5173 } else {
5174 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
5175 }
5176 } else {
5177 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5178 }
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005179 } catch (ImsException e) {
5180 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005181 } finally {
5182 Binder.restoreCallingIdentity(token);
5183 }
5184 }
5185
shilu366312e2019-12-17 09:28:10 -08005186 /**
5187 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5188 * @param subId The subscription to use to check the configuration.
5189 * @param c The callback that will be used to send the result.
5190 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005191 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005192 public void unregisterMmTelCapabilityCallback(int subId, IImsCapabilityCallback c) {
Nathan Harold62c68512021-04-06 11:26:02 -07005193 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005194 mApp, subId, "unregisterMmTelCapabilityCallback");
Brad Ebinger4ae57f92019-01-09 16:51:30 -08005195 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5196 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5197 }
Meng Wangafbc5852019-09-19 17:37:13 -07005198
5199 final long token = Binder.clearCallingIdentity();
5200 try {
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005201 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5202 if (controller != null) {
5203 ImsManager imsManager = controller.getImsManager(subId);
5204 if (imsManager != null) {
5205 imsManager.removeCapabilitiesCallbackForSubscription(c, subId);
5206 } else {
5207 Log.i(LOG_TAG, "unregisterMmTelCapabilityCallback: " + subId
5208 + " is inactive, ignoring unregister.");
5209 // If the ImsManager is not valid, just return, since the callback
5210 // will already have been removed internally.
5211 }
5212 }
Meng Wangafbc5852019-09-19 17:37:13 -07005213 } finally {
5214 Binder.restoreCallingIdentity(token);
5215 }
Brad Ebinger35c841c2018-10-01 10:40:55 -07005216 }
5217
5218 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005219 public boolean isCapable(int subId, int capability, int regTech) {
5220 enforceReadPrivilegedPermission("isCapable");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005221 final long token = Binder.clearCallingIdentity();
5222 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005223 int slotId = getSlotIndexOrException(subId);
5224 verifyImsMmTelConfiguredOrThrow(slotId);
5225 return ImsManager.getInstance(mApp, slotId).queryMmTelCapability(capability, regTech);
5226 } catch (com.android.ims.ImsException e) {
5227 Log.w(LOG_TAG, "IMS isCapable - service unavailable: " + e.getMessage());
5228 return false;
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005229 } catch (ImsException e) {
Brad Ebinger6b5ac222019-02-04 14:36:52 -08005230 Log.i(LOG_TAG, "isCapable: " + subId + " is inactive, returning false.");
5231 return false;
Brad Ebinger35c841c2018-10-01 10:40:55 -07005232 } finally {
5233 Binder.restoreCallingIdentity(token);
5234 }
5235 }
5236
5237 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005238 public boolean isAvailable(int subId, int capability, int regTech) {
5239 enforceReadPrivilegedPermission("isAvailable");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005240 final long token = Binder.clearCallingIdentity();
5241 try {
5242 Phone phone = getPhone(subId);
5243 if (phone == null) return false;
5244 return phone.isImsCapabilityAvailable(capability, regTech);
Daniel Bright5e40e4e2020-03-11 16:35:39 -07005245 } catch (com.android.ims.ImsException e) {
5246 Log.w(LOG_TAG, "IMS isAvailable - service unavailable: " + e.getMessage());
5247 return false;
Brad Ebinger35c841c2018-10-01 10:40:55 -07005248 } finally {
5249 Binder.restoreCallingIdentity(token);
5250 }
5251 }
5252
Brad Ebingerbc7dd582019-10-17 17:03:22 -07005253 /**
5254 * Determines if the MmTel feature capability is supported by the carrier configuration for this
5255 * subscription.
5256 * @param subId The subscription to use to check the configuration.
5257 * @param callback The callback that will be used to send the result.
5258 * @param capability The MmTelFeature capability that will be used to send the result.
5259 * @param transportType The transport type of the MmTelFeature capability.
5260 */
5261 @Override
5262 public void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability,
5263 int transportType) {
5264 enforceReadPrivilegedPermission("isMmTelCapabilitySupported");
Brad Ebingera2628302022-02-18 03:44:55 +00005265 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
5266 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5267 "IMS not available on device.");
5268 }
Brad Ebingerbc7dd582019-10-17 17:03:22 -07005269 final long token = Binder.clearCallingIdentity();
5270 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005271 int slotId = getSlotIndex(subId);
5272 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5273 Log.w(LOG_TAG, "isMmTelCapabilitySupported: called with an inactive subscription '"
5274 + subId + "'");
5275 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
5276 }
5277 verifyImsMmTelConfiguredOrThrow(slotId);
5278 ImsManager.getInstance(mApp, slotId).isSupported(capability,
5279 transportType, aBoolean -> {
5280 try {
5281 callback.accept((aBoolean == null) ? 0 : (aBoolean ? 1 : 0));
5282 } catch (RemoteException e) {
5283 Log.w(LOG_TAG, "isMmTelCapabilitySupported: remote caller is not "
5284 + "running. Ignore");
5285 }
5286 });
Brad Ebinger919631e2021-06-02 17:46:35 -07005287 } catch (ImsException e) {
5288 throw new ServiceSpecificException(e.getCode());
Brad Ebingerbc7dd582019-10-17 17:03:22 -07005289 } finally {
5290 Binder.restoreCallingIdentity(token);
5291 }
5292 }
5293
shilu366312e2019-12-17 09:28:10 -08005294 /**
5295 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5296 * @param subId The subscription to use to check the configuration.
5297 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005298 @Override
5299 public boolean isAdvancedCallingSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005300 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005301 mApp, subId, "isAdvancedCallingSettingEnabled");
shilu366312e2019-12-17 09:28:10 -08005302
Brad Ebinger35c841c2018-10-01 10:40:55 -07005303 final long token = Binder.clearCallingIdentity();
5304 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005305 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005306 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005307 return ImsManager.getInstance(mApp, slotId).isEnhanced4gLteModeSettingEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005308 } catch (ImsException e) {
5309 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005310 } finally {
5311 Binder.restoreCallingIdentity(token);
5312 }
5313 }
5314
5315 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005316 public void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005317 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005318 "setAdvancedCallingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005319 final long identity = Binder.clearCallingIdentity();
5320 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005321 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005322 // This setting doesn't require an active ImsService connection, so do not verify. The
5323 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005324 ImsManager.getInstance(mApp, slotId).setEnhanced4gLteModeSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005325 } catch (ImsException e) {
5326 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005327 } finally {
5328 Binder.restoreCallingIdentity(identity);
5329 }
5330 }
5331
shilu366312e2019-12-17 09:28:10 -08005332 /**
5333 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5334 * @param subId The subscription to use to check the configuration.
5335 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005336 @Override
Brad Ebinger9878b0b2018-11-08 17:43:22 -08005337 public boolean isVtSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005338 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005339 mApp, subId, "isVtSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005340 final long identity = Binder.clearCallingIdentity();
5341 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005342 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005343 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005344 return ImsManager.getInstance(mApp, slotId).isVtEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005345 } catch (ImsException e) {
5346 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005347 } finally {
5348 Binder.restoreCallingIdentity(identity);
5349 }
5350 }
5351
5352 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005353 public void setVtSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005354 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005355 "setVtSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005356 final long identity = Binder.clearCallingIdentity();
5357 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005358 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005359 // This setting doesn't require an active ImsService connection, so do not verify. The
5360 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005361 ImsManager.getInstance(mApp, slotId).setVtSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005362 } catch (ImsException e) {
5363 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005364 } finally {
5365 Binder.restoreCallingIdentity(identity);
5366 }
5367 }
5368
shilu366312e2019-12-17 09:28:10 -08005369 /**
5370 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5371 * @param subId The subscription to use to check the configuration.
5372 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005373 @Override
5374 public boolean isVoWiFiSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005375 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005376 mApp, subId, "isVoWiFiSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005377 final long identity = Binder.clearCallingIdentity();
5378 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005379 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005380 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005381 return ImsManager.getInstance(mApp, slotId).isWfcEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005382 } catch (ImsException e) {
5383 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005384 } finally {
5385 Binder.restoreCallingIdentity(identity);
5386 }
5387 }
5388
5389 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005390 public void setVoWiFiSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005391 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005392 "setVoWiFiSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005393 final long identity = Binder.clearCallingIdentity();
5394 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005395 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005396 // This setting doesn't require an active ImsService connection, so do not verify. The
5397 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005398 ImsManager.getInstance(mApp, slotId).setWfcSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005399 } catch (ImsException e) {
5400 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005401 } finally {
5402 Binder.restoreCallingIdentity(identity);
5403 }
5404 }
5405
shilu366312e2019-12-17 09:28:10 -08005406 /**
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005407 * @return true if the user's setting for Voice over Cross SIM is enabled and false if it is not
5408 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5409 * @param subId The subscription to use to check the configuration.
5410 */
5411 @Override
5412 public boolean isCrossSimCallingEnabledByUser(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005413 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005414 mApp, subId, "isCrossSimCallingEnabledByUser");
5415 final long identity = Binder.clearCallingIdentity();
5416 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005417 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005418 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005419 return ImsManager.getInstance(mApp, slotId).isCrossSimCallingEnabledByUser();
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005420 } catch (ImsException e) {
5421 throw new ServiceSpecificException(e.getCode());
5422 } finally {
5423 Binder.restoreCallingIdentity(identity);
5424 }
5425 }
5426
5427 /**
5428 * Sets the user's setting for whether or not Voice over Cross SIM is enabled.
5429 * Requires MODIFY_PHONE_STATE permission.
5430 * @param subId The subscription to use to check the configuration.
5431 * @param isEnabled true if the user's setting for Voice over Cross SIM is enabled,
5432 * false otherwise
5433 */
5434 @Override
5435 public void setCrossSimCallingEnabled(int subId, boolean isEnabled) {
5436 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5437 "setCrossSimCallingEnabled");
5438 final long identity = Binder.clearCallingIdentity();
5439 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005440 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005441 // This setting doesn't require an active ImsService connection, so do not verify. The
5442 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005443 ImsManager.getInstance(mApp, slotId).setCrossSimCallingEnabled(isEnabled);
Sooraj Sasindrane655add2020-11-23 19:40:38 -08005444 } catch (ImsException e) {
5445 throw new ServiceSpecificException(e.getCode());
5446 } finally {
5447 Binder.restoreCallingIdentity(identity);
5448 }
5449 }
5450
5451 /**
shilu366312e2019-12-17 09:28:10 -08005452 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5453 * @param subId The subscription to use to check the configuration.
5454 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005455 @Override
Nathan Harold62c68512021-04-06 11:26:02 -07005456
Brad Ebinger35c841c2018-10-01 10:40:55 -07005457 public boolean isVoWiFiRoamingSettingEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005458 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005459 mApp, subId, "isVoWiFiRoamingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005460 final long identity = Binder.clearCallingIdentity();
5461 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005462 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005463 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005464 return ImsManager.getInstance(mApp, slotId).isWfcRoamingEnabledByUser();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005465 } catch (ImsException e) {
5466 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005467 } finally {
5468 Binder.restoreCallingIdentity(identity);
5469 }
5470 }
5471
5472 @Override
Brad Ebinger1c162042019-02-21 14:49:10 -08005473 public void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005474 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
Brad Ebinger1c162042019-02-21 14:49:10 -08005475 "setVoWiFiRoamingSettingEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005476 final long identity = Binder.clearCallingIdentity();
5477 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005478 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005479 // This setting doesn't require an active ImsService connection, so do not verify. The
5480 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005481 ImsManager.getInstance(mApp, slotId).setWfcRoamingSetting(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005482 } catch (ImsException e) {
5483 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005484 } finally {
5485 Binder.restoreCallingIdentity(identity);
5486 }
5487 }
5488
5489 @Override
5490 public void setVoWiFiNonPersistent(int subId, boolean isCapable, int mode) {
5491 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5492 "setVoWiFiNonPersistent");
5493 final long identity = Binder.clearCallingIdentity();
5494 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005495 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005496 // This setting will be ignored if the ImsService isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005497 ImsManager.getInstance(mApp, slotId).setWfcNonPersistent(isCapable, mode);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005498 } catch (ImsException e) {
5499 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005500 } finally {
5501 Binder.restoreCallingIdentity(identity);
5502 }
5503 }
5504
shilu366312e2019-12-17 09:28:10 -08005505 /**
5506 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5507 * @param subId The subscription to use to check the configuration.
5508 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005509 @Override
5510 public int getVoWiFiModeSetting(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005511 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005512 mApp, subId, "getVoWiFiModeSetting");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005513 final long identity = Binder.clearCallingIdentity();
5514 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005515 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005516 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005517 return ImsManager.getInstance(mApp, slotId).getWfcMode(false /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005518 } catch (ImsException e) {
5519 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005520 } finally {
5521 Binder.restoreCallingIdentity(identity);
5522 }
5523 }
5524
5525 @Override
5526 public void setVoWiFiModeSetting(int subId, int mode) {
5527 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5528 "setVoWiFiModeSetting");
5529 final long identity = Binder.clearCallingIdentity();
5530 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005531 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005532 // This setting doesn't require an active ImsService connection, so do not verify. The
5533 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005534 ImsManager.getInstance(mApp, slotId).setWfcMode(mode, false /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005535 } catch (ImsException e) {
5536 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005537 } finally {
5538 Binder.restoreCallingIdentity(identity);
5539 }
5540 }
5541
5542 @Override
5543 public int getVoWiFiRoamingModeSetting(int subId) {
5544 enforceReadPrivilegedPermission("getVoWiFiRoamingModeSetting");
5545 final long identity = Binder.clearCallingIdentity();
5546 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005547 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005548 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005549 return ImsManager.getInstance(mApp, slotId).getWfcMode(true /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005550 } catch (ImsException e) {
5551 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005552 } finally {
5553 Binder.restoreCallingIdentity(identity);
5554 }
5555 }
5556
5557 @Override
5558 public void setVoWiFiRoamingModeSetting(int subId, int mode) {
5559 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5560 "setVoWiFiRoamingModeSetting");
5561 final long identity = Binder.clearCallingIdentity();
5562 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005563 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005564 // This setting doesn't require an active ImsService connection, so do not verify. The
5565 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005566 ImsManager.getInstance(mApp, slotId).setWfcMode(mode, true /*isRoaming*/);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005567 } catch (ImsException e) {
5568 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005569 } finally {
5570 Binder.restoreCallingIdentity(identity);
5571 }
5572 }
5573
5574 @Override
5575 public void setRttCapabilitySetting(int subId, boolean isEnabled) {
5576 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5577 "setRttCapabilityEnabled");
5578 final long identity = Binder.clearCallingIdentity();
5579 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005580 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005581 // This setting doesn't require an active ImsService connection, so do not verify. The
5582 // new setting will be picked up when the ImsService comes up next if it isn't up.
Brad Ebinger919631e2021-06-02 17:46:35 -07005583 ImsManager.getInstance(mApp, slotId).setRttEnabled(isEnabled);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005584 } catch (ImsException e) {
5585 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005586 } finally {
5587 Binder.restoreCallingIdentity(identity);
5588 }
5589 }
5590
shilu366312e2019-12-17 09:28:10 -08005591 /**
5592 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
5593 * @param subId The subscription to use to check the configuration.
5594 */
Brad Ebinger35c841c2018-10-01 10:40:55 -07005595 @Override
5596 public boolean isTtyOverVolteEnabled(int subId) {
Nathan Harold62c68512021-04-06 11:26:02 -07005597 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
Rambo Wang37f9c242020-02-10 14:45:28 -08005598 mApp, subId, "isTtyOverVolteEnabled");
Brad Ebinger35c841c2018-10-01 10:40:55 -07005599 final long identity = Binder.clearCallingIdentity();
5600 try {
Brad Ebinger919631e2021-06-02 17:46:35 -07005601 int slotId = getSlotIndexOrException(subId);
Brad Ebinger735c5ce2021-07-12 13:58:21 -07005602 // This setting doesn't require an active ImsService connection, so do not verify.
Brad Ebinger919631e2021-06-02 17:46:35 -07005603 return ImsManager.getInstance(mApp, slotId).isTtyOnVoLteCapable();
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005604 } catch (ImsException e) {
5605 throw new ServiceSpecificException(e.getCode());
Brad Ebinger35c841c2018-10-01 10:40:55 -07005606 } finally {
5607 Binder.restoreCallingIdentity(identity);
5608 }
5609 }
5610
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005611 @Override
5612 public void registerImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
5613 enforceReadPrivilegedPermission("registerImsProvisioningChangedCallback");
joonhunshincffb7fc2021-11-28 07:32:01 +00005614
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005615 final long identity = Binder.clearCallingIdentity();
5616 try {
Brad Ebingera2628302022-02-18 03:44:55 +00005617 if (!isImsAvailableOnDevice()) {
5618 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5619 "IMS not available on device.");
5620 }
5621 int slotId = getSlotIndexOrException(subId);
5622 verifyImsMmTelConfiguredOrThrow(slotId);
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005623
5624 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5625 if (controller != null) {
5626 ImsManager imsManager = controller.getImsManager(subId);
5627 if (imsManager != null) {
5628 imsManager.addProvisioningCallbackForSubscription(callback, subId);
5629 } else {
5630 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
5631 }
5632 } else {
5633 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5634 }
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005635 } catch (ImsException e) {
5636 throw new ServiceSpecificException(e.getCode());
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005637 } finally {
5638 Binder.restoreCallingIdentity(identity);
5639 }
5640 }
5641
5642 @Override
5643 public void unregisterImsProvisioningChangedCallback(int subId, IImsConfigCallback callback) {
5644 enforceReadPrivilegedPermission("unregisterImsProvisioningChangedCallback");
joonhunshincffb7fc2021-11-28 07:32:01 +00005645
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005646 final long identity = Binder.clearCallingIdentity();
Brad Ebinger4ae57f92019-01-09 16:51:30 -08005647 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5648 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5649 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005650 try {
Hwangoo Park8646b0d2023-01-13 02:42:34 +00005651 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
5652 if (controller != null) {
5653 ImsManager imsManager = controller.getImsManager(subId);
5654 if (imsManager != null) {
5655 imsManager.removeProvisioningCallbackForSubscription(callback, subId);
5656 } else {
5657 Log.i(LOG_TAG, "unregisterImsProvisioningChangedCallback: " + subId
5658 + " is inactive, ignoring unregister.");
5659 // If the ImsManager is not valid, just return, since the callback will already
5660 // have been removed internally.
5661 }
5662 }
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005663 } finally {
5664 Binder.restoreCallingIdentity(identity);
5665 }
5666 }
5667
joonhunshincffb7fc2021-11-28 07:32:01 +00005668 @Override
5669 public void registerFeatureProvisioningChangedCallback(int subId,
5670 IFeatureProvisioningCallback callback) {
5671 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5672 mApp, subId, "registerFeatureProvisioningChangedCallback");
5673
5674 final long identity = Binder.clearCallingIdentity();
5675 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5676 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5677 }
5678
joonhunshin91bc1952022-04-29 08:47:15 +00005679 try {
5680 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5681 if (controller == null) {
5682 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
5683 "Device does not support IMS");
5684 }
5685 controller.addFeatureProvisioningChangedCallback(subId, callback);
5686 } finally {
5687 Binder.restoreCallingIdentity(identity);
5688 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005689 }
5690
5691 @Override
5692 public void unregisterFeatureProvisioningChangedCallback(int subId,
5693 IFeatureProvisioningCallback callback) {
5694 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5695 mApp, subId, "unregisterFeatureProvisioningChangedCallback");
5696
5697 final long identity = Binder.clearCallingIdentity();
5698 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5699 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
5700 }
5701
joonhunshin91bc1952022-04-29 08:47:15 +00005702 try {
5703 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5704 if (controller == null) {
5705 loge("unregisterFeatureProvisioningChangedCallback: Device does not support IMS");
5706 return;
5707 }
5708 controller.removeFeatureProvisioningChangedCallback(subId, callback);
5709 } finally {
5710 Binder.restoreCallingIdentity(identity);
5711 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005712 }
allenwtsu99c623b2020-01-03 18:24:23 +08005713
5714 private void checkModifyPhoneStatePermission(int subId, String message) {
5715 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5716 message);
5717 }
5718
allenwtsu99c623b2020-01-03 18:24:23 +08005719 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005720 public void setRcsProvisioningStatusForCapability(int subId, int capability, int tech,
allenwtsu99c623b2020-01-03 18:24:23 +08005721 boolean isProvisioned) {
5722 checkModifyPhoneStatePermission(subId, "setRcsProvisioningStatusForCapability");
5723
5724 final long identity = Binder.clearCallingIdentity();
5725 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005726 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5727 if (controller == null) {
5728 loge("setRcsProvisioningStatusForCapability: Device does not support IMS");
5729 return;
5730 }
5731 controller.setRcsProvisioningStatusForCapability(
5732 subId, capability, tech, isProvisioned);
allenwtsu99c623b2020-01-03 18:24:23 +08005733 } finally {
5734 Binder.restoreCallingIdentity(identity);
5735 }
allenwtsu99c623b2020-01-03 18:24:23 +08005736 }
5737
5738
5739 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005740 public boolean getRcsProvisioningStatusForCapability(int subId, int capability, int tech) {
5741 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5742 mApp, subId, "getRcsProvisioningStatusForCapability");
5743
allenwtsu99c623b2020-01-03 18:24:23 +08005744 final long identity = Binder.clearCallingIdentity();
5745 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005746 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5747 if (controller == null) {
5748 loge("getRcsProvisioningStatusForCapability: Device does not support IMS");
5749
5750 // device does not support IMS, this method will return true always.
5751 return true;
5752 }
5753 return controller.getRcsProvisioningStatusForCapability(subId, capability, tech);
allenwtsu99c623b2020-01-03 18:24:23 +08005754 } finally {
5755 Binder.restoreCallingIdentity(identity);
5756 }
5757 }
5758
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005759 @Override
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005760 public void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
5761 boolean isProvisioned) {
allenwtsu99c623b2020-01-03 18:24:23 +08005762 checkModifyPhoneStatePermission(subId, "setImsProvisioningStatusForCapability");
joonhunshincffb7fc2021-11-28 07:32:01 +00005763
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005764 final long identity = Binder.clearCallingIdentity();
5765 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005766 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5767 if (controller == null) {
5768 loge("setImsProvisioningStatusForCapability: Device does not support IMS");
5769 return;
5770 }
5771 controller.setImsProvisioningStatusForCapability(
5772 subId, capability, tech, isProvisioned);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005773 } finally {
5774 Binder.restoreCallingIdentity(identity);
5775 }
5776 }
5777
5778 @Override
5779 public boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech) {
joonhunshincffb7fc2021-11-28 07:32:01 +00005780 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5781 mApp, subId, "getProvisioningStatusForCapability");
5782
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005783 final long identity = Binder.clearCallingIdentity();
5784 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005785 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5786 if (controller == null) {
5787 loge("getImsProvisioningStatusForCapability: Device does not support IMS");
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005788
joonhunshin91bc1952022-04-29 08:47:15 +00005789 // device does not support IMS, this method will return true always.
5790 return true;
5791 }
5792 return controller.getImsProvisioningStatusForCapability(subId, capability, tech);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005793 } finally {
5794 Binder.restoreCallingIdentity(identity);
5795 }
5796 }
5797
5798 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005799 public boolean isProvisioningRequiredForCapability(int subId, int capability, int tech) {
5800 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5801 mApp, subId, "isProvisioningRequiredForCapability");
5802
5803 final long identity = Binder.clearCallingIdentity();
5804 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005805 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5806 if (controller == null) {
5807 loge("isProvisioningRequiredForCapability: Device does not support IMS");
5808
5809 // device does not support IMS, this method will return false
5810 return false;
5811 }
5812 return controller.isImsProvisioningRequiredForCapability(subId, capability, tech);
joonhunshincffb7fc2021-11-28 07:32:01 +00005813 } finally {
5814 Binder.restoreCallingIdentity(identity);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005815 }
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005816 }
5817
5818 @Override
joonhunshincffb7fc2021-11-28 07:32:01 +00005819 public boolean isRcsProvisioningRequiredForCapability(int subId, int capability, int tech) {
5820 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5821 mApp, subId, "isProvisioningRequiredForCapability");
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005822
joonhunshincffb7fc2021-11-28 07:32:01 +00005823 final long identity = Binder.clearCallingIdentity();
5824 try {
joonhunshin91bc1952022-04-29 08:47:15 +00005825 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5826 if (controller == null) {
5827 loge("isRcsProvisioningRequiredForCapability: Device does not support IMS");
5828
5829 // device does not support IMS, this method will return false
5830 return false;
5831 }
5832 return controller.isRcsProvisioningRequiredForCapability(subId, capability, tech);
joonhunshincffb7fc2021-11-28 07:32:01 +00005833 } finally {
5834 Binder.restoreCallingIdentity(identity);
5835 }
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005836 }
5837
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005838 @Override
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005839 public int getImsProvisioningInt(int subId, int key) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005840 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5841 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5842 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005843 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5844 mApp, subId, "getImsProvisioningInt");
5845
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005846 final long identity = Binder.clearCallingIdentity();
5847 try {
5848 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005849 int slotId = getSlotIndex(subId);
5850 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5851 Log.w(LOG_TAG, "getImsProvisioningInt: called with an inactive subscription '"
5852 + subId + "' for key:" + key);
5853 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
5854 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005855
joonhunshin91bc1952022-04-29 08:47:15 +00005856 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5857 if (controller == null) {
5858 loge("getImsProvisioningInt: Device does not support IMS");
5859
5860 // device does not support IMS, this method will return CONFIG_RESULT_UNKNOWN.
5861 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
5862 }
5863 int retVal = controller.getProvisioningValue(subId, key);
joonhunshincffb7fc2021-11-28 07:32:01 +00005864 if (retVal != ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
5865 return retVal;
5866 }
5867
calvinpanb5a34062021-02-08 19:59:36 +08005868 return ImsManager.getInstance(mApp, slotId).getConfigInt(key);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005869 } catch (com.android.ims.ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005870 Log.w(LOG_TAG, "getImsProvisioningInt: ImsService is not available for subscription '"
5871 + subId + "' for key:" + key);
5872 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005873 } finally {
5874 Binder.restoreCallingIdentity(identity);
5875 }
5876 }
5877
5878 @Override
5879 public String getImsProvisioningString(int subId, int key) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005880 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5881 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5882 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005883 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
5884 mApp, subId, "getImsProvisioningString");
5885
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005886 final long identity = Binder.clearCallingIdentity();
5887 try {
5888 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005889 int slotId = getSlotIndex(subId);
5890 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5891 Log.w(LOG_TAG, "getImsProvisioningString: called for an inactive subscription id '"
5892 + subId + "' for key:" + key);
5893 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_GENERIC;
5894 }
calvinpanb5a34062021-02-08 19:59:36 +08005895 return ImsManager.getInstance(mApp, slotId).getConfigString(key);
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005896 } catch (com.android.ims.ImsException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005897 Log.w(LOG_TAG, "getImsProvisioningString: ImsService is not available for sub '"
5898 + subId + "' for key:" + key);
5899 return ProvisioningManager.STRING_QUERY_RESULT_ERROR_NOT_READY;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005900 } finally {
5901 Binder.restoreCallingIdentity(identity);
5902 }
5903 }
5904
5905 @Override
5906 public int setImsProvisioningInt(int subId, int key, int value) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005907 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5908 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5909 }
Brad Ebinger3d0b34e2018-11-15 14:13:12 -08005910 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5911 "setImsProvisioningInt");
joonhunshincffb7fc2021-11-28 07:32:01 +00005912
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005913 final long identity = Binder.clearCallingIdentity();
5914 try {
5915 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005916 int slotId = getSlotIndex(subId);
5917 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5918 Log.w(LOG_TAG, "setImsProvisioningInt: called with an inactive subscription id '"
5919 + subId + "' for key:" + key);
5920 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
5921 }
joonhunshincffb7fc2021-11-28 07:32:01 +00005922
joonhunshin91bc1952022-04-29 08:47:15 +00005923 ImsProvisioningController controller = ImsProvisioningController.getInstance();
5924 if (controller == null) {
5925 loge("setImsProvisioningInt: Device does not support IMS");
5926
5927 // device does not support IMS, this method will return CONFIG_RESULT_FAILED.
5928 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
5929 }
5930 int retVal = controller.setProvisioningValue(subId, key, value);
joonhunshincffb7fc2021-11-28 07:32:01 +00005931 if (retVal != ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
5932 return retVal;
5933 }
5934
calvinpanb5a34062021-02-08 19:59:36 +08005935 return ImsManager.getInstance(mApp, slotId).setConfig(key, value);
5936 } catch (com.android.ims.ImsException | RemoteException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005937 Log.w(LOG_TAG, "setImsProvisioningInt: ImsService unavailable for sub '" + subId
calvinpanb5a34062021-02-08 19:59:36 +08005938 + "' for key:" + key, e);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005939 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005940 } finally {
5941 Binder.restoreCallingIdentity(identity);
5942 }
5943 }
5944
5945 @Override
5946 public int setImsProvisioningString(int subId, int key, String value) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005947 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
5948 throw new IllegalArgumentException("Invalid Subscription id '" + subId + "'");
5949 }
Brad Ebinger3d0b34e2018-11-15 14:13:12 -08005950 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
5951 "setImsProvisioningString");
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005952 final long identity = Binder.clearCallingIdentity();
5953 try {
5954 // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005955 int slotId = getSlotIndex(subId);
5956 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
5957 Log.w(LOG_TAG, "setImsProvisioningString: called with an inactive subscription id '"
5958 + subId + "' for key:" + key);
5959 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
5960 }
calvinpanb5a34062021-02-08 19:59:36 +08005961 return ImsManager.getInstance(mApp, slotId).setConfig(key, value);
5962 } catch (com.android.ims.ImsException | RemoteException e) {
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005963 Log.w(LOG_TAG, "setImsProvisioningString: ImsService unavailable for sub '" + subId
calvinpanb5a34062021-02-08 19:59:36 +08005964 + "' for key:" + key, e);
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005965 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
Brad Ebingerdf5b4f02018-10-31 11:24:17 -07005966 } finally {
5967 Binder.restoreCallingIdentity(identity);
5968 }
5969 }
5970
Brad Ebinger919631e2021-06-02 17:46:35 -07005971 /**
5972 * Throw an ImsException if the IMS resolver does not have an ImsService configured for MMTEL
5973 * for the given slot ID or no ImsResolver instance has been created.
5974 * @param slotId The slot ID that the IMS service is created for.
5975 * @throws ImsException If there is no ImsService configured for this slot.
5976 */
5977 private void verifyImsMmTelConfiguredOrThrow(int slotId) throws ImsException {
5978 if (mImsResolver == null || !mImsResolver.isImsServiceConfiguredForFeature(slotId,
5979 ImsFeature.FEATURE_MMTEL)) {
5980 throw new ImsException("This subscription does not support MMTEL over IMS",
5981 ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
5982 }
5983 }
5984
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005985 private int getSlotIndexOrException(int subId) throws ImsException {
Brad Ebinger35c841c2018-10-01 10:40:55 -07005986 int slotId = SubscriptionManager.getSlotIndex(subId);
5987 if (!SubscriptionManager.isValidSlotIndex(slotId)) {
Brad Ebinger1ce9c432019-07-16 13:19:44 -07005988 throw new ImsException("Invalid Subscription Id, subId=" + subId,
5989 ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
Brad Ebinger35c841c2018-10-01 10:40:55 -07005990 }
5991 return slotId;
5992 }
5993
Brad Ebinger1c8542e2019-01-14 13:43:14 -08005994 private int getSlotIndex(int subId) {
5995 int slotId = SubscriptionManager.getSlotIndex(subId);
5996 if (!SubscriptionManager.isValidSlotIndex(slotId)) {
5997 return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
5998 }
5999 return slotId;
6000 }
6001
Wink Saville36469e72014-06-11 15:17:00 -07006002 /**
Nathan Harold9042f0b2019-05-21 15:51:27 -07006003 * Returns the data network type for a subId; does not throw SecurityException.
Wink Saville36469e72014-06-11 15:17:00 -07006004 */
6005 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006006 public int getNetworkTypeForSubscriber(int subId, String callingPackage,
6007 String callingFeatureId) {
Shuo Qian13d89152021-05-10 23:58:11 -07006008 try {
6009 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
6010 } catch (SecurityException se) {
6011 EventLog.writeEvent(0x534e4554, "186776740", Binder.getCallingUid());
6012 throw new SecurityException("Package " + callingPackage + " does not belong to "
6013 + Binder.getCallingUid());
6014 }
Nathan Haroldf096d982020-11-18 17:18:06 -08006015 final int targetSdk = TelephonyPermissions.getTargetSdk(mApp, callingPackage);
Nathan Haroldef60dba2019-05-22 13:55:14 -07006016 if (targetSdk > android.os.Build.VERSION_CODES.Q) {
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006017 return getDataNetworkTypeForSubscriber(subId, callingPackage, callingFeatureId);
Nathan Haroldef60dba2019-05-22 13:55:14 -07006018 } else if (targetSdk == android.os.Build.VERSION_CODES.Q
Nathan Harold9042f0b2019-05-21 15:51:27 -07006019 && !TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006020 mApp, subId, callingPackage, callingFeatureId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006021 "getNetworkTypeForSubscriber")) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006022 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6023 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07006024
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006025 final long identity = Binder.clearCallingIdentity();
6026 try {
6027 final Phone phone = getPhone(subId);
6028 if (phone != null) {
6029 return phone.getServiceState().getDataNetworkType();
6030 } else {
6031 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6032 }
6033 } finally {
6034 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006035 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006036 }
6037
6038 /**
6039 * Returns the data network type
6040 */
6041 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006042 public int getDataNetworkType(String callingPackage, String callingFeatureId) {
Jack Yu285100e2022-12-02 22:48:35 -08006043 return getDataNetworkTypeForSubscriber(SubscriptionManager.getDefaultDataSubscriptionId(),
Zoey Chenfd61f7f2021-04-21 13:42:10 +08006044 callingPackage, callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07006045 }
6046
6047 /**
6048 * Returns the data network type for a subId
6049 */
6050 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006051 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage,
6052 String callingFeatureId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07006053 String functionName = "getDataNetworkTypeForSubscriber";
6054 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
6055 mApp, functionName)) {
6056 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6057 mApp, subId, callingPackage, callingFeatureId, functionName)) {
6058 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6059 }
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006060 }
6061
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006062 final long identity = Binder.clearCallingIdentity();
6063 try {
6064 final Phone phone = getPhone(subId);
6065 if (phone != null) {
6066 return phone.getServiceState().getDataNetworkType();
6067 } else {
6068 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6069 }
6070 } finally {
6071 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006072 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006073 }
6074
6075 /**
Wink Saville36469e72014-06-11 15:17:00 -07006076 * Returns the Voice network type for a subId
6077 */
6078 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006079 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage,
6080 String callingFeatureId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07006081 String functionName = "getVoiceNetworkTypeForSubscriber";
6082 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
6083 mApp, functionName)) {
6084 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
6085 mApp, subId, callingPackage, callingFeatureId, functionName)) {
6086 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6087 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07006088 }
6089
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006090 final long identity = Binder.clearCallingIdentity();
6091 try {
6092 final Phone phone = getPhone(subId);
6093 if (phone != null) {
6094 return phone.getServiceState().getVoiceNetworkType();
6095 } else {
6096 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
6097 }
6098 } finally {
6099 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006100 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006101 }
6102
6103 /**
6104 * @return true if a ICC card is present
6105 */
6106 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07006107 // FIXME Make changes to pass defaultSimId of type int
Jack Yu285100e2022-12-02 22:48:35 -08006108 return hasIccCardUsingSlotIndex(SubscriptionManager.getSlotIndex(
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006109 getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -07006110 }
6111
6112 /**
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006113 * @return true if a ICC card is present for a slotIndex
Wink Saville36469e72014-06-11 15:17:00 -07006114 */
Sanket Padawe356d7632015-06-22 14:03:32 -07006115 @Override
Sanket Padawe13bac7b2017-03-20 15:04:47 -07006116 public boolean hasIccCardUsingSlotIndex(int slotIndex) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006117 final long identity = Binder.clearCallingIdentity();
6118 try {
6119 final Phone phone = PhoneFactory.getPhone(slotIndex);
6120 if (phone != null) {
6121 return phone.getIccCard().hasIccCard();
6122 } else {
6123 return false;
6124 }
6125 } finally {
6126 Binder.restoreCallingIdentity(identity);
Amit Mahajana6fc2a82015-01-06 11:53:51 -08006127 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006128 }
6129
6130 /**
6131 * Return if the current radio is LTE on CDMA. This
6132 * is a tri-state return value as for a period of time
6133 * the mode may be unknown.
6134 *
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006135 * @param callingPackage the name of the package making the call.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006136 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08006137 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006138 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006139 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006140 public int getLteOnCdmaMode(String callingPackage, String callingFeatureId) {
6141 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage,
6142 callingFeatureId);
Wink Saville36469e72014-06-11 15:17:00 -07006143 }
6144
Sanket Padawe356d7632015-06-22 14:03:32 -07006145 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006146 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage,
6147 String callingFeatureId) {
Sarah Chin790d2922020-01-16 12:17:23 -08006148 try {
6149 enforceReadPrivilegedPermission("getLteOnCdmaModeForSubscriber");
6150 } catch (SecurityException e) {
Robert Greenwalt36b23af2015-07-06 17:59:14 -07006151 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
6152 }
6153
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006154 final long identity = Binder.clearCallingIdentity();
6155 try {
6156 final Phone phone = getPhone(subId);
6157 if (phone == null) {
6158 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
6159 } else {
Nathan Harold05ad6332020-07-10 11:54:36 -07006160 return TelephonyProperties.lte_on_cdma_device()
6161 .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006162 }
6163 } finally {
6164 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07006165 }
Wink Saville36469e72014-06-11 15:17:00 -07006166 }
6167
Wink Saville36469e72014-06-11 15:17:00 -07006168 /**
6169 * {@hide}
6170 * Returns Default subId, 0 in the case of single standby.
6171 */
Wink Savilleb564aae2014-10-23 10:18:09 -07006172 private int getDefaultSubscription() {
Jack Yu285100e2022-12-02 22:48:35 -08006173 return SubscriptionManager.getDefaultSubscriptionId();
Wink Saville36469e72014-06-11 15:17:00 -07006174 }
6175
Shishir Agrawala9f32182016-04-12 12:00:16 -07006176 private int getSlotForDefaultSubscription() {
Jack Yu285100e2022-12-02 22:48:35 -08006177 return SubscriptionManager.getPhoneId(getDefaultSubscription());
Shishir Agrawala9f32182016-04-12 12:00:16 -07006178 }
6179
Wink Savilleb564aae2014-10-23 10:18:09 -07006180 private int getPreferredVoiceSubscription() {
Jack Yu285100e2022-12-02 22:48:35 -08006181 return SubscriptionManager.getDefaultVoiceSubscriptionId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07006182 }
Ihab Awadf2177b72013-11-25 13:33:23 -08006183
Pengquan Menge92a50d2018-09-21 15:54:48 -07006184 private boolean isActiveSubscription(int subId) {
Jack Yu285100e2022-12-02 22:48:35 -08006185 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08006186 return getSubscriptionManagerService().isActiveSubId(subId,
Jack Yu285100e2022-12-02 22:48:35 -08006187 mApp.getOpPackageName(), mApp.getFeatureId());
6188 }
Pengquan Menge92a50d2018-09-21 15:54:48 -07006189 return mSubscriptionController.isActiveSubId(subId);
6190 }
6191
Ihab Awadf2177b72013-11-25 13:33:23 -08006192 /**
6193 * @see android.telephony.TelephonyManager.WifiCallingChoices
6194 */
6195 public int getWhenToMakeWifiCalls() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006196 final long identity = Binder.clearCallingIdentity();
6197 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006198 return Settings.System.getInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006199 Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
6200 getWhenToMakeWifiCallsDefaultPreference());
6201 } finally {
6202 Binder.restoreCallingIdentity(identity);
6203 }
Ihab Awadf2177b72013-11-25 13:33:23 -08006204 }
6205
6206 /**
6207 * @see android.telephony.TelephonyManager.WifiCallingChoices
6208 */
6209 public void setWhenToMakeWifiCalls(int preference) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006210 final long identity = Binder.clearCallingIdentity();
6211 try {
6212 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006213 Settings.System.putInt(mApp.getContentResolver(),
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006214 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
6215 } finally {
6216 Binder.restoreCallingIdentity(identity);
6217 }
Ihab Awadf9e92732013-12-05 18:02:52 -08006218 }
6219
Sailesh Nepald1e68152013-12-12 19:08:02 -08006220 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07006221 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08006222 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08006223 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08006224
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006225 private Phone getPhoneFromSlotPortIndexOrThrowException(int slotIndex, int portIndex) {
6226 int phoneId = UiccController.getInstance().getPhoneIdFromSlotPortIndex(slotIndex,
6227 portIndex);
Jordan Liu4c733742019-02-28 12:03:40 -08006228 if (phoneId == -1) {
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006229 throw new IllegalArgumentException("Given slot index: " + slotIndex + " port index: "
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006230 + portIndex + " does not correspond to an active phone");
Jordan Liu4c733742019-02-28 12:03:40 -08006231 }
6232 return PhoneFactory.getPhone(phoneId);
6233 }
6234
Shishir Agrawal566b7612013-10-28 14:41:00 -07006235 @Override
Derek Tan740e1672017-06-27 14:56:27 -07006236 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
Rambo Wanga1782702021-11-10 20:15:19 -08006237 @NonNull IccLogicalChannelRequest request) {
6238 Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
6239 /*message=*/ "iccOpenLogicalChannel");
6240
6241 if (DBG) log("iccOpenLogicalChannel: request=" + request);
6242 // Verify that the callingPackage in the request belongs to the calling UID
6243 mAppOps.checkPackage(Binder.getCallingUid(), request.callingPackage);
6244
6245 return iccOpenLogicalChannelWithPermission(phone, request);
Jordan Liu4c733742019-02-28 12:03:40 -08006246 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006247
Rambo Wanga1782702021-11-10 20:15:19 -08006248 private Phone getPhoneFromValidIccLogicalChannelRequest(
6249 @NonNull IccLogicalChannelRequest request, String message) {
6250 Phone phone;
6251 if (request.subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
6252 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6253 mApp, request.subId, message);
6254 phone = getPhoneFromSubId(request.subId);
6255 } else if (request.slotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
6256 enforceModifyPermission();
6257 phone = getPhoneFromSlotPortIndexOrThrowException(request.slotIndex, request.portIndex);
6258 } else {
6259 throw new IllegalArgumentException("Both subId and slotIndex in request are invalid.");
Jordan Liu4c733742019-02-28 12:03:40 -08006260 }
Rambo Wanga1782702021-11-10 20:15:19 -08006261 return phone;
Jordan Liu4c733742019-02-28 12:03:40 -08006262 }
6263
6264 private IccOpenLogicalChannelResponse iccOpenLogicalChannelWithPermission(Phone phone,
Rambo Wanga1782702021-11-10 20:15:19 -08006265 IccLogicalChannelRequest channelRequest) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006266 final long identity = Binder.clearCallingIdentity();
6267 try {
Rambo Wanga1782702021-11-10 20:15:19 -08006268 if (TextUtils.equals(ISDR_AID, channelRequest.aid)) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006269 // Only allows LPA to open logical channel to ISD-R.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006270 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
6271 .getContext().getPackageManager());
Rambo Wanga1782702021-11-10 20:15:19 -08006272 if (bestComponent == null || !TextUtils.equals(channelRequest.callingPackage,
6273 bestComponent.packageName)) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006274 loge("The calling package is not allowed to access ISD-R.");
6275 throw new SecurityException(
6276 "The calling package is not allowed to access ISD-R.");
6277 }
Derek Tan740e1672017-06-27 14:56:27 -07006278 }
Derek Tan740e1672017-06-27 14:56:27 -07006279
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006280 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse) sendRequest(
Rambo Wanga1782702021-11-10 20:15:19 -08006281 CMD_OPEN_CHANNEL, channelRequest, phone, null /* workSource */);
6282 if (DBG) log("iccOpenLogicalChannelWithPermission: response=" + response);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006283 return response;
6284 } finally {
6285 Binder.restoreCallingIdentity(identity);
6286 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006287 }
6288
6289 @Override
Rambo Wanga1782702021-11-10 20:15:19 -08006290 public boolean iccCloseLogicalChannel(@NonNull IccLogicalChannelRequest request) {
6291 Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
6292 /*message=*/"iccCloseLogicalChannel");
6293
6294 if (DBG) log("iccCloseLogicalChannel: request=" + request);
6295
6296 return iccCloseLogicalChannelWithPermission(phone, request);
Jordan Liu4c733742019-02-28 12:03:40 -08006297 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006298
Rambo Wanga1782702021-11-10 20:15:19 -08006299 private boolean iccCloseLogicalChannelWithPermission(Phone phone,
6300 IccLogicalChannelRequest request) {
Chen Xua8f0dff2022-02-12 00:34:15 -08006301 // before this feature is enabled, this API should only return false if
6302 // the operation fails instead of throwing runtime exception for
6303 // backward-compatibility.
6304 final boolean shouldThrowExceptionOnFailure = CompatChanges.isChangeEnabled(
6305 ICC_CLOSE_CHANNEL_EXCEPTION_ON_FAILURE, Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006306 final long identity = Binder.clearCallingIdentity();
6307 try {
Rambo Wanga1782702021-11-10 20:15:19 -08006308 if (request.channel < 0) {
Chen Xu540470b2021-12-14 17:15:47 -08006309 throw new IllegalArgumentException("request.channel is less than 0");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006310 }
Chen Xue9d737e2022-01-01 23:41:31 -08006311 Object result = sendRequest(CMD_CLOSE_CHANNEL, request.channel, phone,
Jordan Liu4c733742019-02-28 12:03:40 -08006312 null /* workSource */);
Chen Xue9d737e2022-01-01 23:41:31 -08006313 Boolean success = false;
6314 if (result instanceof RuntimeException) {
6315 // if there is an exception returned, throw from the binder thread here.
Chen Xua8f0dff2022-02-12 00:34:15 -08006316 if (shouldThrowExceptionOnFailure) {
6317 throw (RuntimeException) result;
6318 } else {
6319 return false;
6320 }
Chen Xue9d737e2022-01-01 23:41:31 -08006321 } else if (result instanceof Boolean) {
6322 success = (Boolean) result;
6323 } else {
6324 loge("iccCloseLogicalChannelWithPermission: supported return type " + result);
6325 }
Rambo Wanga1782702021-11-10 20:15:19 -08006326 if (DBG) log("iccCloseLogicalChannelWithPermission: success=" + success);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006327 return success;
6328 } finally {
6329 Binder.restoreCallingIdentity(identity);
Shishir Agrawal566b7612013-10-28 14:41:00 -07006330 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006331 }
6332
6333 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08006334 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
Shishir Agrawal566b7612013-10-28 14:41:00 -07006335 int command, int p1, int p2, int p3, String data) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006336 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6337 mApp, subId, "iccTransmitApduLogicalChannel");
Jordan Liu4c733742019-02-28 12:03:40 -08006338 if (DBG) {
6339 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
6340 + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
6341 + p3 + " data=" + data);
6342 }
6343 return iccTransmitApduLogicalChannelWithPermission(getPhoneFromSubId(subId), channel, cla,
6344 command, p1, p2, p3, data);
6345 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006346
Jordan Liu4c733742019-02-28 12:03:40 -08006347 @Override
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006348 public String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel,
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006349 int cla, int command, int p1, int p2, int p3, String data) {
Jordan Liu4c733742019-02-28 12:03:40 -08006350 enforceModifyPermission();
6351 if (DBG) {
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006352 log("iccTransmitApduLogicalChannelByPort: slotIndex=" + slotIndex + " portIndex="
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006353 + portIndex + " chnl=" + channel + " cla=" + cla + " cmd=" + command + " p1="
6354 + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
Jordan Liu4c733742019-02-28 12:03:40 -08006355 }
6356 return iccTransmitApduLogicalChannelWithPermission(
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006357 getPhoneFromSlotPortIndexOrThrowException(slotIndex, portIndex), channel, cla,
6358 command, p1, p2, p3, data);
Jordan Liu4c733742019-02-28 12:03:40 -08006359 }
6360
6361 private String iccTransmitApduLogicalChannelWithPermission(Phone phone, int channel, int cla,
6362 int command, int p1, int p2, int p3, String data) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006363 final long identity = Binder.clearCallingIdentity();
6364 try {
Hall Liu4fd771b2019-05-02 09:16:29 -07006365 if (channel <= 0) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006366 return "";
6367 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006368
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006369 IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Jordan Liu4c733742019-02-28 12:03:40 -08006370 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), phone,
6371 null /* workSource */);
6372 if (DBG) log("iccTransmitApduLogicalChannelWithPermission: " + response);
Shishir Agrawal566b7612013-10-28 14:41:00 -07006373
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006374 // Append the returned status code to the end of the response payload.
6375 String s = Integer.toHexString(
6376 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
6377 if (response.payload != null) {
6378 s = IccUtils.bytesToHexString(response.payload) + s;
6379 }
6380 return s;
6381 } finally {
6382 Binder.restoreCallingIdentity(identity);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07006383 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07006384 }
Jake Hambye994d462014-02-03 13:10:13 -08006385
Evan Charltonc66da362014-05-16 14:06:40 -07006386 @Override
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08006387 public String iccTransmitApduBasicChannel(int subId, String callingPackage, int cla,
6388 int command, int p1, int p2, int p3, String data) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006389 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6390 mApp, subId, "iccTransmitApduBasicChannel");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006391 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Jordan Liu4c733742019-02-28 12:03:40 -08006392 if (DBG) {
6393 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
6394 + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
6395 }
6396 return iccTransmitApduBasicChannelWithPermission(getPhoneFromSubId(subId), callingPackage,
6397 cla, command, p1, p2, p3, data);
6398 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006399
Jordan Liu4c733742019-02-28 12:03:40 -08006400 @Override
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006401 public String iccTransmitApduBasicChannelByPort(int slotIndex, int portIndex,
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006402 String callingPackage, int cla, int command, int p1, int p2, int p3, String data) {
Jordan Liu4c733742019-02-28 12:03:40 -08006403 enforceModifyPermission();
6404 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
6405 if (DBG) {
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006406 log("iccTransmitApduBasicChannelByPort: slotIndex=" + slotIndex + " portIndex="
Thomas Nguyen8ee49682023-02-01 11:46:09 -08006407 + portIndex + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2="
6408 + p2 + " p3=" + p3 + " data=" + data);
Jordan Liu4c733742019-02-28 12:03:40 -08006409 }
6410
6411 return iccTransmitApduBasicChannelWithPermission(
Muralidhar Reddybd38d952021-12-02 21:04:16 +00006412 getPhoneFromSlotPortIndexOrThrowException(slotIndex, portIndex), callingPackage,
6413 cla, command, p1, p2, p3, data);
Jordan Liu4c733742019-02-28 12:03:40 -08006414 }
6415
6416 // open APDU basic channel assuming the caller has sufficient permissions
6417 private String iccTransmitApduBasicChannelWithPermission(Phone phone, String callingPackage,
6418 int cla, int command, int p1, int p2, int p3, String data) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006419 final long identity = Binder.clearCallingIdentity();
6420 try {
6421 if (command == SELECT_COMMAND && p1 == SELECT_P1 && p2 == SELECT_P2 && p3 == SELECT_P3
6422 && TextUtils.equals(ISDR_AID, data)) {
6423 // Only allows LPA to select ISD-R.
Nazanin Bakhshif782e562018-12-11 15:15:39 -08006424 ComponentInfo bestComponent = EuiccConnector.findBestComponent(getDefaultPhone()
6425 .getContext().getPackageManager());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006426 if (bestComponent == null
6427 || !TextUtils.equals(callingPackage, bestComponent.packageName)) {
6428 loge("The calling package is not allowed to select ISD-R.");
6429 throw new SecurityException(
6430 "The calling package is not allowed to select ISD-R.");
6431 }
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08006432 }
Holly Jiuyu Sun1cc2d552018-01-26 15:51:16 -08006433
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006434 IccIoResult response = (IccIoResult) sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
Jordan Liu4c733742019-02-28 12:03:40 -08006435 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), phone,
6436 null /* workSource */);
6437 if (DBG) log("iccTransmitApduBasicChannelWithPermission: " + response);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006438
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006439 // Append the returned status code to the end of the response payload.
6440 String s = Integer.toHexString(
6441 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
6442 if (response.payload != null) {
6443 s = IccUtils.bytesToHexString(response.payload) + s;
6444 }
6445 return s;
6446 } finally {
6447 Binder.restoreCallingIdentity(identity);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07006448 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006449 }
6450
6451 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08006452 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006453 String filePath) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006454 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6455 mApp, subId, "iccExchangeSimIO");
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006456
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006457 final long identity = Binder.clearCallingIdentity();
6458 try {
6459 if (DBG) {
6460 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " "
6461 + p1 + " " + p2 + " " + p3 + ":" + filePath);
6462 }
6463
6464 IccIoResult response =
6465 (IccIoResult) sendRequest(CMD_EXCHANGE_SIM_IO,
6466 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
6467 subId);
6468
6469 if (DBG) {
6470 log("Exchange SIM_IO [R]" + response);
6471 }
6472
6473 byte[] result = null;
6474 int length = 2;
6475 if (response.payload != null) {
6476 length = 2 + response.payload.length;
6477 result = new byte[length];
6478 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
6479 } else {
6480 result = new byte[length];
6481 }
6482
6483 result[length - 1] = (byte) response.sw2;
6484 result[length - 2] = (byte) response.sw1;
6485 return result;
6486 } finally {
6487 Binder.restoreCallingIdentity(identity);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006488 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006489 }
6490
Nathan Haroldb3014052017-01-25 15:57:32 -08006491 /**
6492 * Get the forbidden PLMN List from the given app type (ex APPTYPE_USIM)
6493 * on a particular subscription
6494 */
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006495 public String[] getForbiddenPlmns(int subId, int appType, String callingPackage,
6496 String callingFeatureId) {
sqianb6e41952018-03-12 14:54:01 -07006497 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006498 mApp, subId, callingPackage, callingFeatureId, "getForbiddenPlmns")) {
sqianb6e41952018-03-12 14:54:01 -07006499 return null;
6500 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006501
6502 final long identity = Binder.clearCallingIdentity();
6503 try {
6504 if (appType != TelephonyManager.APPTYPE_USIM
6505 && appType != TelephonyManager.APPTYPE_SIM) {
6506 loge("getForbiddenPlmnList(): App Type must be USIM or SIM");
6507 return null;
6508 }
6509 Object response = sendRequest(
6510 CMD_GET_FORBIDDEN_PLMNS, new Integer(appType), subId);
6511 if (response instanceof String[]) {
6512 return (String[]) response;
6513 }
yincheng zhao2737e882019-09-06 17:06:54 -07006514 // Response is an Exception of some kind
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006515 // which is signalled to the user as a NULL retval
Nathan Haroldb3014052017-01-25 15:57:32 -08006516 return null;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006517 } finally {
6518 Binder.restoreCallingIdentity(identity);
Nathan Haroldb3014052017-01-25 15:57:32 -08006519 }
Nathan Haroldb3014052017-01-25 15:57:32 -08006520 }
6521
yincheng zhao2737e882019-09-06 17:06:54 -07006522 /**
6523 * Set the forbidden PLMN list from the given app type (ex APPTYPE_USIM) on a particular
6524 * subscription.
6525 *
6526 * @param subId the id of the subscription.
6527 * @param appType the uicc app type, must be USIM or SIM.
6528 * @param fplmns the Forbiden plmns list that needed to be written to the SIM.
6529 * @param callingPackage the op Package name.
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006530 * @param callingFeatureId the feature in the package.
yincheng zhao2737e882019-09-06 17:06:54 -07006531 * @return number of fplmns that is successfully written to the SIM.
6532 */
Philip P. Moltmann700a9592019-10-03 11:53:50 -07006533 public int setForbiddenPlmns(int subId, int appType, List<String> fplmns, String callingPackage,
6534 String callingFeatureId) {
Jayachandran C5b0d75a2021-10-21 22:15:27 -07006535 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6536 mApp, subId, "setForbiddenPlmns");
6537
yincheng zhao2737e882019-09-06 17:06:54 -07006538 if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
6539 loge("setForbiddenPlmnList(): App Type must be USIM or SIM");
6540 throw new IllegalArgumentException("Invalid appType: App Type must be USIM or SIM");
6541 }
6542 if (fplmns == null) {
6543 throw new IllegalArgumentException("Fplmn List provided is null");
6544 }
6545 for (String fplmn : fplmns) {
6546 if (!CellIdentity.isValidPlmn(fplmn)) {
6547 throw new IllegalArgumentException("Invalid fplmn provided: " + fplmn);
6548 }
6549 }
6550 final long identity = Binder.clearCallingIdentity();
6551 try {
6552 Object response = sendRequest(
6553 CMD_SET_FORBIDDEN_PLMNS,
6554 new Pair<Integer, List<String>>(new Integer(appType), fplmns),
6555 subId);
6556 return (int) response;
6557 } finally {
6558 Binder.restoreCallingIdentity(identity);
6559 }
6560 }
6561
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07006562 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08006563 public String sendEnvelopeWithStatus(int subId, String content) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006564 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6565 mApp, subId, "sendEnvelopeWithStatus");
Evan Charltonc66da362014-05-16 14:06:40 -07006566
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006567 final long identity = Binder.clearCallingIdentity();
6568 try {
6569 IccIoResult response = (IccIoResult) sendRequest(CMD_SEND_ENVELOPE, content, subId);
6570 if (response.payload == null) {
6571 return "";
6572 }
Evan Charltonc66da362014-05-16 14:06:40 -07006573
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006574 // Append the returned status code to the end of the response payload.
6575 String s = Integer.toHexString(
6576 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
6577 s = IccUtils.bytesToHexString(response.payload) + s;
6578 return s;
6579 } finally {
6580 Binder.restoreCallingIdentity(identity);
6581 }
Evan Charltonc66da362014-05-16 14:06:40 -07006582 }
6583
Jake Hambye994d462014-02-03 13:10:13 -08006584 /**
6585 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
6586 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
6587 *
6588 * @param itemID the ID of the item to read
6589 * @return the NV item as a String, or null on error.
6590 */
6591 @Override
6592 public String nvReadItem(int itemID) {
vagdeviaf9a5b92018-08-15 16:01:53 -07006593 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Jeff Davidson7e17e312018-02-13 18:17:36 -08006594 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6595 mApp, getDefaultSubscription(), "nvReadItem");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006596
6597 final long identity = Binder.clearCallingIdentity();
6598 try {
6599 if (DBG) log("nvReadItem: item " + itemID);
vagdeviaf9a5b92018-08-15 16:01:53 -07006600 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006601 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
6602 return value;
6603 } finally {
6604 Binder.restoreCallingIdentity(identity);
6605 }
Jake Hambye994d462014-02-03 13:10:13 -08006606 }
6607
6608 /**
6609 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
6610 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
6611 *
6612 * @param itemID the ID of the item to read
6613 * @param itemValue the value to write, as a String
6614 * @return true on success; false on any failure
6615 */
6616 @Override
6617 public boolean nvWriteItem(int itemID, String itemValue) {
vagdeviaf9a5b92018-08-15 16:01:53 -07006618 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Jeff Davidson7e17e312018-02-13 18:17:36 -08006619 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6620 mApp, getDefaultSubscription(), "nvWriteItem");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006621
6622 final long identity = Binder.clearCallingIdentity();
6623 try {
6624 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
6625 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
vagdeviaf9a5b92018-08-15 16:01:53 -07006626 new Pair<Integer, String>(itemID, itemValue), workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006627 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
6628 return success;
6629 } finally {
6630 Binder.restoreCallingIdentity(identity);
6631 }
Jake Hambye994d462014-02-03 13:10:13 -08006632 }
6633
6634 /**
6635 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
6636 * Used for device configuration by some CDMA operators.
6637 *
6638 * @param preferredRoamingList byte array containing the new PRL
6639 * @return true on success; false on any failure
6640 */
6641 @Override
6642 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006643 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6644 mApp, getDefaultSubscription(), "nvWriteCdmaPrl");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006645
6646 final long identity = Binder.clearCallingIdentity();
6647 try {
6648 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
6649 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
6650 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
6651 return success;
6652 } finally {
6653 Binder.restoreCallingIdentity(identity);
6654 }
Jake Hambye994d462014-02-03 13:10:13 -08006655 }
6656
6657 /**
chen xu6dac5ab2018-10-26 17:39:23 -07006658 * Rollback modem configurations to factory default except some config which are in whitelist.
Jake Hambye994d462014-02-03 13:10:13 -08006659 * Used for device configuration by some CDMA operators.
6660 *
chen xu6dac5ab2018-10-26 17:39:23 -07006661 * @param slotIndex - device slot.
6662 *
Jake Hambye994d462014-02-03 13:10:13 -08006663 * @return true on success; false on any failure
6664 */
6665 @Override
chen xu6dac5ab2018-10-26 17:39:23 -07006666 public boolean resetModemConfig(int slotIndex) {
6667 Phone phone = PhoneFactory.getPhone(slotIndex);
6668 if (phone != null) {
6669 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6670 mApp, phone.getSubId(), "resetModemConfig");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006671
chen xu6dac5ab2018-10-26 17:39:23 -07006672 final long identity = Binder.clearCallingIdentity();
6673 try {
6674 Boolean success = (Boolean) sendRequest(CMD_RESET_MODEM_CONFIG, null);
6675 if (DBG) log("resetModemConfig:" + ' ' + (success ? "ok" : "fail"));
6676 return success;
6677 } finally {
6678 Binder.restoreCallingIdentity(identity);
6679 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006680 }
chen xu6dac5ab2018-10-26 17:39:23 -07006681 return false;
6682 }
6683
6684 /**
6685 * Generate a radio modem reset. Used for device configuration by some CDMA operators.
6686 *
6687 * @param slotIndex - device slot.
6688 *
6689 * @return true on success; false on any failure
6690 */
6691 @Override
6692 public boolean rebootModem(int slotIndex) {
6693 Phone phone = PhoneFactory.getPhone(slotIndex);
6694 if (phone != null) {
6695 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6696 mApp, phone.getSubId(), "rebootModem");
6697
6698 final long identity = Binder.clearCallingIdentity();
6699 try {
6700 Boolean success = (Boolean) sendRequest(CMD_MODEM_REBOOT, null);
6701 if (DBG) log("rebootModem:" + ' ' + (success ? "ok" : "fail"));
6702 return success;
6703 } finally {
6704 Binder.restoreCallingIdentity(identity);
6705 }
6706 }
6707 return false;
Jake Hambye994d462014-02-03 13:10:13 -08006708 }
Jake Hamby7c27be32014-03-03 13:25:59 -08006709
Brad Ebinger51f743a2017-01-23 13:50:20 -08006710 /**
Grace Jiaaa2eb6b2020-01-09 16:26:08 -08006711 * Toggle IMS disable and enable for the framework to reset it. See {@link #enableIms(int)} and
6712 * {@link #disableIms(int)}.
6713 * @param slotIndex device slot.
6714 */
6715 public void resetIms(int slotIndex) {
6716 enforceModifyPermission();
6717
6718 final long identity = Binder.clearCallingIdentity();
6719 try {
6720 if (mImsResolver == null) {
6721 // may happen if the does not support IMS.
6722 return;
6723 }
Hyunhoa17ac7c2022-08-30 12:03:04 +00006724 mImsResolver.resetIms(slotIndex);
Grace Jiaaa2eb6b2020-01-09 16:26:08 -08006725 } finally {
6726 Binder.restoreCallingIdentity(identity);
6727 }
6728 }
6729
6730 /**
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006731 * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
6732 * status updates, if not already enabled.
Brad Ebinger51f743a2017-01-23 13:50:20 -08006733 */
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006734 public void enableIms(int slotId) {
Brad Ebinger51f743a2017-01-23 13:50:20 -08006735 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006736
6737 final long identity = Binder.clearCallingIdentity();
6738 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006739 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006740 // may happen if the device does not support IMS.
6741 return;
6742 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006743 mImsResolver.enableIms(slotId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006744 } finally {
6745 Binder.restoreCallingIdentity(identity);
6746 }
Brad Ebinger34bef922017-11-09 10:27:08 -08006747 }
6748
6749 /**
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006750 * Disables IMS for the framework. This will trigger IMS de-registration and trigger ImsFeature
6751 * status updates to disabled.
Brad Ebinger34bef922017-11-09 10:27:08 -08006752 */
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006753 public void disableIms(int slotId) {
6754 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006755
6756 final long identity = Binder.clearCallingIdentity();
6757 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006758 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006759 // may happen if the device does not support IMS.
6760 return;
6761 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006762 mImsResolver.disableIms(slotId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006763 } finally {
6764 Binder.restoreCallingIdentity(identity);
6765 }
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006766 }
6767
6768 /**
Brad Ebinger67b3e042020-09-11 12:45:11 -07006769 * Registers for updates to the MmTelFeature connection through the IImsServiceFeatureCallback
6770 * callback.
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006771 */
Brad Ebinger67b3e042020-09-11 12:45:11 -07006772 @Override
Brad Ebingerf6aca002020-10-01 13:51:05 -07006773 public void registerMmTelFeatureCallback(int slotId, IImsServiceFeatureCallback callback) {
Brad Ebinger34bef922017-11-09 10:27:08 -08006774 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006775
6776 final long identity = Binder.clearCallingIdentity();
6777 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006778 if (mImsResolver == null) {
Brad Ebinger67b3e042020-09-11 12:45:11 -07006779 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
6780 "Device does not support IMS");
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006781 }
Brad Ebingerf6aca002020-10-01 13:51:05 -07006782 mImsResolver.listenForFeature(slotId, ImsFeature.FEATURE_MMTEL, callback);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006783 } finally {
6784 Binder.restoreCallingIdentity(identity);
6785 }
Brad Ebinger34bef922017-11-09 10:27:08 -08006786 }
Brad Ebinger5f64b052017-12-14 14:26:15 -08006787 /**
Brad Ebinger075ff3a2020-05-18 17:52:58 -07006788 * Unregister a previously registered IImsServiceFeatureCallback associated with an ImsFeature.
6789 */
Brad Ebinger67b3e042020-09-11 12:45:11 -07006790 @Override
6791 public void unregisterImsFeatureCallback(IImsServiceFeatureCallback callback) {
Brad Ebinger075ff3a2020-05-18 17:52:58 -07006792 enforceModifyPermission();
6793
6794 final long identity = Binder.clearCallingIdentity();
6795 try {
6796 if (mImsResolver == null) return;
Brad Ebinger67b3e042020-09-11 12:45:11 -07006797 mImsResolver.unregisterImsFeatureCallback(callback);
Brad Ebinger075ff3a2020-05-18 17:52:58 -07006798 } finally {
6799 Binder.restoreCallingIdentity(identity);
6800 }
6801 }
6802
6803 /**
Brad Ebinger5f64b052017-12-14 14:26:15 -08006804 * Returns the {@link IImsRegistration} structure associated with the slotId and feature
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006805 * specified or null if IMS is not supported on the slot specified.
Brad Ebinger5f64b052017-12-14 14:26:15 -08006806 */
6807 public IImsRegistration getImsRegistration(int slotId, int feature) throws RemoteException {
6808 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006809
6810 final long identity = Binder.clearCallingIdentity();
6811 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006812 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006813 // may happen if the device does not support IMS.
6814 return null;
6815 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006816 return mImsResolver.getImsRegistration(slotId, feature);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006817 } finally {
6818 Binder.restoreCallingIdentity(identity);
6819 }
Brad Ebinger5f64b052017-12-14 14:26:15 -08006820 }
6821
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006822 /**
6823 * Returns the {@link IImsConfig} structure associated with the slotId and feature
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006824 * specified or null if IMS is not supported on the slot specified.
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006825 */
6826 public IImsConfig getImsConfig(int slotId, int feature) throws RemoteException {
6827 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006828
6829 final long identity = Binder.clearCallingIdentity();
6830 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006831 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006832 // may happen if the device does not support IMS.
6833 return null;
6834 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006835 return mImsResolver.getImsConfig(slotId, feature);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006836 } finally {
6837 Binder.restoreCallingIdentity(identity);
6838 }
Brad Ebinger22bc3e42018-01-16 09:39:35 -08006839 }
6840
Brad Ebinger884c07b2018-02-15 16:17:40 -08006841 /**
Brad Ebingerdac2f002018-04-03 15:17:52 -07006842 * Sets the ImsService Package Name that Telephony will bind to.
6843 *
Brad Ebinger24c29992019-12-05 13:03:21 -08006844 * @param slotIndex the slot ID that the ImsService should bind for.
6845 * @param isCarrierService true if the ImsService is the carrier override, false if the
Brad Ebingerdac2f002018-04-03 15:17:52 -07006846 * ImsService is the device default ImsService.
Brad Ebinger24c29992019-12-05 13:03:21 -08006847 * @param featureTypes An integer array of feature types associated with a packageName.
6848 * @param packageName The name of the package that the current configuration will be replaced
6849 * with.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006850 * @return true if setting the ImsService to bind to succeeded, false if it did not.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006851 */
Brad Ebinger24c29992019-12-05 13:03:21 -08006852 public boolean setBoundImsServiceOverride(int slotIndex, boolean isCarrierService,
6853 int[] featureTypes, String packageName) {
Brad Ebinger24c29992019-12-05 13:03:21 -08006854 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setBoundImsServiceOverride");
Brad Ebingerde696de2018-04-06 09:56:40 -07006855 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
Jack Yu00ece8c2022-11-19 22:29:12 -08006856 SubscriptionManager.getSubscriptionId(slotIndex), "setBoundImsServiceOverride");
Brad Ebingerde696de2018-04-06 09:56:40 -07006857
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006858 final long identity = Binder.clearCallingIdentity();
6859 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006860 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006861 // may happen if the device does not support IMS.
6862 return false;
6863 }
Brad Ebinger24c29992019-12-05 13:03:21 -08006864 Map<Integer, String> featureConfig = new HashMap<>();
6865 for (int featureType : featureTypes) {
6866 featureConfig.put(featureType, packageName);
6867 }
6868 return mImsResolver.overrideImsServiceConfiguration(slotIndex, isCarrierService,
6869 featureConfig);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006870 } finally {
6871 Binder.restoreCallingIdentity(identity);
6872 }
Brad Ebingerdac2f002018-04-03 15:17:52 -07006873 }
6874
6875 /**
Brad Ebinger999d3302020-11-25 14:31:39 -08006876 * Clears any carrier ImsService overrides for the slot index specified that were previously
6877 * set with {@link #setBoundImsServiceOverride(int, boolean, int[], String)}.
6878 *
6879 * This should only be used for testing.
6880 *
6881 * @param slotIndex the slot ID that the ImsService should bind for.
6882 * @return true if clearing the carrier ImsService override succeeded or false if it did not.
6883 */
6884 @Override
6885 public boolean clearCarrierImsServiceOverride(int slotIndex) {
Brad Ebinger999d3302020-11-25 14:31:39 -08006886 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
6887 "clearCarrierImsServiceOverride");
6888 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
Jack Yu00ece8c2022-11-19 22:29:12 -08006889 SubscriptionManager.getSubscriptionId(slotIndex), "clearCarrierImsServiceOverride");
Brad Ebinger999d3302020-11-25 14:31:39 -08006890
6891 final long identity = Binder.clearCallingIdentity();
6892 try {
6893 if (mImsResolver == null) {
6894 // may happen if the device does not support IMS.
6895 return false;
6896 }
6897 return mImsResolver.clearCarrierImsServiceConfiguration(slotIndex);
6898 } finally {
6899 Binder.restoreCallingIdentity(identity);
6900 }
6901 }
6902
6903 /**
Brad Ebinger24c29992019-12-05 13:03:21 -08006904 * Return the package name of the currently bound ImsService.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006905 *
6906 * @param slotId The slot that the ImsService is associated with.
6907 * @param isCarrierImsService true, if the ImsService is a carrier override, false if it is
6908 * the device default.
Brad Ebinger24c29992019-12-05 13:03:21 -08006909 * @param featureType The feature associated with the queried configuration.
Brad Ebingerdac2f002018-04-03 15:17:52 -07006910 * @return the package name of the ImsService configuration.
6911 */
Brad Ebinger24c29992019-12-05 13:03:21 -08006912 public String getBoundImsServicePackage(int slotId, boolean isCarrierImsService,
6913 @ImsFeature.FeatureType int featureType) {
Brad Ebinger24c29992019-12-05 13:03:21 -08006914 TelephonyPermissions
Jack Yu00ece8c2022-11-19 22:29:12 -08006915 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(mApp,
6916 SubscriptionManager.getSubscriptionId(slotId), "getBoundImsServicePackage");
Brad Ebingerde696de2018-04-06 09:56:40 -07006917
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006918 final long identity = Binder.clearCallingIdentity();
6919 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08006920 if (mImsResolver == null) {
Brad Ebinger9c0eb502019-01-23 15:06:19 -08006921 // may happen if the device does not support IMS.
6922 return "";
6923 }
Brad Ebingera80c3312019-12-02 10:59:39 -08006924 // TODO: change API to query RCS separately.
Brad Ebinger24c29992019-12-05 13:03:21 -08006925 return mImsResolver.getImsServiceConfiguration(slotId, isCarrierImsService,
6926 featureType);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006927 } finally {
6928 Binder.restoreCallingIdentity(identity);
6929 }
Brad Ebingerdac2f002018-04-03 15:17:52 -07006930 }
6931
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006932 /**
6933 * Get the MmTelFeature state associated with the requested subscription id.
6934 * @param subId The subscription that the MmTelFeature is associated with.
6935 * @param callback A callback with an integer containing the
6936 * {@link android.telephony.ims.feature.ImsFeature.ImsState} associated with the MmTelFeature.
6937 */
6938 @Override
6939 public void getImsMmTelFeatureState(int subId, IIntegerConsumer callback) {
6940 enforceReadPrivilegedPermission("getImsMmTelFeatureState");
Brad Ebingera2628302022-02-18 03:44:55 +00006941 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
6942 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
6943 "IMS not available on device.");
6944 }
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006945 final long token = Binder.clearCallingIdentity();
6946 try {
Brad Ebingera2628302022-02-18 03:44:55 +00006947 int slotId = getSlotIndex(subId);
6948 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
6949 Log.w(LOG_TAG, "getImsMmTelFeatureState: called with an inactive subscription '"
6950 + subId + "'");
6951 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
6952 }
6953 verifyImsMmTelConfiguredOrThrow(slotId);
6954 ImsManager.getInstance(mApp, slotId).getImsServiceState(anInteger -> {
6955 try {
6956 callback.accept(anInteger == null ? ImsFeature.STATE_UNAVAILABLE : anInteger);
6957 } catch (RemoteException e) {
6958 Log.w(LOG_TAG, "getImsMmTelFeatureState: remote caller is no longer running. "
6959 + "Ignore");
6960 }
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006961 });
Brad Ebinger919631e2021-06-02 17:46:35 -07006962 } catch (ImsException e) {
6963 throw new ServiceSpecificException(e.getCode());
Brad Ebingerbc7dd582019-10-17 17:03:22 -07006964 } finally {
6965 Binder.restoreCallingIdentity(token);
6966 }
6967 }
6968
Daniel Brightbb5840b2021-01-12 15:48:18 -08006969 /**
6970 * Sets the ims registration state on all valid {@link Phone}s.
6971 */
6972 public void setImsRegistrationState(final boolean registered) {
Wink Saville36469e72014-06-11 15:17:00 -07006973 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006974
6975 final long identity = Binder.clearCallingIdentity();
6976 try {
Daniel Brightbb5840b2021-01-12 15:48:18 -08006977 // NOTE: Before S, this method only set the default phone.
6978 for (final Phone phone : PhoneFactory.getPhones()) {
6979 if (SubscriptionManager.isValidSubscriptionId(phone.getSubId())) {
6980 phone.setImsRegistrationState(registered);
6981 }
6982 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006983 } finally {
6984 Binder.restoreCallingIdentity(identity);
6985 }
Wink Saville36469e72014-06-11 15:17:00 -07006986 }
6987
6988 /**
Stuart Scott54788802015-03-30 13:18:01 -07006989 * Set the network selection mode to automatic.
6990 *
6991 */
6992 @Override
6993 public void setNetworkSelectionModeAutomatic(int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08006994 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
6995 mApp, subId, "setNetworkSelectionModeAutomatic");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08006996
6997 final long identity = Binder.clearCallingIdentity();
6998 try {
shilufc958392020-01-20 11:36:01 -08006999 if (!isActiveSubscription(subId)) {
7000 return;
7001 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007002 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
Rambo Wang0f050d82021-02-12 11:43:36 -08007003 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId,
7004 SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007005 } finally {
7006 Binder.restoreCallingIdentity(identity);
7007 }
Stuart Scott54788802015-03-30 13:18:01 -07007008 }
7009
Jack Yud10cdd42020-09-28 20:28:01 -07007010 /**
Pengquan Mengea84e042018-09-20 14:57:26 -07007011 * Ask the radio to connect to the input network and change selection mode to manual.
7012 *
7013 * @param subId the id of the subscription.
7014 * @param operatorInfo the operator information, included the PLMN, long name and short name of
7015 * the operator to attach to.
7016 * @param persistSelection whether the selection will persist until reboot. If true, only allows
7017 * attaching to the selected PLMN until reboot; otherwise, attach to the chosen PLMN and resume
7018 * normal network selection next time.
7019 * @return {@code true} on success; {@code true} on any failure.
Shishir Agrawal302c8692015-06-19 13:49:39 -07007020 */
7021 @Override
Pengquan Mengea84e042018-09-20 14:57:26 -07007022 public boolean setNetworkSelectionModeManual(
7023 int subId, OperatorInfo operatorInfo, boolean persistSelection) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007024 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7025 mApp, subId, "setNetworkSelectionModeManual");
Pengquan Menge92a50d2018-09-21 15:54:48 -07007026
Jack Yu285100e2022-12-02 22:48:35 -08007027 final long identity = Binder.clearCallingIdentity();
Pengquan Menge92a50d2018-09-21 15:54:48 -07007028 if (!isActiveSubscription(subId)) {
7029 return false;
7030 }
7031
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007032 try {
Pengquan Mengea84e042018-09-20 14:57:26 -07007033 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operatorInfo,
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007034 persistSelection);
Pengquan Mengea84e042018-09-20 14:57:26 -07007035 if (DBG) {
7036 log("setNetworkSelectionModeManual: subId: " + subId
7037 + " operator: " + operatorInfo);
7038 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007039 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
7040 } finally {
7041 Binder.restoreCallingIdentity(identity);
7042 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07007043 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007044 /**
shilu84f6e8b2019-12-19 13:58:01 -08007045 * Get the manual network selection
7046 *
7047 * @param subId the id of the subscription.
7048 *
7049 * @return the previously saved user selected PLMN
7050 */
7051 @Override
7052 public String getManualNetworkSelectionPlmn(int subId) {
7053 TelephonyPermissions
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007054 .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
7055 mApp, subId, "getManualNetworkSelectionPlmn");
shilu84f6e8b2019-12-19 13:58:01 -08007056
7057 final long identity = Binder.clearCallingIdentity();
7058 try {
7059 if (!isActiveSubscription(subId)) {
shilufa1c2592020-03-10 10:59:43 -07007060 throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
shilu84f6e8b2019-12-19 13:58:01 -08007061 }
7062
7063 final Phone phone = getPhone(subId);
7064 if (phone == null) {
shilufa1c2592020-03-10 10:59:43 -07007065 throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
shilu84f6e8b2019-12-19 13:58:01 -08007066 }
7067 OperatorInfo networkSelection = phone.getSavedNetworkSelection();
7068 return TextUtils.isEmpty(networkSelection.getOperatorNumeric())
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007069 ? phone.getManualNetworkSelectionPlmn() : networkSelection.getOperatorNumeric();
shilu84f6e8b2019-12-19 13:58:01 -08007070 } finally {
7071 Binder.restoreCallingIdentity(identity);
7072 }
7073 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07007074
7075 /**
7076 * Scans for available networks.
7077 */
7078 @Override
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07007079 public CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage,
7080 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007081 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7082 mApp, subId, "getCellNetworkScanResults");
Hall Liuf19c44f2018-11-27 14:38:17 -08007083 LocationAccessPolicy.LocationPermissionResult locationResult =
7084 LocationAccessPolicy.checkLocationPermission(mApp,
7085 new LocationAccessPolicy.LocationPermissionQuery.Builder()
7086 .setCallingPackage(callingPackage)
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07007087 .setCallingFeatureId(callingFeatureId)
Hall Liuf19c44f2018-11-27 14:38:17 -08007088 .setCallingPid(Binder.getCallingPid())
7089 .setCallingUid(Binder.getCallingUid())
7090 .setMethod("getCellNetworkScanResults")
7091 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
Hall Liuc4a3e422020-05-26 17:18:03 -07007092 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
7093 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
Hall Liuf19c44f2018-11-27 14:38:17 -08007094 .build());
7095 switch (locationResult) {
7096 case DENIED_HARD:
7097 throw new SecurityException("Not allowed to access scan results -- location");
7098 case DENIED_SOFT:
7099 return null;
7100 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007101
Pengquan Menga1bb6272018-09-06 09:59:22 -07007102 long identity = Binder.clearCallingIdentity();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007103 try {
7104 if (DBG) log("getCellNetworkScanResults: subId " + subId);
Pengquan Menga1bb6272018-09-06 09:59:22 -07007105 return (CellNetworkScanResult) sendRequest(
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007106 CMD_PERFORM_NETWORK_SCAN, null, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007107 } finally {
7108 Binder.restoreCallingIdentity(identity);
7109 }
Shishir Agrawal302c8692015-06-19 13:49:39 -07007110 }
7111
7112 /**
Shuo Qian4a594052020-01-23 11:59:30 -08007113 * Get the call forwarding info, given the call forwarding reason.
7114 */
7115 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007116 public void getCallForwarding(int subId, int callForwardingReason,
7117 ICallForwardingInfoCallback callback) {
Shuo Qian4a594052020-01-23 11:59:30 -08007118 enforceReadPrivilegedPermission("getCallForwarding");
7119 long identity = Binder.clearCallingIdentity();
7120 try {
7121 if (DBG) {
7122 log("getCallForwarding: subId " + subId
7123 + " callForwardingReason" + callForwardingReason);
7124 }
Hall Liu27d24262020-09-18 19:04:59 -07007125
7126 Phone phone = getPhone(subId);
7127 if (phone == null) {
7128 try {
Hall Liu940c4ca2020-09-29 17:10:18 -07007129 callback.onError(
7130 TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
Hall Liu27d24262020-09-18 19:04:59 -07007131 } catch (RemoteException e) {
7132 // ignore
7133 }
7134 return;
7135 }
7136
7137 Pair<Integer, TelephonyManager.CallForwardingInfoCallback> argument = Pair.create(
7138 callForwardingReason, new TelephonyManager.CallForwardingInfoCallback() {
7139 @Override
7140 public void onCallForwardingInfoAvailable(CallForwardingInfo info) {
7141 try {
7142 callback.onCallForwardingInfoAvailable(info);
7143 } catch (RemoteException e) {
7144 // ignore
7145 }
7146 }
7147
7148 @Override
7149 public void onError(int error) {
7150 try {
7151 callback.onError(error);
7152 } catch (RemoteException e) {
7153 // ignore
7154 }
7155 }
7156 });
7157 sendRequestAsync(CMD_GET_CALL_FORWARDING, argument, phone, null);
Shuo Qian4a594052020-01-23 11:59:30 -08007158 } finally {
7159 Binder.restoreCallingIdentity(identity);
7160 }
7161 }
7162
7163 /**
7164 * Sets the voice call forwarding info including status (enable/disable), call forwarding
7165 * reason, the number to forward, and the timeout before the forwarding is attempted.
7166 */
7167 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007168 public void setCallForwarding(int subId, CallForwardingInfo callForwardingInfo,
7169 IIntegerConsumer callback) {
Shuo Qian4a594052020-01-23 11:59:30 -08007170 enforceModifyPermission();
7171 long identity = Binder.clearCallingIdentity();
7172 try {
7173 if (DBG) {
7174 log("setCallForwarding: subId " + subId
7175 + " callForwardingInfo" + callForwardingInfo);
7176 }
Hall Liu27d24262020-09-18 19:04:59 -07007177
7178 Phone phone = getPhone(subId);
7179 if (phone == null) {
7180 try {
Hall Liu940c4ca2020-09-29 17:10:18 -07007181 callback.accept(
7182 TelephonyManager.CallForwardingInfoCallback.RESULT_ERROR_UNKNOWN);
Hall Liu27d24262020-09-18 19:04:59 -07007183 } catch (RemoteException e) {
7184 // ignore
7185 }
7186 return;
7187 }
7188
7189 Pair<CallForwardingInfo, Consumer<Integer>> arguments = Pair.create(callForwardingInfo,
7190 FunctionalUtils.ignoreRemoteException(callback::accept));
7191
7192 sendRequestAsync(CMD_SET_CALL_FORWARDING, arguments, phone, null);
Shuo Qian4a594052020-01-23 11:59:30 -08007193 } finally {
7194 Binder.restoreCallingIdentity(identity);
7195 }
7196 }
7197
7198 /**
Hall Liu27d24262020-09-18 19:04:59 -07007199 * Get the call waiting status for a subId.
Shuo Qian4a594052020-01-23 11:59:30 -08007200 */
7201 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007202 public void getCallWaitingStatus(int subId, IIntegerConsumer callback) {
SongFerngWang0e767992021-03-31 22:08:45 +08007203 enforceReadPrivilegedPermission("getCallWaitingStatus");
Shuo Qian4a594052020-01-23 11:59:30 -08007204 long identity = Binder.clearCallingIdentity();
7205 try {
Hall Liu27d24262020-09-18 19:04:59 -07007206 Phone phone = getPhone(subId);
7207 if (phone == null) {
7208 try {
7209 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
7210 } catch (RemoteException e) {
7211 // ignore
7212 }
7213 return;
7214 }
SongFerngWang0e767992021-03-31 22:08:45 +08007215 CarrierConfigManager configManager = new CarrierConfigManager(phone.getContext());
7216 PersistableBundle c = configManager.getConfigForSubId(subId);
7217 boolean requireUssd = c.getBoolean(
7218 CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false);
Hall Liu27d24262020-09-18 19:04:59 -07007219
Shuo Qian4a594052020-01-23 11:59:30 -08007220 if (DBG) log("getCallWaitingStatus: subId " + subId);
SongFerngWang0e767992021-03-31 22:08:45 +08007221 if (requireUssd) {
7222 CarrierXmlParser carrierXmlParser = new CarrierXmlParser(phone.getContext(),
7223 getSubscriptionCarrierId(subId));
7224 String newUssdCommand = "";
7225 try {
7226 newUssdCommand = carrierXmlParser.getFeature(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007227 CarrierXmlParser.FEATURE_CALL_WAITING)
SongFerngWang0e767992021-03-31 22:08:45 +08007228 .makeCommand(CarrierXmlParser.SsEntry.SSAction.QUERY, null);
7229 } catch (NullPointerException e) {
7230 loge("Failed to generate USSD number" + e);
7231 }
7232 ResultReceiver wrappedCallback = new CallWaitingUssdResultReceiver(
7233 mMainThreadHandler, callback, carrierXmlParser,
7234 CarrierXmlParser.SsEntry.SSAction.QUERY);
7235 final String ussdCommand = newUssdCommand;
7236 Executors.newSingleThreadExecutor().execute(() -> {
7237 handleUssdRequest(subId, ussdCommand, wrappedCallback);
7238 });
7239 } else {
7240 Consumer<Integer> argument = FunctionalUtils.ignoreRemoteException(
7241 callback::accept);
7242 sendRequestAsync(CMD_GET_CALL_WAITING, argument, phone, null);
7243 }
Shuo Qian4a594052020-01-23 11:59:30 -08007244 } finally {
7245 Binder.restoreCallingIdentity(identity);
7246 }
7247 }
7248
7249 /**
Hall Liu27d24262020-09-18 19:04:59 -07007250 * Sets whether call waiting is enabled for a given subId.
Shuo Qian4a594052020-01-23 11:59:30 -08007251 */
7252 @Override
Hall Liu27d24262020-09-18 19:04:59 -07007253 public void setCallWaitingStatus(int subId, boolean enable, IIntegerConsumer callback) {
Shuo Qian4a594052020-01-23 11:59:30 -08007254 enforceModifyPermission();
7255 long identity = Binder.clearCallingIdentity();
7256 try {
Hall Liu27d24262020-09-18 19:04:59 -07007257 if (DBG) log("setCallWaitingStatus: subId " + subId + " enable: " + enable);
7258
7259 Phone phone = getPhone(subId);
7260 if (phone == null) {
7261 try {
7262 callback.accept(TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR);
7263 } catch (RemoteException e) {
7264 // ignore
7265 }
7266 return;
7267 }
7268
SongFerngWang0e767992021-03-31 22:08:45 +08007269 CarrierConfigManager configManager = new CarrierConfigManager(phone.getContext());
7270 PersistableBundle c = configManager.getConfigForSubId(subId);
7271 boolean requireUssd = c.getBoolean(
7272 CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false);
Hall Liu27d24262020-09-18 19:04:59 -07007273
SongFerngWang0e767992021-03-31 22:08:45 +08007274 if (DBG) log("getCallWaitingStatus: subId " + subId);
7275 if (requireUssd) {
7276 CarrierXmlParser carrierXmlParser = new CarrierXmlParser(phone.getContext(),
7277 getSubscriptionCarrierId(subId));
7278 CarrierXmlParser.SsEntry.SSAction ssAction =
7279 enable ? CarrierXmlParser.SsEntry.SSAction.UPDATE_ACTIVATE
7280 : CarrierXmlParser.SsEntry.SSAction.UPDATE_DEACTIVATE;
7281 String newUssdCommand = "";
7282 try {
7283 newUssdCommand = carrierXmlParser.getFeature(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007284 CarrierXmlParser.FEATURE_CALL_WAITING)
SongFerngWang0e767992021-03-31 22:08:45 +08007285 .makeCommand(ssAction, null);
7286 } catch (NullPointerException e) {
7287 loge("Failed to generate USSD number" + e);
7288 }
7289 ResultReceiver wrappedCallback = new CallWaitingUssdResultReceiver(
7290 mMainThreadHandler, callback, carrierXmlParser, ssAction);
7291 final String ussdCommand = newUssdCommand;
7292 Executors.newSingleThreadExecutor().execute(() -> {
7293 handleUssdRequest(subId, ussdCommand, wrappedCallback);
7294 });
7295 } else {
7296 Pair<Boolean, Consumer<Integer>> arguments = Pair.create(enable,
7297 FunctionalUtils.ignoreRemoteException(callback::accept));
7298
7299 sendRequestAsync(CMD_SET_CALL_WAITING, arguments, phone, null);
7300 }
Shuo Qian4a594052020-01-23 11:59:30 -08007301 } finally {
7302 Binder.restoreCallingIdentity(identity);
7303 }
7304 }
7305
7306 /**
yinxub1bed742017-04-17 11:45:04 -07007307 * Starts a new network scan and returns the id of this scan.
yinxu504e1392017-04-12 16:03:22 -07007308 *
yinxub1bed742017-04-17 11:45:04 -07007309 * @param subId id of the subscription
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007310 * @param renounceFineLocationAccess Set this to true if the caller would not like to receive
7311 * location related information which will be sent if the caller already possess
7312 * {@android.Manifest.permission.ACCESS_FINE_LOCATION} and do not renounce the permission
yinxub1bed742017-04-17 11:45:04 -07007313 * @param request contains the radio access networks with bands/channels to scan
7314 * @param messenger callback messenger for scan results or errors
7315 * @param binder for the purpose of auto clean when the user thread crashes
yinxu504e1392017-04-12 16:03:22 -07007316 * @return the id of the requested scan which can be used to stop the scan.
7317 */
7318 @Override
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007319 public int requestNetworkScan(int subId, boolean renounceFineLocationAccess,
7320 NetworkScanRequest request, Messenger messenger,
Philip P. Moltmann3a2772a2019-10-04 08:15:00 -07007321 IBinder binder, String callingPackage, String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007322 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7323 mApp, subId, "requestNetworkScan");
Hall Liuf19c44f2018-11-27 14:38:17 -08007324 LocationAccessPolicy.LocationPermissionResult locationResult =
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007325 LocationAccessPolicy.LocationPermissionResult.DENIED_HARD;
7326 if (!renounceFineLocationAccess) {
7327 locationResult = LocationAccessPolicy.checkLocationPermission(mApp,
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007328 new LocationAccessPolicy.LocationPermissionQuery.Builder()
7329 .setCallingPackage(callingPackage)
7330 .setCallingFeatureId(callingFeatureId)
7331 .setCallingPid(Binder.getCallingPid())
7332 .setCallingUid(Binder.getCallingUid())
7333 .setMethod("requestNetworkScan")
7334 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
7335 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
7336 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
7337 .build());
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007338 }
Hall Liub2ac8ef2019-02-28 15:56:23 -08007339 if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
Nathan Harold1c11dba2020-09-22 17:54:53 -07007340 SecurityException e = checkNetworkRequestForSanitizedLocationAccess(
7341 request, subId, callingPackage);
Hall Liub2ac8ef2019-02-28 15:56:23 -08007342 if (e != null) {
7343 if (locationResult == LocationAccessPolicy.LocationPermissionResult.DENIED_HARD) {
7344 throw e;
7345 } else {
Hall Liu0e5abaf2019-04-04 01:25:30 -07007346 loge(e.getMessage());
Hall Liub2ac8ef2019-02-28 15:56:23 -08007347 return TelephonyScanManager.INVALID_SCAN_ID;
7348 }
7349 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007350 }
Hall Liu912dfd32019-04-25 14:02:26 -07007351 int callingUid = Binder.getCallingUid();
7352 int callingPid = Binder.getCallingPid();
Ying Xu94a46582019-04-18 17:14:56 -07007353 final long identity = Binder.clearCallingIdentity();
7354 try {
7355 return mNetworkScanRequestTracker.startNetworkScan(
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08007356 renounceFineLocationAccess, request, messenger, binder, getPhone(subId),
Hall Liu912dfd32019-04-25 14:02:26 -07007357 callingUid, callingPid, callingPackage);
Ying Xu94a46582019-04-18 17:14:56 -07007358 } finally {
7359 Binder.restoreCallingIdentity(identity);
7360 }
yinxu504e1392017-04-12 16:03:22 -07007361 }
7362
Hall Liub2ac8ef2019-02-28 15:56:23 -08007363 private SecurityException checkNetworkRequestForSanitizedLocationAccess(
Nathan Harold1c11dba2020-09-22 17:54:53 -07007364 NetworkScanRequest request, int subId, String callingPackage) {
Rambo Wang3dee30a2022-10-20 16:52:29 +00007365 boolean hasCarrierPriv;
7366 final long identity = Binder.clearCallingIdentity();
7367 try {
7368 hasCarrierPriv = checkCarrierPrivilegesForPackage(subId, callingPackage)
7369 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
7370 } finally {
7371 Binder.restoreCallingIdentity(identity);
7372 }
Hall Liu558027f2019-05-15 19:14:05 -07007373 boolean hasNetworkScanPermission =
7374 mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
Thomas Nguyen8ee49682023-02-01 11:46:09 -08007375 == PERMISSION_GRANTED;
Hall Liu558027f2019-05-15 19:14:05 -07007376
7377 if (!hasCarrierPriv && !hasNetworkScanPermission) {
7378 return new SecurityException("permission.NETWORK_SCAN or carrier privileges is needed"
7379 + " for network scans without location access.");
Hall Liub2ac8ef2019-02-28 15:56:23 -08007380 }
7381
7382 if (request.getSpecifiers() != null && request.getSpecifiers().length > 0) {
7383 for (RadioAccessSpecifier ras : request.getSpecifiers()) {
Hall Liub2ac8ef2019-02-28 15:56:23 -08007384 if (ras.getChannels() != null && ras.getChannels().length > 0) {
7385 return new SecurityException("Specific channels must not be"
7386 + " scanned without location access.");
7387 }
7388 }
7389 }
7390
Hall Liub2ac8ef2019-02-28 15:56:23 -08007391 return null;
7392 }
7393
yinxu504e1392017-04-12 16:03:22 -07007394 /**
7395 * Stops an existing network scan with the given scanId.
yinxub1bed742017-04-17 11:45:04 -07007396 *
7397 * @param subId id of the subscription
7398 * @param scanId id of the scan that needs to be stopped
yinxu504e1392017-04-12 16:03:22 -07007399 */
7400 @Override
7401 public void stopNetworkScan(int subId, int scanId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007402 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7403 mApp, subId, "stopNetworkScan");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007404
Hall Liu912dfd32019-04-25 14:02:26 -07007405 int callingUid = Binder.getCallingUid();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007406 final long identity = Binder.clearCallingIdentity();
7407 try {
Hall Liu912dfd32019-04-25 14:02:26 -07007408 mNetworkScanRequestTracker.stopNetworkScan(scanId, callingUid);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007409 } finally {
7410 Binder.restoreCallingIdentity(identity);
7411 }
yinxu504e1392017-04-12 16:03:22 -07007412 }
7413
7414 /**
SongFerngWang3ef3e072020-12-21 16:41:52 +08007415 * Get the allowed network types bitmask.
Junda Liu84d15a22014-07-02 11:21:04 -07007416 *
SongFerngWang3ef3e072020-12-21 16:41:52 +08007417 * @return the allowed network types bitmask, defined in RILConstants.java.
Junda Liu84d15a22014-07-02 11:21:04 -07007418 */
7419 @Override
SongFerngWang3ef3e072020-12-21 16:41:52 +08007420 public int getAllowedNetworkTypesBitmask(int subId) {
Pengquan Menga4009cb2018-12-20 11:00:24 -08007421 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07007422 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
SongFerngWang3ef3e072020-12-21 16:41:52 +08007423 mApp, subId, "getAllowedNetworkTypesBitmask");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007424
7425 final long identity = Binder.clearCallingIdentity();
7426 try {
SongFerngWang3ef3e072020-12-21 16:41:52 +08007427 if (DBG) log("getAllowedNetworkTypesBitmask");
7428 int[] result = (int[]) sendRequest(CMD_GET_ALLOWED_NETWORK_TYPES_BITMASK, null, subId);
7429 int networkTypesBitmask = (result != null ? result[0] : -1);
7430 if (DBG) log("getAllowedNetworkTypesBitmask: " + networkTypesBitmask);
7431 return networkTypesBitmask;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007432 } finally {
7433 Binder.restoreCallingIdentity(identity);
7434 }
Jake Hamby7c27be32014-03-03 13:25:59 -08007435 }
7436
7437 /**
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007438 * Get the allowed network types for certain reason.
7439 *
7440 * @param subId the id of the subscription.
7441 * @param reason the reason the allowed network type change is taking place
7442 * @return the allowed network types.
7443 */
7444 @Override
7445 public long getAllowedNetworkTypesForReason(int subId,
7446 @TelephonyManager.AllowedNetworkTypesReason int reason) {
Nathan Harold62c68512021-04-06 11:26:02 -07007447 TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007448 mApp, subId, "getAllowedNetworkTypesForReason");
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007449 final long identity = Binder.clearCallingIdentity();
7450 try {
7451 return getPhoneFromSubId(subId).getAllowedNetworkTypes(reason);
7452 } finally {
7453 Binder.restoreCallingIdentity(identity);
7454 }
7455 }
7456
7457 /**
Sooraj Sasindran37444802020-08-11 10:40:43 -07007458 * Enable/Disable E-UTRA-NR Dual Connectivity
7459 * @param subId subscription id of the sim card
7460 * @param nrDualConnectivityState expected NR dual connectivity state
7461 * This can be passed following states
7462 * <ol>
7463 * <li>Enable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_ENABLE}
7464 * <li>Disable NR dual connectivity {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE}
7465 * <li>Disable NR dual connectivity and force secondary cell to be released
7466 * {@link TelephonyManager#NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE}
7467 * </ol>
7468 * @return operation result.
7469 */
7470 @Override
7471 public int setNrDualConnectivityState(int subId,
7472 @TelephonyManager.NrDualConnectivityState int nrDualConnectivityState) {
7473 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7474 mApp, subId, "enableNRDualConnectivity");
Sooraj Sasindran0e4e00a2021-03-16 18:02:32 -07007475 if (!isRadioInterfaceCapabilitySupported(
Sooraj Sasindrandfd595b2021-03-11 17:38:13 -08007476 TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE)) {
7477 return TelephonyManager.ENABLE_NR_DUAL_CONNECTIVITY_NOT_SUPPORTED;
7478 }
7479
Sooraj Sasindran37444802020-08-11 10:40:43 -07007480 WorkSource workSource = getWorkSource(Binder.getCallingUid());
7481 final long identity = Binder.clearCallingIdentity();
7482 try {
7483 int result = (int) sendRequest(CMD_ENABLE_NR_DUAL_CONNECTIVITY,
7484 nrDualConnectivityState, subId,
7485 workSource);
7486 if (DBG) log("enableNRDualConnectivity result: " + result);
7487 return result;
7488 } finally {
7489 Binder.restoreCallingIdentity(identity);
7490 }
7491 }
7492
7493 /**
7494 * Is E-UTRA-NR Dual Connectivity enabled
7495 * @return true if dual connectivity is enabled else false
7496 */
7497 @Override
7498 public boolean isNrDualConnectivityEnabled(int subId) {
7499 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07007500 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Sooraj Sasindran37444802020-08-11 10:40:43 -07007501 mApp, subId, "isNRDualConnectivityEnabled");
Sooraj Sasindran0e4e00a2021-03-16 18:02:32 -07007502 if (!isRadioInterfaceCapabilitySupported(
Sooraj Sasindrandfd595b2021-03-11 17:38:13 -08007503 TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE)) {
7504 return false;
7505 }
Sooraj Sasindran37444802020-08-11 10:40:43 -07007506 WorkSource workSource = getWorkSource(Binder.getCallingUid());
7507 final long identity = Binder.clearCallingIdentity();
7508 try {
7509 boolean isEnabled = (boolean) sendRequest(CMD_IS_NR_DUAL_CONNECTIVITY_ENABLED,
7510 null, subId, workSource);
7511 if (DBG) log("isNRDualConnectivityEnabled: " + isEnabled);
7512 return isEnabled;
7513 } finally {
7514 Binder.restoreCallingIdentity(identity);
7515 }
7516 }
7517
7518 /**
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007519 * Set the allowed network types of the device and
7520 * provide the reason triggering the allowed network change.
7521 *
7522 * @param subId the id of the subscription.
7523 * @param reason the reason the allowed network type change is taking place
7524 * @param allowedNetworkTypes the allowed network types.
7525 * @return true on success; false on any failure.
7526 */
7527 @Override
7528 public boolean setAllowedNetworkTypesForReason(int subId,
SongFerngWang3ef3e072020-12-21 16:41:52 +08007529 @TelephonyManager.AllowedNetworkTypesReason int reason,
7530 @TelephonyManager.NetworkTypeBitMask long allowedNetworkTypes) {
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007531 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
7532 mApp, subId, "setAllowedNetworkTypesForReason");
Gil Cukierman1d3d3752022-10-03 21:31:33 +00007533 // If the caller only has carrier privileges, then they should not be able to override
7534 // any network types which were set for security reasons.
7535 if (mApp.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE)
7536 != PERMISSION_GRANTED
Gil Cukierman2a8f48b2023-01-26 20:26:20 +00007537 && reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G) {
Gil Cukierman1d3d3752022-10-03 21:31:33 +00007538 throw new SecurityException(
7539 "setAllowedNetworkTypesForReason cannot be called with carrier privileges for"
Gil Cukierman2a8f48b2023-01-26 20:26:20 +00007540 + " reason " + reason);
Gil Cukierman1d3d3752022-10-03 21:31:33 +00007541 }
SongFerngWang3ef3e072020-12-21 16:41:52 +08007542 if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
Jack Yu5b494332023-01-23 18:18:04 +00007543 loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
SongFerngWang7ffc2732021-04-15 19:46:33 +08007544 return false;
7545 }
7546 if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
7547 loge("setAllowedNetworkTypesForReason: Invalid subscriptionId:" + subId);
SongFerngWang3ef3e072020-12-21 16:41:52 +08007548 return false;
7549 }
7550
Jack Yu5b494332023-01-23 18:18:04 +00007551 log("setAllowedNetworkTypesForReason: subId=" + subId + ", reason=" + reason + " value: "
7552 + TelephonyManager.convertNetworkTypeBitmaskToString(allowedNetworkTypes));
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007553
Jack Yue37dd262022-12-16 11:53:37 -08007554 Phone phone = getPhone(subId);
7555 if (phone == null) {
7556 return false;
7557 }
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007558
Jack Yue37dd262022-12-16 11:53:37 -08007559 if (allowedNetworkTypes == phone.getAllowedNetworkTypes(reason)) {
Jack Yu5b494332023-01-23 18:18:04 +00007560 log("setAllowedNetworkTypesForReason: " + reason + "does not change value");
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007561 return true;
SongFerngWang3ef3e072020-12-21 16:41:52 +08007562 }
SongFerngWang8c6e82e2021-03-02 22:09:29 +08007563
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007564 final long identity = Binder.clearCallingIdentity();
7565 try {
SongFerngWang3ef3e072020-12-21 16:41:52 +08007566 Boolean success = (Boolean) sendRequest(
7567 CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON,
7568 new Pair<Integer, Long>(reason, allowedNetworkTypes), subId);
7569
7570 if (DBG) log("setAllowedNetworkTypesForReason: " + (success ? "ok" : "fail"));
7571 return success;
Sooraj Sasindranc46dfbd2020-06-03 01:06:00 -07007572 } finally {
7573 Binder.restoreCallingIdentity(identity);
7574 }
7575 }
7576
7577 /**
Miaoa84611c2019-03-15 09:21:10 +08007578 * Check whether DUN APN is required for tethering with subId.
Junda Liu475951f2014-11-07 16:45:03 -08007579 *
Miaoa84611c2019-03-15 09:21:10 +08007580 * @param subId the id of the subscription to require tethering.
Amit Mahajanfe58cdf2017-07-11 12:01:53 -07007581 * @return {@code true} if DUN APN is required for tethering.
Junda Liu475951f2014-11-07 16:45:03 -08007582 * @hide
7583 */
7584 @Override
SongFerngWangf08d8122019-11-15 14:58:44 +08007585 public boolean isTetheringApnRequiredForSubscriber(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08007586 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007587 final long identity = Binder.clearCallingIdentity();
Miaoa84611c2019-03-15 09:21:10 +08007588 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007589 try {
Miaoa84611c2019-03-15 09:21:10 +08007590 if (phone != null) {
7591 return phone.hasMatchedTetherApnSetting();
7592 } else {
7593 return false;
7594 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007595 } finally {
7596 Binder.restoreCallingIdentity(identity);
Junda Liu475951f2014-11-07 16:45:03 -08007597 }
Junda Liu475951f2014-11-07 16:45:03 -08007598 }
7599
7600 /**
Malcolm Chen964682d2017-11-28 16:20:07 -08007601 * Get the user enabled state of Mobile Data.
7602 *
7603 * TODO: remove and use isUserDataEnabled.
7604 * This can't be removed now because some vendor codes
7605 * calls through ITelephony directly while they should
7606 * use TelephonyManager.
7607 *
7608 * @return true on enabled
7609 */
7610 @Override
7611 public boolean getDataEnabled(int subId) {
7612 return isUserDataEnabled(subId);
7613 }
7614
7615 /**
7616 * Get whether mobile data is enabled per user setting.
7617 *
7618 * There are other factors deciding whether mobile data is actually enabled, but they are
7619 * not considered here. See {@link #isDataEnabled(int)} for more details.
Robert Greenwalt646120a2014-05-23 11:54:03 -07007620 *
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007621 * Accepts either READ_BASIC_PHONE_STATE, ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE
7622 * or carrier privileges.
Robert Greenwalted86e582014-05-21 20:03:20 -07007623 *
7624 * @return {@code true} if data is enabled else {@code false}
7625 */
7626 @Override
Malcolm Chen964682d2017-11-28 16:20:07 -08007627 public boolean isUserDataEnabled(int subId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007628 String functionName = "isUserDataEnabled";
Robert Greenwalt646120a2014-05-23 11:54:03 -07007629 try {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007630 try {
7631 mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
7632 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007633 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007634 mApp.enforceCallingOrSelfPermission(permission.ACCESS_NETWORK_STATE, functionName);
7635 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007636 } catch (SecurityException e) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08007637 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007638 mApp, subId, functionName);
7639
Robert Greenwalt646120a2014-05-23 11:54:03 -07007640 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007641
7642 final long identity = Binder.clearCallingIdentity();
7643 try {
Jack Yu285100e2022-12-02 22:48:35 -08007644 int phoneId = SubscriptionManager.getPhoneId(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007645 if (DBG) log("isUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
7646 Phone phone = PhoneFactory.getPhone(phoneId);
7647 if (phone != null) {
7648 boolean retVal = phone.isUserDataEnabled();
7649 if (DBG) log("isUserDataEnabled: subId=" + subId + " retVal=" + retVal);
7650 return retVal;
7651 } else {
7652 if (DBG) loge("isUserDataEnabled: no phone subId=" + subId + " retVal=false");
7653 return false;
7654 }
7655 } finally {
7656 Binder.restoreCallingIdentity(identity);
Malcolm Chen964682d2017-11-28 16:20:07 -08007657 }
7658 }
7659
7660 /**
Shuo Qian8ee4e882020-01-08 14:30:06 -08007661 * Checks if the device is capable of mobile data by considering whether whether the
7662 * user has enabled mobile data, whether the carrier has enabled mobile data, and
7663 * whether the network policy allows data connections.
Malcolm Chen964682d2017-11-28 16:20:07 -08007664 *
Shuo Qian8ee4e882020-01-08 14:30:06 -08007665 * @return {@code true} if the overall data connection is capable; {@code false} if not.
Malcolm Chen964682d2017-11-28 16:20:07 -08007666 */
7667 @Override
7668 public boolean isDataEnabled(int subId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007669 String functionName = "isDataEnabled";
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007670 try {
7671 try {
7672 mApp.enforceCallingOrSelfPermission(
7673 android.Manifest.permission.ACCESS_NETWORK_STATE,
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007674 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007675 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007676 try {
7677 mApp.enforceCallingOrSelfPermission(
7678 android.Manifest.permission.READ_PHONE_STATE,
7679 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007680 } catch (SecurityException e2) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007681 mApp.enforceCallingOrSelfPermission(
7682 permission.READ_BASIC_PHONE_STATE, functionName);
7683 }
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007684 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007685 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007686 enforceReadPrivilegedPermission(functionName);
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007687 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007688
7689 final long identity = Binder.clearCallingIdentity();
7690 try {
Jack Yu285100e2022-12-02 22:48:35 -08007691 int phoneId = SubscriptionManager.getPhoneId(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007692 Phone phone = PhoneFactory.getPhone(phoneId);
7693 if (phone != null) {
Sarah Chine04784a2022-10-31 20:32:34 -07007694 boolean retVal = phone.getDataSettingsManager().isDataEnabled();
Jack Yu4ad64e52021-12-03 14:23:53 -08007695 if (DBG) log("isDataEnabled: " + retVal + ", subId=" + subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007696 return retVal;
7697 } else {
7698 if (DBG) loge("isDataEnabled: no phone subId=" + subId + " retVal=false");
7699 return false;
7700 }
7701 } finally {
7702 Binder.restoreCallingIdentity(identity);
Wink Savillee7353bb2014-12-05 14:21:41 -08007703 }
Robert Greenwalted86e582014-05-21 20:03:20 -07007704 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07007705
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007706 /**
7707 * Check if data is enabled for a specific reason
7708 * @param subId Subscription index
7709 * @param reason the reason the data enable change is taking place
7710 * @return {@code true} if the overall data is enabled; {@code false} if not.
7711 */
7712 @Override
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007713 public boolean isDataEnabledForReason(int subId,
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007714 @TelephonyManager.DataEnabledReason int reason) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007715 String functionName = "isDataEnabledForReason";
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007716 try {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007717 try {
7718 mApp.enforceCallingOrSelfPermission(
7719 android.Manifest.permission.ACCESS_NETWORK_STATE,
7720 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007721 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007722 mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
7723 functionName);
7724 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007725 } catch (SecurityException e) {
Sooraj Sasindran0d909a02021-11-08 12:01:16 -08007726 try {
7727 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007728 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07007729 } catch (SecurityException e2) {
Sooraj Sasindran0d909a02021-11-08 12:01:16 -08007730 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07007731 mApp, subId, functionName);
Sooraj Sasindran0d909a02021-11-08 12:01:16 -08007732 }
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007733 }
7734
7735
7736 final long identity = Binder.clearCallingIdentity();
7737 try {
Jack Yu285100e2022-12-02 22:48:35 -08007738 int phoneId = SubscriptionManager.getPhoneId(subId);
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007739 if (DBG) {
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007740 log("isDataEnabledForReason: subId=" + subId + " phoneId=" + phoneId
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007741 + " reason=" + reason);
7742 }
7743 Phone phone = PhoneFactory.getPhone(phoneId);
7744 if (phone != null) {
7745 boolean retVal;
Jack Yu7968c6d2022-07-31 00:43:21 -07007746 retVal = phone.getDataSettingsManager().isDataEnabledForReason(reason);
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007747 if (DBG) log("isDataEnabledForReason: retVal=" + retVal);
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007748 return retVal;
7749 } else {
7750 if (DBG) {
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07007751 loge("isDataEnabledForReason: no phone subId="
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00007752 + subId + " retVal=false");
7753 }
7754 return false;
7755 }
7756 } finally {
7757 Binder.restoreCallingIdentity(identity);
7758 }
7759 }
7760
Shishir Agrawal60f9c952014-06-23 12:00:43 -07007761 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08007762 public int getCarrierPrivilegeStatus(int subId) {
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007763 // No permission needed; this only lets the caller inspect their own status.
7764 return getCarrierPrivilegeStatusForUidWithPermission(subId, Binder.getCallingUid());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07007765 }
Junda Liu29340342014-07-10 15:23:27 -07007766
7767 @Override
Jeff Davidson7e17e312018-02-13 18:17:36 -08007768 public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08007769 enforceReadPrivilegedPermission("getCarrierPrivilegeStatusForUid");
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007770 return getCarrierPrivilegeStatusForUidWithPermission(subId, uid);
7771 }
7772
7773 private int getCarrierPrivilegeStatusForUidWithPermission(int subId, int uid) {
7774 Phone phone = getPhone(subId);
Jeff Davidson7e17e312018-02-13 18:17:36 -08007775 if (phone == null) {
Taesu Leef8fbed92019-10-07 18:47:02 +09007776 loge("getCarrierPrivilegeStatusForUid: Invalid subId");
Jeff Davidson7e17e312018-02-13 18:17:36 -08007777 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
7778 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007779 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7780 if (cpt == null) {
7781 loge("getCarrierPrivilegeStatusForUid: No CarrierPrivilegesTracker");
Jeff Davidson7e17e312018-02-13 18:17:36 -08007782 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
7783 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007784 return cpt.getCarrierPrivilegeStatusForUid(uid);
Jeff Davidson7e17e312018-02-13 18:17:36 -08007785 }
7786
7787 @Override
chen xuf7e9fe82019-05-09 19:31:02 -07007788 public int checkCarrierPrivilegesForPackage(int subId, String pkgName) {
Nazanin1adf4562021-03-29 15:35:30 -07007789 enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackage");
chen xuf7e9fe82019-05-09 19:31:02 -07007790 if (TextUtils.isEmpty(pkgName)) {
Junda Liu317d70b2016-03-08 09:33:53 -08007791 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
chen xuf7e9fe82019-05-09 19:31:02 -07007792 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007793 Phone phone = getPhone(subId);
7794 if (phone == null) {
7795 loge("checkCarrierPrivilegesForPackage: Invalid subId");
7796 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
7797 }
7798 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7799 if (cpt == null) {
7800 loge("checkCarrierPrivilegesForPackage: No CarrierPrivilegesTracker");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07007801 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
7802 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007803 return cpt.getCarrierPrivilegeStatusForPackage(pkgName);
Zach Johnson50ecba32015-05-19 00:24:21 -07007804 }
7805
7806 @Override
7807 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007808 enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackageAnyPhone");
Rambo Wange7209ce2022-02-23 13:41:02 -08007809 return checkCarrierPrivilegesForPackageAnyPhoneWithPermission(pkgName);
7810 }
7811
7812 private int checkCarrierPrivilegesForPackageAnyPhoneWithPermission(String pkgName) {
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007813 if (TextUtils.isEmpty(pkgName)) {
Junda Liu317d70b2016-03-08 09:33:53 -08007814 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007815 }
Zach Johnson50ecba32015-05-19 00:24:21 -07007816 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007817 for (int phoneId = 0; phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) {
7818 Phone phone = PhoneFactory.getPhone(phoneId);
7819 if (phone == null) {
7820 continue;
Zach Johnson50ecba32015-05-19 00:24:21 -07007821 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007822 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7823 if (cpt == null) {
7824 continue;
7825 }
7826 result = cpt.getCarrierPrivilegeStatusForPackage(pkgName);
Zach Johnson50ecba32015-05-19 00:24:21 -07007827 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
7828 break;
7829 }
7830 }
Zach Johnson50ecba32015-05-19 00:24:21 -07007831 return result;
Junda Liu29340342014-07-10 15:23:27 -07007832 }
Derek Tan89e89d42014-07-08 17:00:10 -07007833
7834 @Override
Junda Liue64de782015-04-16 17:19:16 -07007835 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
Nazanin1adf4562021-03-29 15:35:30 -07007836 enforceReadPrivilegedPermission("getCarrierPackageNamesForIntentAndPhone");
Rambo Wang8a247eb2022-02-08 21:11:18 +00007837 Phone phone = PhoneFactory.getPhone(phoneId);
7838 if (phone == null) {
7839 return Collections.emptyList();
Junda Liue64de782015-04-16 17:19:16 -07007840 }
Rambo Wang8a247eb2022-02-08 21:11:18 +00007841 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7842 if (cpt == null) {
7843 return Collections.emptyList();
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07007844 }
Rambo Wang8a247eb2022-02-08 21:11:18 +00007845 return cpt.getCarrierPackageNamesForIntent(intent);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07007846 }
7847
Amith Yamasani6e118872016-02-19 12:53:51 -08007848 @Override
chen xuf7e9fe82019-05-09 19:31:02 -07007849 public List<String> getPackagesWithCarrierPrivileges(int phoneId) {
Nazanin1adf4562021-03-29 15:35:30 -07007850 enforceReadPrivilegedPermission("getPackagesWithCarrierPrivileges");
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007851 Phone phone = PhoneFactory.getPhone(phoneId);
7852 if (phone == null) {
7853 return Collections.emptyList();
Amith Yamasani6e118872016-02-19 12:53:51 -08007854 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007855 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7856 if (cpt == null) {
7857 return Collections.emptyList();
7858 }
7859 return new ArrayList<>(cpt.getPackagesWithCarrierPrivileges());
Amith Yamasani6e118872016-02-19 12:53:51 -08007860 }
7861
chen xuf7e9fe82019-05-09 19:31:02 -07007862 @Override
7863 public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
Shuo Qian067a06d2019-12-03 23:40:18 +00007864 enforceReadPrivilegedPermission("getPackagesWithCarrierPrivilegesForAllPhones");
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007865 Set<String> privilegedPackages = new ArraySet<>();
Shuo Qian067a06d2019-12-03 23:40:18 +00007866 final long identity = Binder.clearCallingIdentity();
Shuo Qian067a06d2019-12-03 23:40:18 +00007867 try {
7868 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
7869 privilegedPackages.addAll(getPackagesWithCarrierPrivileges(i));
7870 }
7871 } finally {
7872 Binder.restoreCallingIdentity(identity);
chen xuf7e9fe82019-05-09 19:31:02 -07007873 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08007874 return new ArrayList<>(privilegedPackages);
chen xuf7e9fe82019-05-09 19:31:02 -07007875 }
7876
Rambo Wang6812ffb2022-03-15 16:54:17 -07007877 @Override
7878 public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
7879 enforceReadPrivilegedPermission("getCarrierServicePackageNameForLogicalSlot");
7880
7881 final Phone phone = PhoneFactory.getPhone(logicalSlotIndex);
7882 if (phone == null) {
7883 return null;
7884 }
7885 final CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
7886 if (cpt == null) {
7887 return null;
7888 }
7889 return cpt.getCarrierServicePackageName();
7890 }
7891
Wink Savilleb564aae2014-10-23 10:18:09 -07007892 private String getIccId(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07007893 final Phone phone = getPhone(subId);
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00007894 UiccPort port = phone == null ? null : phone.getUiccPort();
7895 if (port == null) {
Derek Tan97ebb422014-09-05 16:55:38 -07007896 return null;
7897 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00007898 String iccId = port.getIccId();
Derek Tan97ebb422014-09-05 16:55:38 -07007899 if (TextUtils.isEmpty(iccId)) {
Derek Tan97ebb422014-09-05 16:55:38 -07007900 return null;
7901 }
7902 return iccId;
7903 }
7904
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07007905 @Override
Shuo Qiane4e11672020-12-15 22:15:33 -08007906 public void setCallComposerStatus(int subId, int status) {
7907 enforceModifyPermission();
7908
7909 final long identity = Binder.clearCallingIdentity();
7910 try {
7911 Phone phone = getPhone(subId);
7912 if (phone != null) {
7913 Phone defaultPhone = phone.getImsPhone();
7914 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
7915 ImsPhone imsPhone = (ImsPhone) defaultPhone;
7916 imsPhone.setCallComposerStatus(status);
Shuo Qian284ae752020-12-22 19:10:14 -08007917 ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
7918 .updateImsServiceConfig();
Shuo Qiane4e11672020-12-15 22:15:33 -08007919 }
7920 }
Shuo Qian284ae752020-12-22 19:10:14 -08007921 } catch (ImsException e) {
7922 throw new ServiceSpecificException(e.getCode());
7923 } finally {
Shuo Qiane4e11672020-12-15 22:15:33 -08007924 Binder.restoreCallingIdentity(identity);
7925 }
7926 }
7927
7928 @Override
7929 public int getCallComposerStatus(int subId) {
7930 enforceReadPrivilegedPermission("getCallComposerStatus");
7931
7932 final long identity = Binder.clearCallingIdentity();
7933 try {
7934 Phone phone = getPhone(subId);
7935 if (phone != null) {
7936 Phone defaultPhone = phone.getImsPhone();
7937 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
7938 ImsPhone imsPhone = (ImsPhone) defaultPhone;
7939 return imsPhone.getCallComposerStatus();
7940 }
7941 }
7942 } finally {
7943 Binder.restoreCallingIdentity(identity);
7944 }
7945 return TelephonyManager.CALL_COMPOSER_STATUS_OFF;
7946 }
7947
7948 @Override
Jeff Sharkey85190e62014-12-05 09:40:12 -08007949 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
7950 String number) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08007951 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
Jeff Davidson7e17e312018-02-13 18:17:36 -08007952 subId, "setLine1NumberForDisplayForSubscriber");
Derek Tan97ebb422014-09-05 16:55:38 -07007953
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007954 final long identity = Binder.clearCallingIdentity();
7955 try {
7956 final String iccId = getIccId(subId);
7957 final Phone phone = getPhone(subId);
7958 if (phone == null) {
7959 return false;
7960 }
7961 final String subscriberId = phone.getSubscriberId();
7962
7963 if (DBG_MERGE) {
Amit Mahajanb8f13202020-01-27 18:16:07 -08007964 Rlog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
Malcolm Chenaa4a8532018-02-28 15:00:40 -08007965 + subscriberId + " to " + number);
7966 }
7967
7968 if (TextUtils.isEmpty(iccId)) {
7969 return false;
7970 }
7971
7972 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
7973
7974 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
7975 if (alphaTag == null) {
7976 editor.remove(alphaTagPrefKey);
7977 } else {
7978 editor.putString(alphaTagPrefKey, alphaTag);
7979 }
7980
7981 // Record both the line number and IMSI for this ICCID, since we need to
7982 // track all merged IMSIs based on line number
7983 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
7984 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
7985 if (number == null) {
7986 editor.remove(numberPrefKey);
7987 editor.remove(subscriberPrefKey);
7988 } else {
7989 editor.putString(numberPrefKey, number);
7990 editor.putString(subscriberPrefKey, subscriberId);
7991 }
7992
7993 editor.commit();
7994 return true;
7995 } finally {
7996 Binder.restoreCallingIdentity(identity);
Sanket Padawe356d7632015-06-22 14:03:32 -07007997 }
Derek Tan7226c842014-07-02 17:42:23 -07007998 }
7999
8000 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008001 public String getLine1NumberForDisplay(int subId, String callingPackage,
8002 String callingFeatureId) {
Makoto Onukifee69342015-06-29 14:44:50 -07008003 // This is open to apps with WRITE_SMS.
Jeff Davidson7e17e312018-02-13 18:17:36 -08008004 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008005 mApp, subId, callingPackage, callingFeatureId, "getLine1NumberForDisplay")) {
Amit Mahajan9cf11512015-11-09 11:40:48 -08008006 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
Svet Ganovb320e182015-04-16 12:30:10 -07008007 return null;
8008 }
Derek Tan97ebb422014-09-05 16:55:38 -07008009
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008010 final long identity = Binder.clearCallingIdentity();
8011 try {
8012 String iccId = getIccId(subId);
8013 if (iccId != null) {
8014 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
8015 if (DBG_MERGE) {
8016 log("getLine1NumberForDisplay returning "
8017 + mTelephonySharedPreferences.getString(numberPrefKey, null));
8018 }
8019 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Amit Mahajan9cf11512015-11-09 11:40:48 -08008020 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008021 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
8022 return null;
8023 } finally {
8024 Binder.restoreCallingIdentity(identity);
Derek Tan7226c842014-07-02 17:42:23 -07008025 }
Derek Tan7226c842014-07-02 17:42:23 -07008026 }
8027
8028 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008029 public String getLine1AlphaTagForDisplay(int subId, String callingPackage,
8030 String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08008031 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008032 mApp, subId, callingPackage, callingFeatureId, "getLine1AlphaTagForDisplay")) {
Svet Ganovb320e182015-04-16 12:30:10 -07008033 return null;
8034 }
Derek Tan97ebb422014-09-05 16:55:38 -07008035
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008036 final long identity = Binder.clearCallingIdentity();
8037 try {
8038 String iccId = getIccId(subId);
8039 if (iccId != null) {
8040 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
8041 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
8042 }
8043 return null;
8044 } finally {
8045 Binder.restoreCallingIdentity(identity);
Derek Tan7226c842014-07-02 17:42:23 -07008046 }
Derek Tan7226c842014-07-02 17:42:23 -07008047 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07008048
8049 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008050 public String[] getMergedSubscriberIds(int subId, String callingPackage,
8051 String callingFeatureId) {
Jeff Davidson913390f2018-02-23 17:11:49 -08008052 // This API isn't public, so no need to provide a valid subscription ID - we're not worried
8053 // about carrier-privileged callers not having access.
Jeff Davidson7e17e312018-02-13 18:17:36 -08008054 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Jeff Davidson913390f2018-02-23 17:11:49 -08008055 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008056 callingFeatureId, "getMergedSubscriberIds")) {
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008057 return null;
8058 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08008059
Jordan Liub49b04b2019-05-06 14:45:15 -07008060 // Clear calling identity, when calling TelephonyManager, because callerUid must be
8061 // the process, where TelephonyManager was instantiated.
8062 // Otherwise AppOps check will fail.
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008063 final long identity = Binder.clearCallingIdentity();
8064 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008065 final Context context = mApp;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008066 final TelephonyManager tele = TelephonyManager.from(context);
8067 final SubscriptionManager sub = SubscriptionManager.from(context);
8068
8069 // Figure out what subscribers are currently active
8070 final ArraySet<String> activeSubscriberIds = new ArraySet<>();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008071
Jordan Liub49b04b2019-05-06 14:45:15 -07008072 // Only consider subs which match the current subId
8073 // This logic can be simplified. See b/131189269 for progress.
8074 if (isActiveSubscription(subId)) {
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008075 activeSubscriberIds.add(tele.getSubscriberId(subId));
8076 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008077
8078 // First pass, find a number override for an active subscriber
8079 String mergeNumber = null;
8080 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
8081 for (String key : prefs.keySet()) {
8082 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
8083 final String subscriberId = (String) prefs.get(key);
8084 if (activeSubscriberIds.contains(subscriberId)) {
8085 final String iccId = key.substring(
8086 PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
8087 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
8088 mergeNumber = (String) prefs.get(numberKey);
8089 if (DBG_MERGE) {
Amit Mahajanb8f13202020-01-27 18:16:07 -08008090 Rlog.d(LOG_TAG, "Found line number " + mergeNumber
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008091 + " for active subscriber " + subscriberId);
8092 }
8093 if (!TextUtils.isEmpty(mergeNumber)) {
8094 break;
8095 }
8096 }
8097 }
8098 }
8099
8100 // Shortcut when no active merged subscribers
8101 if (TextUtils.isEmpty(mergeNumber)) {
8102 return null;
8103 }
8104
8105 // Second pass, find all subscribers under that line override
8106 final ArraySet<String> result = new ArraySet<>();
8107 for (String key : prefs.keySet()) {
8108 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
8109 final String number = (String) prefs.get(key);
8110 if (mergeNumber.equals(number)) {
8111 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
8112 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
8113 final String subscriberId = (String) prefs.get(subscriberKey);
8114 if (!TextUtils.isEmpty(subscriberId)) {
8115 result.add(subscriberId);
8116 }
8117 }
8118 }
8119 }
8120
8121 final String[] resultArray = result.toArray(new String[result.size()]);
8122 Arrays.sort(resultArray);
8123 if (DBG_MERGE) {
Amit Mahajanb8f13202020-01-27 18:16:07 -08008124 Rlog.d(LOG_TAG,
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008125 "Found subscribers " + Arrays.toString(resultArray) + " after merge");
8126 }
8127 return resultArray;
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07008128 } finally {
8129 Binder.restoreCallingIdentity(identity);
Jeff Sharkey85190e62014-12-05 09:40:12 -08008130 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08008131 }
8132
8133 @Override
zoey chen38003472019-12-13 17:16:31 +08008134 public String[] getMergedImsisFromGroup(int subId, String callingPackage) {
8135 enforceReadPrivilegedPermission("getMergedImsisFromGroup");
Malcolm Chen6ca97372019-07-01 16:28:21 -07008136
8137 final long identity = Binder.clearCallingIdentity();
8138 try {
8139 final TelephonyManager telephonyManager = mApp.getSystemService(
8140 TelephonyManager.class);
8141 String subscriberId = telephonyManager.getSubscriberId(subId);
8142 if (subscriberId == null) {
8143 if (DBG) {
zoey chen38003472019-12-13 17:16:31 +08008144 log("getMergedImsisFromGroup can't find subscriberId for subId "
Malcolm Chen6ca97372019-07-01 16:28:21 -07008145 + subId);
8146 }
8147 return null;
8148 }
8149
Jack Yu285100e2022-12-02 22:48:35 -08008150 ParcelUuid groupUuid;
8151 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008152 final SubscriptionInfo info = getSubscriptionManagerService()
Jack Yu285100e2022-12-02 22:48:35 -08008153 .getSubscriptionInfo(subId);
8154 groupUuid = info.getGroupUuid();
8155 } else {
8156 final SubscriptionInfo info = mSubscriptionController
8157 .getSubscriptionInfo(subId);
8158 groupUuid = info.getGroupUuid();
8159 }
Malcolm Chen6ca97372019-07-01 16:28:21 -07008160 // If it doesn't belong to any group, return just subscriberId of itself.
8161 if (groupUuid == null) {
8162 return new String[]{subscriberId};
8163 }
8164
8165 // Get all subscriberIds from the group.
8166 final List<String> mergedSubscriberIds = new ArrayList<>();
Jack Yu285100e2022-12-02 22:48:35 -08008167 List<SubscriptionInfo> groupInfos;
8168 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008169 groupInfos = getSubscriptionManagerService()
Jack Yu285100e2022-12-02 22:48:35 -08008170 .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
8171 mApp.getAttributionTag());
8172 } else {
8173 groupInfos = mSubscriptionController
8174 .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
8175 mApp.getAttributionTag());
8176 }
Malcolm Chen6ca97372019-07-01 16:28:21 -07008177 for (SubscriptionInfo subInfo : groupInfos) {
8178 subscriberId = telephonyManager.getSubscriberId(subInfo.getSubscriptionId());
8179 if (subscriberId != null) {
8180 mergedSubscriberIds.add(subscriberId);
8181 }
8182 }
8183
8184 return mergedSubscriberIds.toArray(new String[mergedSubscriberIds.size()]);
8185 } finally {
8186 Binder.restoreCallingIdentity(identity);
8187
8188 }
8189 }
8190
8191 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08008192 public boolean setOperatorBrandOverride(int subId, String brand) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08008193 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
Jeff Davidson7e17e312018-02-13 18:17:36 -08008194 subId, "setOperatorBrandOverride");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008195
8196 final long identity = Binder.clearCallingIdentity();
8197 try {
8198 final Phone phone = getPhone(subId);
8199 return phone == null ? false : phone.setOperatorBrandOverride(brand);
8200 } finally {
8201 Binder.restoreCallingIdentity(identity);
8202 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07008203 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05008204
8205 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08008206 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08008207 List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
8208 List<String> cdmaNonRoamingList) {
Shuo Qian2c0ae432019-12-05 11:40:37 -08008209 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
8210 mApp, subId, "setRoamingOverride");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008211
8212 final long identity = Binder.clearCallingIdentity();
8213 try {
8214 final Phone phone = getPhone(subId);
8215 if (phone == null) {
8216 return false;
8217 }
8218 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
8219 cdmaNonRoamingList);
8220 } finally {
8221 Binder.restoreCallingIdentity(identity);
Shishir Agrawalc04d9752016-02-19 10:41:00 -08008222 }
Shishir Agrawal621a47c2014-12-01 10:25:09 -08008223 }
8224
8225 @Override
Shuo Qian850e4d6a2018-04-25 21:02:08 +00008226 @Deprecated
8227 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
8228 enforceModifyPermission();
8229
8230 int returnValue = 0;
8231 try {
vagdeviaf9a5b92018-08-15 16:01:53 -07008232 AsyncResult result = (AsyncResult) sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
Shuo Qian850e4d6a2018-04-25 21:02:08 +00008233 if(result.exception == null) {
8234 if (result.result != null) {
8235 byte[] responseData = (byte[])(result.result);
8236 if(responseData.length > oemResp.length) {
8237 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
8238 responseData.length + "bytes. Buffer Size is " +
8239 oemResp.length + "bytes.");
8240 }
8241 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
8242 returnValue = responseData.length;
8243 }
8244 } else {
8245 CommandException ex = (CommandException) result.exception;
8246 returnValue = ex.getCommandError().ordinal();
8247 if(returnValue > 0) returnValue *= -1;
8248 }
8249 } catch (RuntimeException e) {
8250 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
8251 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
8252 if(returnValue > 0) returnValue *= -1;
8253 }
8254
8255 return returnValue;
8256 }
8257
8258 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07008259 public int getRadioAccessFamily(int phoneId, String callingPackage) {
Jeff Davidson913390f2018-02-23 17:11:49 -08008260 Phone phone = PhoneFactory.getPhone(phoneId);
Shuo Qiandee53402020-05-29 14:08:15 -07008261 try {
8262 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07008263 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Shuo Qiandee53402020-05-29 14:08:15 -07008264 mApp, phone.getSubId(), "getRadioAccessFamily");
8265 } catch (SecurityException e) {
8266 EventLog.writeEvent(0x534e4554, "150857259", -1, "Missing Permission");
8267 throw e;
8268 }
chen xub97461a2018-10-26 14:17:57 -07008269 int raf = RadioAccessFamily.RAF_UNKNOWN;
Jeff Davidson913390f2018-02-23 17:11:49 -08008270 if (phone == null) {
chen xub97461a2018-10-26 14:17:57 -07008271 return raf;
Jeff Davidson913390f2018-02-23 17:11:49 -08008272 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008273 final long identity = Binder.clearCallingIdentity();
8274 try {
chen xub97461a2018-10-26 14:17:57 -07008275 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07008276 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
chen xub97461a2018-10-26 14:17:57 -07008277 mApp, phone.getSubId(), "getRadioAccessFamily");
8278 raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008279 } finally {
8280 Binder.restoreCallingIdentity(identity);
8281 }
chen xub97461a2018-10-26 14:17:57 -07008282 return raf;
Wink Saville5d475dd2014-10-17 15:00:58 -07008283 }
Andrew Leedf14ead2014-10-17 14:22:52 -07008284
8285 @Override
Hall Liu82694d52020-12-11 18:22:04 -08008286 public void uploadCallComposerPicture(int subscriptionId, String callingPackage,
Hall Liue31bac62020-12-23 19:16:10 -08008287 String contentType, ParcelFileDescriptor fd, ResultReceiver callback) {
Hall Liu82694d52020-12-11 18:22:04 -08008288 try {
8289 if (!Objects.equals(mApp.getPackageManager().getPackageUid(callingPackage, 0),
8290 Binder.getCallingUid())) {
Tyler Gunnb87925a2021-06-10 14:54:27 -07008291 throw new SecurityException("Invalid package:" + callingPackage);
Hall Liu82694d52020-12-11 18:22:04 -08008292 }
8293 } catch (PackageManager.NameNotFoundException e) {
Tyler Gunnb87925a2021-06-10 14:54:27 -07008294 throw new SecurityException("Invalid package:" + callingPackage);
Hall Liu82694d52020-12-11 18:22:04 -08008295 }
8296 RoleManager rm = mApp.getSystemService(RoleManager.class);
8297 List<String> dialerRoleHolders = rm.getRoleHolders(RoleManager.ROLE_DIALER);
8298 if (!dialerRoleHolders.contains(callingPackage)) {
8299 throw new SecurityException("App must be the dialer role holder to"
8300 + " upload a call composer pic");
8301 }
8302
8303 Executors.newSingleThreadExecutor().execute(() -> {
8304 ByteArrayOutputStream output = new ByteArrayOutputStream(
8305 (int) TelephonyManager.getMaximumCallComposerPictureSize());
8306 InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(fd);
8307 boolean readUntilEnd = false;
8308 int totalBytesRead = 0;
8309 byte[] buffer = new byte[16 * 1024];
8310 while (true) {
8311 int numRead;
8312 try {
8313 numRead = input.read(buffer);
8314 } catch (IOException e) {
8315 try {
8316 fd.checkError();
8317 callback.send(TelephonyManager.CallComposerException.ERROR_INPUT_CLOSED,
8318 null);
8319 } catch (IOException e1) {
8320 // This means that the other side closed explicitly with an error. If this
8321 // happens, log and ignore.
8322 loge("Remote end of call composer picture pipe closed: " + e1);
8323 }
8324 break;
8325 }
8326 if (numRead == -1) {
8327 readUntilEnd = true;
8328 break;
8329 }
8330 totalBytesRead += numRead;
8331 if (totalBytesRead > TelephonyManager.getMaximumCallComposerPictureSize()) {
8332 loge("Too many bytes read for call composer picture: " + totalBytesRead);
8333 try {
8334 input.close();
8335 } catch (IOException e) {
8336 // ignore
8337 }
8338 break;
8339 }
8340 output.write(buffer, 0, numRead);
8341 }
8342 // Generally, the remote end will close the file descriptors. The only case where we
8343 // close is above, where the picture size is too big.
8344
8345 try {
8346 fd.checkError();
8347 } catch (IOException e) {
8348 loge("Remote end for call composer closed with an error: " + e);
8349 return;
8350 }
8351
Hall Liuaa4211e2021-01-20 15:43:39 -08008352 if (!readUntilEnd) {
8353 loge("Did not finish reading entire image; aborting");
8354 return;
8355 }
Hall Liu82694d52020-12-11 18:22:04 -08008356
Hall Liuaa4211e2021-01-20 15:43:39 -08008357 ImageData imageData = new ImageData(output.toByteArray(), contentType, null);
8358 CallComposerPictureManager.getInstance(mApp, subscriptionId).handleUploadToServer(
8359 new CallComposerPictureTransfer.Factory() {},
8360 imageData,
8361 (result) -> {
8362 if (result.first != null) {
8363 ParcelUuid parcelUuid = new ParcelUuid(result.first);
8364 Bundle outputResult = new Bundle();
8365 outputResult.putParcelable(
8366 TelephonyManager.KEY_CALL_COMPOSER_PICTURE_HANDLE, parcelUuid);
8367 callback.send(TelephonyManager.CallComposerException.SUCCESS,
8368 outputResult);
8369 } else {
8370 callback.send(result.second, null);
8371 }
8372 }
8373 );
Hall Liu82694d52020-12-11 18:22:04 -08008374 });
8375 }
8376
8377 @Override
Andrew Leedf14ead2014-10-17 14:22:52 -07008378 public void enableVideoCalling(boolean enable) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008379 final Phone defaultPhone = getDefaultPhone();
Andrew Leedf14ead2014-10-17 14:22:52 -07008380 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008381
8382 final long identity = Binder.clearCallingIdentity();
8383 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008384 ImsManager.getInstance(defaultPhone.getContext(),
8385 defaultPhone.getPhoneId()).setVtSetting(enable);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008386 } finally {
8387 Binder.restoreCallingIdentity(identity);
8388 }
Andrew Leedf14ead2014-10-17 14:22:52 -07008389 }
8390
8391 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008392 public boolean isVideoCallingEnabled(String callingPackage, String callingFeatureId) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008393 final Phone defaultPhone = getDefaultPhone();
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008394 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, defaultPhone.getSubId(),
8395 callingPackage, callingFeatureId, "isVideoCallingEnabled")) {
Amit Mahajan578e53d2018-03-20 16:18:38 +00008396 return false;
8397 }
Svet Ganovb320e182015-04-16 12:30:10 -07008398
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008399 final long identity = Binder.clearCallingIdentity();
8400 try {
8401 // Check the user preference and the system-level IMS setting. Even if the user has
8402 // enabled video calling, if IMS is disabled we aren't able to support video calling.
8403 // In the long run, we may instead need to check if there exists a connection service
8404 // which can support video calling.
8405 ImsManager imsManager =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008406 ImsManager.getInstance(defaultPhone.getContext(), defaultPhone.getPhoneId());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008407 return imsManager.isVtEnabledByPlatform()
8408 && imsManager.isEnhanced4gLteModeSettingEnabledByUser()
8409 && imsManager.isVtEnabledByUser();
8410 } finally {
8411 Binder.restoreCallingIdentity(identity);
8412 }
Andrew Leedf14ead2014-10-17 14:22:52 -07008413 }
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06008414
Andrew Leea1239f22015-03-02 17:44:07 -08008415 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008416 public boolean canChangeDtmfToneLength(int subId, String callingPackage,
8417 String callingFeatureId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008418 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008419 mApp, subId, callingPackage, callingFeatureId,
8420 "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_DTMF_TYPE_ENABLED_BOOL);
8430 } finally {
8431 Binder.restoreCallingIdentity(identity);
8432 }
Andrew Leea1239f22015-03-02 17:44:07 -08008433 }
8434
8435 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008436 public boolean isWorldPhone(int subId, String callingPackage, String callingFeatureId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008437 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008438 mApp, subId, callingPackage, callingFeatureId, "isVideoCallingEnabled")) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008439 return false;
8440 }
8441
8442 final long identity = Binder.clearCallingIdentity();
8443 try {
8444 CarrierConfigManager configManager =
8445 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008446 return configManager.getConfigForSubId(subId)
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008447 .getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
8448 } finally {
8449 Binder.restoreCallingIdentity(identity);
8450 }
Andrew Leea1239f22015-03-02 17:44:07 -08008451 }
8452
Andrew Lee9431b832015-03-09 18:46:45 -07008453 @Override
8454 public boolean isTtyModeSupported() {
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07008455 TelecomManager telecomManager = mApp.getSystemService(TelecomManager.class);
Wooki Wu1f82f7a2016-02-15 15:59:58 +08008456 return telecomManager.isTtySupported();
Andrew Lee9431b832015-03-09 18:46:45 -07008457 }
8458
8459 @Override
8460 public boolean isHearingAidCompatibilitySupported() {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008461 final long identity = Binder.clearCallingIdentity();
8462 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008463 return mApp.getResources().getBoolean(R.bool.hac_enabled);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008464 } finally {
8465 Binder.restoreCallingIdentity(identity);
8466 }
Andrew Lee9431b832015-03-09 18:46:45 -07008467 }
8468
Hall Liuf6668912018-10-31 17:05:23 -07008469 /**
8470 * Determines whether the device currently supports RTT (Real-time text). Based both on carrier
8471 * support for the feature and device firmware support.
8472 *
8473 * @return {@code true} if the device and carrier both support RTT, {@code false} otherwise.
8474 */
8475 @Override
8476 public boolean isRttSupported(int subscriptionId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008477 final long identity = Binder.clearCallingIdentity();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008478 final Phone phone = getPhone(subscriptionId);
8479 if (phone == null) {
8480 loge("isRttSupported: no Phone found. Invalid subId:" + subscriptionId);
8481 return false;
8482 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008483 try {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008484 boolean isCarrierSupported = mApp.getCarrierConfigForSubId(subscriptionId).getBoolean(
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008485 CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
8486 boolean isDeviceSupported =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008487 phone.getContext().getResources().getBoolean(R.bool.config_support_rtt);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008488 return isCarrierSupported && isDeviceSupported;
8489 } finally {
8490 Binder.restoreCallingIdentity(identity);
8491 }
Hall Liu98187582018-01-22 19:15:32 -08008492 }
8493
Hall Liuf6668912018-10-31 17:05:23 -07008494 /**
Hall Liuf2daa022019-07-23 18:39:00 -07008495 * Determines whether the user has turned on RTT. If the carrier wants to ignore the user-set
8496 * RTT setting, will return true if the device and carrier both support RTT.
8497 * Otherwise. only returns true if the device and carrier both also support RTT.
Hall Liuf6668912018-10-31 17:05:23 -07008498 */
8499 public boolean isRttEnabled(int subscriptionId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008500 final long identity = Binder.clearCallingIdentity();
8501 try {
Hall Liu5bab75c2019-12-11 23:58:20 +00008502 boolean isRttSupported = isRttSupported(subscriptionId);
8503 boolean isUserRttSettingOn = Settings.Secure.getInt(
8504 mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
8505 boolean shouldIgnoreUserRttSetting = mApp.getCarrierConfigForSubId(subscriptionId)
8506 .getBoolean(CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL);
8507 return isRttSupported && (isUserRttSettingOn || shouldIgnoreUserRttSetting);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008508 } finally {
8509 Binder.restoreCallingIdentity(identity);
8510 }
Hall Liu3ad5f012018-04-06 16:23:39 -07008511 }
8512
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008513 @Deprecated
8514 @Override
8515 public String getDeviceId(String callingPackage) {
8516 return getDeviceIdWithFeature(callingPackage, null);
8517 }
8518
Sanket Padawe7310cc72015-01-14 09:53:20 -08008519 /**
8520 * Returns the unique device ID of phone, for example, the IMEI for
8521 * GSM and the MEID for CDMA phones. Return null if device ID is not available.
8522 *
8523 * <p>Requires Permission:
8524 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
8525 */
8526 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008527 public String getDeviceIdWithFeature(String callingPackage, String callingFeatureId) {
Shuo Qian13d89152021-05-10 23:58:11 -07008528 try {
8529 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
8530 } catch (SecurityException se) {
8531 EventLog.writeEvent(0x534e4554, "186530889", Binder.getCallingUid());
8532 throw new SecurityException("Package " + callingPackage + " does not belong to "
8533 + Binder.getCallingUid());
8534 }
Sanket Padawe7310cc72015-01-14 09:53:20 -08008535 final Phone phone = PhoneFactory.getPhone(0);
Jeff Davidson913390f2018-02-23 17:11:49 -08008536 if (phone == null) {
Sanket Padawe7310cc72015-01-14 09:53:20 -08008537 return null;
8538 }
Jeff Davidson913390f2018-02-23 17:11:49 -08008539 int subId = phone.getSubId();
Michael Groover70af6dc2018-10-01 16:23:15 -07008540 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mApp, subId,
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008541 callingPackage, callingFeatureId, "getDeviceId")) {
Jeff Davidson913390f2018-02-23 17:11:49 -08008542 return null;
8543 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008544
8545 final long identity = Binder.clearCallingIdentity();
8546 try {
8547 return phone.getDeviceId();
8548 } finally {
8549 Binder.restoreCallingIdentity(identity);
8550 }
Sanket Padawe7310cc72015-01-14 09:53:20 -08008551 }
8552
Ping Sunc67b7c22016-03-02 19:16:45 +08008553 /**
8554 * {@hide}
8555 * Returns the IMS Registration Status on a particular subid
8556 *
8557 * @param subId
8558 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008559 public boolean isImsRegistered(int subId) {
Ping Sunc67b7c22016-03-02 19:16:45 +08008560 Phone phone = getPhone(subId);
8561 if (phone != null) {
8562 return phone.isImsRegistered();
8563 } else {
8564 return false;
8565 }
8566 }
8567
Santos Cordon7a1885b2015-02-03 11:15:19 -08008568 @Override
Shuo Qian6e6137d2019-10-30 16:33:31 -07008569 public int getSubIdForPhoneAccountHandle(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008570 PhoneAccountHandle phoneAccountHandle, String callingPackage, String callingFeatureId) {
Shuo Qian6e6137d2019-10-30 16:33:31 -07008571 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, getDefaultSubscription(),
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008572 callingPackage, callingFeatureId, "getSubIdForPhoneAccountHandle")) {
Shuo Qian6e6137d2019-10-30 16:33:31 -07008573 throw new SecurityException("Requires READ_PHONE_STATE permission.");
8574 }
8575 final long identity = Binder.clearCallingIdentity();
8576 try {
8577 return PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle);
8578 } finally {
8579 Binder.restoreCallingIdentity(identity);
8580 }
8581 }
8582
8583 @Override
Tyler Gunnf70ed162019-04-03 15:28:53 -07008584 public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
Alireza Forouzan4ac4f982021-03-16 22:18:52 -07008585 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07008586 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008587 mApp,
8588 subscriptionId,
8589 "getPhoneAccountHandleForSubscriptionId, " + "subscriptionId: "
8590 + subscriptionId);
Tyler Gunnf70ed162019-04-03 15:28:53 -07008591 final long identity = Binder.clearCallingIdentity();
8592 try {
8593 Phone phone = getPhone(subscriptionId);
8594 if (phone == null) {
8595 return null;
8596 }
8597 return PhoneUtils.makePstnPhoneAccountHandle(phone);
8598 } finally {
8599 Binder.restoreCallingIdentity(identity);
8600 }
8601 }
8602
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008603 /**
8604 * @return the VoWiFi calling availability.
Nathan Haroldc55097a2015-03-11 18:14:50 -07008605 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008606 public boolean isWifiCallingAvailable(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008607 final long identity = Binder.clearCallingIdentity();
8608 try {
8609 Phone phone = getPhone(subId);
8610 if (phone != null) {
8611 return phone.isWifiCallingEnabled();
8612 } else {
8613 return false;
8614 }
8615 } finally {
8616 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008617 }
Nathan Haroldc55097a2015-03-11 18:14:50 -07008618 }
8619
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008620 /**
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008621 * @return the VT calling availability.
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07008622 */
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008623 public boolean isVideoTelephonyAvailable(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.isVideoEnabled();
8629 } else {
8630 return false;
8631 }
8632 } finally {
8633 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008634 }
8635 }
8636
8637 /**
8638 * @return the IMS registration technology for the MMTEL feature. Valid return values are
8639 * defined in {@link ImsRegistrationImplBase}.
8640 */
8641 public @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegTechnologyForMmTel(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008642 final long identity = Binder.clearCallingIdentity();
8643 try {
8644 Phone phone = getPhone(subId);
8645 if (phone != null) {
8646 return phone.getImsRegistrationTech();
8647 } else {
8648 return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
8649 }
8650 } finally {
8651 Binder.restoreCallingIdentity(identity);
Brad Ebinger1f2b5082018-02-08 16:11:32 -08008652 }
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07008653 }
8654
Stuart Scott8eef64f2015-04-08 15:13:54 -07008655 @Override
Sarah Chinecc78c42022-03-31 21:16:48 -07008656 public void factoryReset(int subId, String callingPackage) {
paulhu5a773602019-08-23 19:17:33 +08008657 enforceSettingsPermission();
Stuart Scott981d8582015-04-21 14:09:50 -07008658 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
8659 return;
8660 }
Kai Shif70f46f2021-03-03 13:59:46 -08008661 Phone defaultPhone = getDefaultPhone();
8662 if (defaultPhone != null) {
8663 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
8664 mApp, getDefaultPhone().getSubId(), "factoryReset");
8665 }
Svet Ganovcc087f82015-05-12 20:35:54 -07008666 final long identity = Binder.clearCallingIdentity();
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008667
Svet Ganovcc087f82015-05-12 20:35:54 -07008668 try {
Stuart Scott981d8582015-04-21 14:09:50 -07008669 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
8670 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07008671 setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_USER,
Sarah Chinecc78c42022-03-31 21:16:48 -07008672 getDefaultDataEnabled(), callingPackage);
Svet Ganovcc087f82015-05-12 20:35:54 -07008673 setNetworkSelectionModeAutomatic(subId);
SongFerngWang8c6e82e2021-03-02 22:09:29 +08008674 Phone phone = getPhone(subId);
SongFerngWangfd89b102021-05-27 22:44:54 +08008675 cleanUpAllowedNetworkTypes(phone, subId);
Nazanin Bakhshif782e562018-12-11 15:15:39 -08008676 setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
Jordan Liu857e73a2021-03-05 16:24:04 -08008677 getPhone(subId).resetCarrierKeysForImsiEncryption();
Svet Ganovcc087f82015-05-12 20:35:54 -07008678 }
Amit Mahajan7dbbd822019-03-13 17:33:47 -07008679 // There has been issues when Sms raw table somehow stores orphan
8680 // fragments. They lead to garbled message when new fragments come
8681 // in and combined with those stale ones. In case this happens again,
8682 // user can reset all network settings which will clean up this table.
8683 cleanUpSmsRawTable(getDefaultPhone().getContext());
Brad Ebingerbc7dd582019-10-17 17:03:22 -07008684 // Clean up IMS settings as well here.
8685 int slotId = getSlotIndex(subId);
8686 if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
8687 ImsManager.getInstance(mApp, slotId).factoryReset();
8688 }
Naina Nallurid63128d2019-09-17 14:10:30 -07008689
Kai Shif70f46f2021-03-03 13:59:46 -08008690 if (defaultPhone == null) {
8691 return;
8692 }
Naina Nallurid63128d2019-09-17 14:10:30 -07008693 // Erase modem config if erase modem on network setting is enabled.
8694 String configValue = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_TELEPHONY,
8695 RESET_NETWORK_ERASE_MODEM_CONFIG_ENABLED);
8696 if (configValue != null && Boolean.parseBoolean(configValue)) {
Kai Shif70f46f2021-03-03 13:59:46 -08008697 sendEraseModemConfig(defaultPhone);
Naina Nallurid63128d2019-09-17 14:10:30 -07008698 }
Kai Shif70f46f2021-03-03 13:59:46 -08008699
8700 sendEraseDataInSharedPreferences(defaultPhone);
Svet Ganovcc087f82015-05-12 20:35:54 -07008701 } finally {
8702 Binder.restoreCallingIdentity(identity);
Stuart Scott8eef64f2015-04-08 15:13:54 -07008703 }
8704 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01008705
SongFerngWangfd89b102021-05-27 22:44:54 +08008706 @VisibleForTesting
8707 void cleanUpAllowedNetworkTypes(Phone phone, int subId) {
8708 if (phone == null || !SubscriptionManager.isUsableSubscriptionId(subId)) {
8709 return;
8710 }
8711 long defaultNetworkType = RadioAccessFamily.getRafFromNetworkType(
8712 RILConstants.PREFERRED_NETWORK_MODE);
8713 SubscriptionManager.setSubscriptionProperty(subId,
8714 SubscriptionManager.ALLOWED_NETWORK_TYPES,
8715 "user=" + defaultNetworkType);
8716 phone.loadAllowedNetworksFromSubscriptionDatabase();
8717 phone.setAllowedNetworkTypes(TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER,
8718 defaultNetworkType, null);
8719 }
8720
Amit Mahajan7dbbd822019-03-13 17:33:47 -07008721 private void cleanUpSmsRawTable(Context context) {
8722 ContentResolver resolver = context.getContentResolver();
8723 Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
8724 resolver.delete(uri, null, null);
8725 }
8726
Narayan Kamath1c496c22015-04-16 14:40:19 +01008727 @Override
chen xu5d3637b2019-01-21 23:31:38 -08008728 public String getSimLocaleForSubscriber(int subId) {
8729 enforceReadPrivilegedPermission("getSimLocaleForSubscriber, subId: " + subId);
8730 final Phone phone = getPhone(subId);
8731 if (phone == null) {
8732 log("getSimLocaleForSubscriber, invalid subId");
chen xu2bb91e42019-01-24 14:35:54 -08008733 return null;
chen xu5d3637b2019-01-21 23:31:38 -08008734 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008735 final long identity = Binder.clearCallingIdentity();
8736 try {
Jack Yu285100e2022-12-02 22:48:35 -08008737 SubscriptionInfo info;
8738 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008739 info = getSubscriptionManagerService().getActiveSubscriptionInfo(subId,
Jack Yu285100e2022-12-02 22:48:35 -08008740 phone.getContext().getOpPackageName(),
8741 phone.getContext().getAttributionTag());
8742 if (info == null) {
8743 log("getSimLocaleForSubscriber, inactive subId: " + subId);
8744 return null;
8745 }
8746 } else {
8747 info = mSubscriptionController.getActiveSubscriptionInfo(subId,
8748 phone.getContext().getOpPackageName(),
8749 phone.getContext().getAttributionTag());
8750 if (info == null) {
8751 log("getSimLocaleForSubscriber, inactive subId: " + subId);
8752 return null;
8753 }
chen xu6291c472019-02-04 12:55:53 -08008754 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008755 // Try and fetch the locale from the carrier properties or from the SIM language
8756 // preferences (EF-PL and EF-LI)...
8757 final int mcc = info.getMcc();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008758 String simLanguage = null;
chen xu5d3637b2019-01-21 23:31:38 -08008759 final Locale localeFromDefaultSim = phone.getLocaleFromSimAndCarrierPrefs();
8760 if (localeFromDefaultSim != null) {
8761 if (!localeFromDefaultSim.getCountry().isEmpty()) {
8762 if (DBG) log("Using locale from subId: " + subId + " locale: "
8763 + localeFromDefaultSim);
tom hsu60a8dc52022-10-27 00:10:04 +08008764 return matchLocaleFromSupportedLocaleList(phone, localeFromDefaultSim);
chen xu5d3637b2019-01-21 23:31:38 -08008765 } else {
8766 simLanguage = localeFromDefaultSim.getLanguage();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008767 }
8768 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01008769
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008770 // The SIM language preferences only store a language (e.g. fr = French), not an
8771 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
8772 // the SIM and carrier preferences does not include a country we add the country
8773 // determined from the SIM MCC to provide an exact locale.
zoey chenc730df82019-12-18 17:07:20 +08008774 final Locale mccLocale = LocaleUtils.getLocaleFromMcc(mApp, mcc, simLanguage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008775 if (mccLocale != null) {
chen xu5d3637b2019-01-21 23:31:38 -08008776 if (DBG) log("No locale from SIM, using mcc locale:" + mccLocale);
tom hsu60a8dc52022-10-27 00:10:04 +08008777 return matchLocaleFromSupportedLocaleList(phone, mccLocale);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008778 }
8779
8780 if (DBG) log("No locale found - returning null");
8781 return null;
8782 } finally {
8783 Binder.restoreCallingIdentity(identity);
8784 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01008785 }
8786
tom hsu0b59d292022-09-29 23:49:21 +08008787 @VisibleForTesting
tom hsu60a8dc52022-10-27 00:10:04 +08008788 String matchLocaleFromSupportedLocaleList(Phone phone, @NonNull Locale inputLocale) {
tom hsu0b59d292022-09-29 23:49:21 +08008789 String[] supportedLocale = com.android.internal.app.LocalePicker.getSupportedLocales(
tom hsu60a8dc52022-10-27 00:10:04 +08008790 phone.getContext());
tom hsu0b59d292022-09-29 23:49:21 +08008791 for (String localeTag : supportedLocale) {
tom hsu60a8dc52022-10-27 00:10:04 +08008792 if (LocaleList.matchesLanguageAndScript(inputLocale, Locale.forLanguageTag(localeTag))
8793 && TextUtils.equals(inputLocale.getCountry(),
tom hsu0b59d292022-09-29 23:49:21 +08008794 Locale.forLanguageTag(localeTag).getCountry())) {
8795 return localeTag;
8796 }
8797 }
8798 return inputLocale.toLanguageTag();
8799 }
8800
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008801 /**
8802 * NOTE: this method assumes permission checks are done and caller identity has been cleared.
8803 */
8804 private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
Jack Yu285100e2022-12-02 22:48:35 -08008805 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08008806 return getSubscriptionManagerService().getActiveSubscriptionInfoList(
Jack Yu285100e2022-12-02 22:48:35 -08008807 mApp.getOpPackageName(), mApp.getAttributionTag());
8808 }
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008809 return mSubscriptionController.getActiveSubscriptionInfoList(mApp.getOpPackageName(),
Philip P. Moltmann8d34f0c2020-03-05 16:24:02 -08008810 mApp.getAttributionTag());
Narayan Kamath1c496c22015-04-16 14:40:19 +01008811 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008812
Gary Jian3aa9a762022-01-24 16:41:19 +08008813 private ActivityStatsTechSpecificInfo[] mLastModemActivitySpecificInfo = null;
8814 private ModemActivityInfo mLastModemActivityInfo = null;
Chenjie Yu1ba97252018-01-11 18:16:20 -08008815
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008816 /**
Adam Lesinski903a54c2016-04-11 14:49:52 -07008817 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
8818 * representing the state of the modem.
8819 *
Chenjie Yu1ba97252018-01-11 18:16:20 -08008820 * NOTE: The underlying implementation clears the modem state, so there should only ever be one
8821 * caller to it. Everyone should call this class to get cumulative data.
Adam Lesinski903a54c2016-04-11 14:49:52 -07008822 * @hide
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008823 */
8824 @Override
Adam Lesinski903a54c2016-04-11 14:49:52 -07008825 public void requestModemActivityInfo(ResultReceiver result) {
8826 enforceModifyPermission();
vagdeviaf9a5b92018-08-15 16:01:53 -07008827 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008828
8829 final long identity = Binder.clearCallingIdentity();
8830 try {
Shuo Qian8f4750a2020-02-20 17:12:10 -08008831 sendRequestAsync(CMD_GET_MODEM_ACTIVITY_INFO, result, null, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08008832 } finally {
8833 Binder.restoreCallingIdentity(identity);
Chenjie Yu1ba97252018-01-11 18:16:20 -08008834 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07008835 }
Jack Yu85bd38a2015-11-09 11:34:32 -08008836
Gary Jian76280a42022-12-07 16:18:33 +08008837 // Checks that ModemActivityInfo is valid. Sleep time and Idle time should be
Siddharth Rayb8114062018-06-17 15:02:38 -07008838 // less than total activity duration.
8839 private boolean isModemActivityInfoValid(ModemActivityInfo info) {
8840 if (info == null) {
8841 return false;
8842 }
8843 int activityDurationMs =
Hall Liu49656c02020-10-09 19:00:11 -07008844 (int) (info.getTimestampMillis() - mLastModemActivityInfo.getTimestampMillis());
Gary Jian76280a42022-12-07 16:18:33 +08008845 activityDurationMs += MODEM_ACTIVITY_TIME_OFFSET_CORRECTION_MS;
8846
Hall Liu49656c02020-10-09 19:00:11 -07008847 int totalTxTimeMs = Arrays.stream(info.getTransmitTimeMillis()).sum();
8848
Siddharth Rayb8114062018-06-17 15:02:38 -07008849 return (info.isValid()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008850 && (info.getSleepTimeMillis() <= activityDurationMs)
8851 && (info.getIdleTimeMillis() <= activityDurationMs));
Siddharth Rayb8114062018-06-17 15:02:38 -07008852 }
8853
Gary Jian3aa9a762022-01-24 16:41:19 +08008854 private void updateLastModemActivityInfo(ModemActivityInfo info, int rat, int freq) {
8855 int[] mergedTxTimeMs = new int [ModemActivityInfo.getNumTxPowerLevels()];
8856 int[] txTimeMs = info.getTransmitTimeMillis(rat, freq);
8857 int[] lastModemTxTimeMs = mLastModemActivityInfo.getTransmitTimeMillis(rat, freq);
8858
8859 for (int lvl = 0; lvl < mergedTxTimeMs.length; lvl++) {
8860 mergedTxTimeMs[lvl] = txTimeMs[lvl] + lastModemTxTimeMs[lvl];
8861 }
8862
8863 mLastModemActivityInfo.setTransmitTimeMillis(rat, freq, mergedTxTimeMs);
8864 mLastModemActivityInfo.setReceiveTimeMillis(
8865 rat,
8866 freq,
8867 info.getReceiveTimeMillis(rat, freq)
8868 + mLastModemActivityInfo.getReceiveTimeMillis(rat, freq));
8869 }
8870
8871 private void updateLastModemActivityInfo(ModemActivityInfo info, int rat) {
8872 int[] mergedTxTimeMs = new int [ModemActivityInfo.getNumTxPowerLevels()];
8873 int[] txTimeMs = info.getTransmitTimeMillis(rat);
8874 int[] lastModemTxTimeMs = mLastModemActivityInfo.getTransmitTimeMillis(rat);
8875
8876 for (int lvl = 0; lvl < mergedTxTimeMs.length; lvl++) {
8877 mergedTxTimeMs[lvl] = txTimeMs[lvl] + lastModemTxTimeMs[lvl];
8878 }
8879 mLastModemActivityInfo.setTransmitTimeMillis(rat, mergedTxTimeMs);
8880 mLastModemActivityInfo.setReceiveTimeMillis(
8881 rat,
8882 info.getReceiveTimeMillis(rat) + mLastModemActivityInfo.getReceiveTimeMillis(rat));
8883 }
8884
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008885 /**
8886 * Merge this ModemActivityInfo with mLastModemActivitySpecificInfo
8887 * @param info recent ModemActivityInfo
8888 */
Gary Jian3aa9a762022-01-24 16:41:19 +08008889 private void mergeModemActivityInfo(ModemActivityInfo info) {
8890 List<ActivityStatsTechSpecificInfo> merged = new ArrayList<>();
Kai Shi917fdc62022-11-28 14:01:02 -08008891 ActivityStatsTechSpecificInfo deltaSpecificInfo;
Gary Jian3aa9a762022-01-24 16:41:19 +08008892 boolean matched;
8893 for (int i = 0; i < info.getSpecificInfoLength(); i++) {
8894 matched = false;
8895 int rat = info.getSpecificInfoRat(i);
8896 int freq = info.getSpecificInfoFrequencyRange(i);
8897 //Check each ActivityStatsTechSpecificInfo in this ModemActivityInfo for new rat returns
8898 //Add a new ActivityStatsTechSpecificInfo if is a new rat, and merge with the original
8899 //if it already exists
8900 for (int j = 0; j < mLastModemActivitySpecificInfo.length; j++) {
8901 if (rat == mLastModemActivityInfo.getSpecificInfoRat(j) && !matched) {
8902 //Merged based on frequency range (MMWAVE vs SUB6) for 5G
8903 if (rat == AccessNetworkConstants.AccessNetworkType.NGRAN) {
8904 if (freq == mLastModemActivityInfo.getSpecificInfoFrequencyRange(j)) {
8905 updateLastModemActivityInfo(info, rat, freq);
8906 matched = true;
8907 }
8908 } else {
8909 updateLastModemActivityInfo(info, rat);
8910 matched = true;
8911 }
8912 }
8913 }
8914
8915 if (!matched) {
Kai Shi917fdc62022-11-28 14:01:02 -08008916 deltaSpecificInfo =
Gary Jian3aa9a762022-01-24 16:41:19 +08008917 new ActivityStatsTechSpecificInfo(
8918 rat,
8919 freq,
8920 info.getTransmitTimeMillis(rat, freq),
8921 (int) info.getReceiveTimeMillis(rat, freq));
Kai Shi917fdc62022-11-28 14:01:02 -08008922 merged.addAll(Arrays.asList(deltaSpecificInfo));
Gary Jian3aa9a762022-01-24 16:41:19 +08008923 }
8924 }
8925 merged.addAll(Arrays.asList(mLastModemActivitySpecificInfo));
8926 mLastModemActivitySpecificInfo =
8927 new ActivityStatsTechSpecificInfo[merged.size()];
8928 merged.toArray(mLastModemActivitySpecificInfo);
8929
8930 mLastModemActivityInfo.setTimestamp(info.getTimestampMillis());
8931 mLastModemActivityInfo.setSleepTimeMillis(
8932 info.getSleepTimeMillis()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008933 + mLastModemActivityInfo.getSleepTimeMillis());
Gary Jian3aa9a762022-01-24 16:41:19 +08008934 mLastModemActivityInfo.setIdleTimeMillis(
8935 info.getIdleTimeMillis()
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008936 + mLastModemActivityInfo.getIdleTimeMillis());
Kai Shi917fdc62022-11-28 14:01:02 -08008937
8938 mLastModemActivityInfo =
Thomas Nguyen8ee49682023-02-01 11:46:09 -08008939 new ModemActivityInfo(
8940 mLastModemActivityInfo.getTimestampMillis(),
8941 mLastModemActivityInfo.getSleepTimeMillis(),
8942 mLastModemActivityInfo.getIdleTimeMillis(),
8943 mLastModemActivitySpecificInfo);
Kai Shi917fdc62022-11-28 14:01:02 -08008944 }
8945
8946 private ActivityStatsTechSpecificInfo[] deepCopyModemActivitySpecificInfo(
8947 ActivityStatsTechSpecificInfo[] info) {
8948 int infoSize = info.length;
8949 ActivityStatsTechSpecificInfo[] ret = new ActivityStatsTechSpecificInfo[infoSize];
8950 for (int i = 0; i < infoSize; i++) {
8951 ret[i] = new ActivityStatsTechSpecificInfo(
8952 info[i].getRat(), info[i].getFrequencyRange(),
8953 info[i].getTransmitTimeMillis(),
8954 (int) info[i].getReceiveTimeMillis());
8955 }
8956 return ret;
Gary Jian3aa9a762022-01-24 16:41:19 +08008957 }
8958
Jack Yu85bd38a2015-11-09 11:34:32 -08008959 /**
Jack Yu85bd38a2015-11-09 11:34:32 -08008960 * Returns the service state information on specified subscription.
8961 */
8962 @Override
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08008963 public ServiceState getServiceStateForSubscriber(int subId,
8964 boolean renounceFineLocationAccess, boolean renounceCoarseLocationAccess,
8965 String callingPackage, String callingFeatureId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08008966 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07008967 mApp, subId, callingPackage, callingFeatureId, "getServiceStateForSubscriber")) {
Jack Yu85bd38a2015-11-09 11:34:32 -08008968 return null;
8969 }
8970
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08008971 boolean hasFinePermission = false;
8972 boolean hasCoarsePermission = false;
8973 if (!renounceFineLocationAccess) {
8974 LocationAccessPolicy.LocationPermissionResult fineLocationResult =
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 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
8984 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
8985 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
8986 .build());
8987 hasFinePermission =
8988 fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
8989 }
Hall Liuf19c44f2018-11-27 14:38:17 -08008990
Sooraj Sasindran2250dc02021-11-10 16:42:01 -08008991 if (!renounceCoarseLocationAccess) {
8992 LocationAccessPolicy.LocationPermissionResult coarseLocationResult =
8993 LocationAccessPolicy.checkLocationPermission(mApp,
8994 new LocationAccessPolicy.LocationPermissionQuery.Builder()
8995 .setCallingPackage(callingPackage)
8996 .setCallingFeatureId(callingFeatureId)
8997 .setCallingPid(Binder.getCallingPid())
8998 .setCallingUid(Binder.getCallingUid())
8999 .setMethod("getServiceStateForSubscriber")
9000 .setLogAsInfo(true)
9001 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
9002 .setMinSdkVersionForFine(Integer.MAX_VALUE)
9003 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
9004 .build());
9005 hasCoarsePermission =
9006 coarseLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
9007 }
Hall Liuf19c44f2018-11-27 14:38:17 -08009008
Jack Yu479f40e2020-10-27 21:29:25 -07009009 final Phone phone = getPhone(subId);
9010 if (phone == null) {
9011 return null;
9012 }
9013
Jordan Liu0f2bc442020-11-18 16:47:37 -08009014 final long identity = Binder.clearCallingIdentity();
9015
Jack Yu479f40e2020-10-27 21:29:25 -07009016 boolean isCallingPackageDataService = phone.getDataServicePackages()
9017 .contains(callingPackage);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009018 try {
Jordan Liuc437b192020-08-17 10:59:12 -07009019 // isActiveSubId requires READ_PHONE_STATE, which we already check for above
Jack Yu285100e2022-12-02 22:48:35 -08009020 if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
Jack Yufa8ed012023-02-11 15:42:28 -08009021 SubscriptionInfoInternal subInfo = getSubscriptionManagerService()
Jack Yu285100e2022-12-02 22:48:35 -08009022 .getSubscriptionInfoInternal(subId);
9023 if (subInfo == null || !subInfo.isActive()) {
9024 Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
9025 + "subId=" + subId);
9026 return null;
9027 }
9028 } else {
9029 if (!mSubscriptionController.isActiveSubId(subId, callingPackage,
9030 callingFeatureId)) {
9031 Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
9032 + "subId=" + subId);
9033 return null;
9034 }
Jordan Liuc437b192020-08-17 10:59:12 -07009035 }
9036
Hall Liuf19c44f2018-11-27 14:38:17 -08009037 ServiceState ss = phone.getServiceState();
9038
9039 // Scrub out the location info in ServiceState depending on what level of access
9040 // the caller has.
Jack Yu479f40e2020-10-27 21:29:25 -07009041 if (hasFinePermission || isCallingPackageDataService) return ss;
Malcolm Chen5052de62019-12-30 13:56:38 -08009042 if (hasCoarsePermission) return ss.createLocationInfoSanitizedCopy(false);
9043 return ss.createLocationInfoSanitizedCopy(true);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009044 } finally {
9045 Binder.restoreCallingIdentity(identity);
9046 }
Jack Yu85bd38a2015-11-09 11:34:32 -08009047 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009048
9049 /**
9050 * Returns the URI for the per-account voicemail ringtone set in Phone settings.
9051 *
9052 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
9053 * voicemail ringtone.
9054 * @return The URI for the ringtone to play when receiving a voicemail from a specific
9055 * PhoneAccount.
9056 */
9057 @Override
9058 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009059 final long identity = Binder.clearCallingIdentity();
9060 try {
9061 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
9062 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009063 phone = getDefaultPhone();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009064 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009065
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009066 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone.getContext());
9067 } finally {
9068 Binder.restoreCallingIdentity(identity);
9069 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009070 }
9071
9072 /**
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009073 * Sets the per-account voicemail ringtone.
9074 *
9075 * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
9076 * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
9077 *
9078 * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
9079 * voicemail ringtone.
9080 * @param uri The URI for the ringtone to play when receiving a voicemail from a specific
9081 * PhoneAccount.
9082 */
9083 @Override
9084 public void setVoicemailRingtoneUri(String callingPackage,
9085 PhoneAccountHandle phoneAccountHandle, Uri uri) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009086 final Phone defaultPhone = getDefaultPhone();
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009087 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07009088 TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
9089 if (!TextUtils.equals(callingPackage, tm.getDefaultDialerPackage())) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009090 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9091 mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
9092 "setVoicemailRingtoneUri");
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009093 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009094
9095 final long identity = Binder.clearCallingIdentity();
9096 try {
9097 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
9098 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009099 phone = defaultPhone;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009100 }
9101 VoicemailNotificationSettingsUtil.setRingtoneUri(phone.getContext(), uri);
9102 } finally {
9103 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009104 }
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009105 }
9106
9107 /**
Nancy Chen31f9ba12016-01-06 11:42:12 -08009108 * Returns whether vibration is set for voicemail notification in Phone settings.
9109 *
9110 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
9111 * voicemail vibration setting.
9112 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
9113 */
9114 @Override
9115 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009116 final long identity = Binder.clearCallingIdentity();
9117 try {
9118 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
9119 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009120 phone = getDefaultPhone();
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009121 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009122
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009123 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone.getContext());
9124 } finally {
9125 Binder.restoreCallingIdentity(identity);
9126 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08009127 }
9128
Youhan Wange64578a2016-05-02 15:32:42 -07009129 /**
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009130 * Sets the per-account voicemail vibration.
9131 *
9132 * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
9133 * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
9134 *
9135 * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
9136 * voicemail vibration setting.
9137 * @param enabled Whether to enable or disable vibration for voicemail notifications from a
9138 * specific PhoneAccount.
9139 */
9140 @Override
9141 public void setVoicemailVibrationEnabled(String callingPackage,
9142 PhoneAccountHandle phoneAccountHandle, boolean enabled) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009143 final Phone defaultPhone = getDefaultPhone();
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009144 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Tyler Gunn5ddfdc92019-10-31 13:08:23 -07009145 TelecomManager tm = defaultPhone.getContext().getSystemService(TelecomManager.class);
9146 if (!TextUtils.equals(callingPackage, tm.getDefaultDialerPackage())) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009147 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9148 mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
9149 "setVoicemailVibrationEnabled");
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009150 }
9151
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009152 final long identity = Binder.clearCallingIdentity();
9153 try {
9154 Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
9155 if (phone == null) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009156 phone = defaultPhone;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009157 }
9158 VoicemailNotificationSettingsUtil.setVibrationEnabled(phone.getContext(), enabled);
9159 } finally {
9160 Binder.restoreCallingIdentity(identity);
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009161 }
Ta-wei Yenc33877d2017-01-23 18:11:21 -08009162 }
9163
9164 /**
Youhan Wange64578a2016-05-02 15:32:42 -07009165 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
9166 *
9167 * @throws SecurityException if the caller does not have the required permission
9168 */
arunvoddud7401012022-12-15 16:08:12 +00009169 @VisibleForTesting
9170 public void enforceReadPrivilegedPermission(String message) {
Youhan Wange64578a2016-05-02 15:32:42 -07009171 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
Brad Ebinger35c841c2018-10-01 10:40:55 -07009172 message);
Youhan Wange64578a2016-05-02 15:32:42 -07009173 }
9174
9175 /**
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009176 * Make sure either called from same process as self (phone) or IPC caller has send SMS
9177 * permission.
9178 *
9179 * @throws SecurityException if the caller does not have the required permission
9180 */
9181 private void enforceSendSmsPermission() {
9182 mApp.enforceCallingOrSelfPermission(permission.SEND_SMS, null);
9183 }
9184
9185 /**
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +00009186 * Make sure either called from same process as self (phone) or IPC caller has interact across
9187 * users permission.
9188 *
9189 * @throws SecurityException if the caller does not have the required permission
9190 */
9191 private void enforceInteractAcrossUsersPermission(String message) {
9192 mApp.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, message);
9193 }
9194
9195 /**
Ta-wei Yen527a9c02017-01-06 15:29:25 -08009196 * Make sure called from the package in charge of visual voicemail.
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009197 *
Ta-wei Yen527a9c02017-01-06 15:29:25 -08009198 * @throws SecurityException if the caller is not the visual voicemail package.
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009199 */
Ta-wei Yen527a9c02017-01-06 15:29:25 -08009200 private void enforceVisualVoicemailPackage(String callingPackage, int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009201 final long identity = Binder.clearCallingIdentity();
9202 try {
9203 ComponentName componentName =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009204 RemoteVvmTaskManager.getRemotePackage(mApp, subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009205 if (componentName == null) {
9206 throw new SecurityException(
9207 "Caller not current active visual voicemail package[null]");
9208 }
9209 String vvmPackage = componentName.getPackageName();
9210 if (!callingPackage.equals(vvmPackage)) {
Hui Wang7f657552022-08-16 16:58:25 +00009211 throw new SecurityException("Caller not current active visual voicemail package");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009212 }
9213 } finally {
9214 Binder.restoreCallingIdentity(identity);
Ta-wei Yen30a69c82016-12-27 14:52:32 -08009215 }
9216 }
9217
9218 /**
Youhan Wange64578a2016-05-02 15:32:42 -07009219 * Return the application ID for the app type.
9220 *
9221 * @param subId the subscription ID that this request applies to.
9222 * @param appType the uicc app type.
9223 * @return Application ID for specificied app type, or null if no uicc.
9224 */
9225 @Override
9226 public String getAidForAppType(int subId, int appType) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009227 enforceReadPrivilegedPermission("getAidForAppType");
Youhan Wange64578a2016-05-02 15:32:42 -07009228 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009229
9230 final long identity = Binder.clearCallingIdentity();
Youhan Wange64578a2016-05-02 15:32:42 -07009231 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009232 if (phone == null) {
9233 return null;
9234 }
9235 String aid = null;
9236 try {
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00009237 aid = UiccController.getInstance().getUiccPort(phone.getPhoneId())
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009238 .getApplicationByType(appType).getAid();
9239 } catch (Exception e) {
9240 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
9241 }
9242 return aid;
9243 } finally {
9244 Binder.restoreCallingIdentity(identity);
Youhan Wange64578a2016-05-02 15:32:42 -07009245 }
Youhan Wange64578a2016-05-02 15:32:42 -07009246 }
9247
Youhan Wang4001d252016-05-11 10:29:41 -07009248 /**
9249 * Return the Electronic Serial Number.
9250 *
9251 * @param subId the subscription ID that this request applies to.
9252 * @return ESN or null if error.
9253 */
9254 @Override
9255 public String getEsn(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009256 enforceReadPrivilegedPermission("getEsn");
Youhan Wang4001d252016-05-11 10:29:41 -07009257 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009258
9259 final long identity = Binder.clearCallingIdentity();
Youhan Wang4001d252016-05-11 10:29:41 -07009260 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009261 if (phone == null) {
9262 return null;
9263 }
9264 String esn = null;
9265 try {
9266 esn = phone.getEsn();
9267 } catch (Exception e) {
9268 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
9269 }
9270 return esn;
9271 } finally {
9272 Binder.restoreCallingIdentity(identity);
Youhan Wang4001d252016-05-11 10:29:41 -07009273 }
Youhan Wang4001d252016-05-11 10:29:41 -07009274 }
9275
Sanket Padawe99ef1e32016-05-18 16:12:33 -07009276 /**
Youhan Wang66ad5d72016-07-18 17:56:58 -07009277 * Return the Preferred Roaming List Version.
9278 *
9279 * @param subId the subscription ID that this request applies to.
9280 * @return PRLVersion or null if error.
9281 */
9282 @Override
9283 public String getCdmaPrlVersion(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009284 enforceReadPrivilegedPermission("getCdmaPrlVersion");
Youhan Wang66ad5d72016-07-18 17:56:58 -07009285 Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009286
9287 final long identity = Binder.clearCallingIdentity();
Youhan Wang66ad5d72016-07-18 17:56:58 -07009288 try {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009289 if (phone == null) {
9290 return null;
9291 }
9292 String cdmaPrlVersion = null;
9293 try {
9294 cdmaPrlVersion = phone.getCdmaPrlVersion();
9295 } catch (Exception e) {
9296 Log.e(LOG_TAG, "Not getting PRLVersion", e);
9297 }
9298 return cdmaPrlVersion;
9299 } finally {
9300 Binder.restoreCallingIdentity(identity);
Youhan Wang66ad5d72016-07-18 17:56:58 -07009301 }
Youhan Wang66ad5d72016-07-18 17:56:58 -07009302 }
9303
9304 /**
Sanket Padawe99ef1e32016-05-18 16:12:33 -07009305 * Get snapshot of Telephony histograms
9306 * @return List of Telephony histograms
9307 * @hide
9308 */
9309 @Override
9310 public List<TelephonyHistogram> getTelephonyHistograms() {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009311 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9312 mApp, getDefaultSubscription(), "getTelephonyHistograms");
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009313
9314 final long identity = Binder.clearCallingIdentity();
9315 try {
9316 return RIL.getTelephonyRILTimingHistograms();
9317 } finally {
9318 Binder.restoreCallingIdentity(identity);
9319 }
Sanket Padawe99ef1e32016-05-18 16:12:33 -07009320 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07009321
9322 /**
9323 * {@hide}
Michele Berionne482f8202018-11-27 18:57:59 -08009324 * Set the allowed carrier list and the excluded carrier list, indicating the priority between
9325 * the two lists.
Meng Wang1a7c35a2016-05-05 20:56:15 -07009326 * Require system privileges. In the future we may add this to carrier APIs.
9327 *
Michele Berionne482f8202018-11-27 18:57:59 -08009328 * @return Integer with the result of the operation, as defined in {@link TelephonyManager}.
Meng Wang1a7c35a2016-05-05 20:56:15 -07009329 */
9330 @Override
Michele Berionne482f8202018-11-27 18:57:59 -08009331 @TelephonyManager.SetCarrierRestrictionResult
9332 public int setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules) {
Meng Wang1a7c35a2016-05-05 20:56:15 -07009333 enforceModifyPermission();
vagdeviaf9a5b92018-08-15 16:01:53 -07009334 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009335
Michele Berionne482f8202018-11-27 18:57:59 -08009336 if (carrierRestrictionRules == null) {
9337 throw new NullPointerException("carrier restriction cannot be null");
Meng Wang9b7c4e92017-02-17 11:41:27 -08009338 }
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009339
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009340 final long identity = Binder.clearCallingIdentity();
9341 try {
Michele Berionne482f8202018-11-27 18:57:59 -08009342 return (int) sendRequest(CMD_SET_ALLOWED_CARRIERS, carrierRestrictionRules,
vagdeviaf9a5b92018-08-15 16:01:53 -07009343 workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009344 } finally {
9345 Binder.restoreCallingIdentity(identity);
9346 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07009347 }
9348
9349 /**
9350 * {@hide}
Michele Berionne482f8202018-11-27 18:57:59 -08009351 * Get the allowed carrier list and the excluded carrier list, including the priority between
9352 * the two lists.
Meng Wang1a7c35a2016-05-05 20:56:15 -07009353 * Require system privileges. In the future we may add this to carrier APIs.
9354 *
Michele Berionne482f8202018-11-27 18:57:59 -08009355 * @return {@link android.telephony.CarrierRestrictionRules}
Meng Wang1a7c35a2016-05-05 20:56:15 -07009356 */
9357 @Override
Michele Berionne482f8202018-11-27 18:57:59 -08009358 public CarrierRestrictionRules getAllowedCarriers() {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009359 enforceReadPrivilegedPermission("getAllowedCarriers");
vagdeviaf9a5b92018-08-15 16:01:53 -07009360 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009361
9362 final long identity = Binder.clearCallingIdentity();
9363 try {
Michele Berionne482f8202018-11-27 18:57:59 -08009364 Object response = sendRequest(CMD_GET_ALLOWED_CARRIERS, null, workSource);
9365 if (response instanceof CarrierRestrictionRules) {
9366 return (CarrierRestrictionRules) response;
9367 }
9368 // Response is an Exception of some kind,
9369 // which is signalled to the user as a NULL retval
9370 return null;
9371 } catch (Exception e) {
9372 Log.e(LOG_TAG, "getAllowedCarriers. Exception ex=" + e);
9373 return null;
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009374 } finally {
9375 Binder.restoreCallingIdentity(identity);
9376 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07009377 }
9378
fionaxu59545b42016-05-25 15:53:37 -07009379 /**
arunvoddud7401012022-12-15 16:08:12 +00009380 * Fetches the carrier restriction status of the device and sends the status to the caller
9381 * through the callback.
9382 *
9383 * @param callback The callback that will be used to send the result.
9384 * @throws SecurityException if the caller does not have the required permission/privileges or
9385 * the caller is not allowlisted.
9386 */
9387 @Override
9388 public void getCarrierRestrictionStatus(IIntegerConsumer callback, String packageName) {
9389 enforceReadPermission("getCarrierRestrictionStatus");
9390 int carrierId = validateCallerAndGetCarrierId(packageName);
9391 if (carrierId == CarrierAllowListInfo.INVALID_CARRIER_ID) {
9392 Rlog.e(LOG_TAG, "getCarrierRestrictionStatus: caller is not registered");
9393 throw new SecurityException("Not an authorized caller");
9394 }
9395 final long identity = Binder.clearCallingIdentity();
9396 try {
9397 Consumer<Integer> consumer = FunctionalUtils.ignoreRemoteException(callback::accept);
9398 CallerCallbackInfo callbackInfo = new CallerCallbackInfo(consumer, carrierId);
9399 sendRequestAsync(CMD_GET_ALLOWED_CARRIERS, callbackInfo);
9400 } finally {
9401 Binder.restoreCallingIdentity(identity);
9402 }
9403 }
9404
9405 @VisibleForTesting
9406 public int validateCallerAndGetCarrierId(String packageName) {
9407 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mApp);
9408 return allowListInfo.validateCallerAndGetCarrierId(packageName);
9409 }
9410
9411 /**
fionaxu59545b42016-05-25 15:53:37 -07009412 * Action set from carrier signalling broadcast receivers to enable/disable radio
9413 * @param subId the subscription ID that this action applies to.
9414 * @param enabled control enable or disable radio.
9415 * {@hide}
9416 */
9417 @Override
9418 public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
9419 enforceModifyPermission();
9420 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009421
9422 final long identity = Binder.clearCallingIdentity();
fionaxu59545b42016-05-25 15:53:37 -07009423 if (phone == null) {
9424 loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
9425 return;
9426 }
9427 try {
9428 phone.carrierActionSetRadioEnabled(enabled);
9429 } catch (Exception e) {
9430 Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009431 } finally {
9432 Binder.restoreCallingIdentity(identity);
fionaxu59545b42016-05-25 15:53:37 -07009433 }
9434 }
9435
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07009436 /**
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07009437 * Enable or disable Voice over NR (VoNR)
9438 * @param subId the subscription ID that this action applies to.
9439 * @param enabled enable or disable VoNR.
9440 * @return operation result.
9441 */
9442 @Override
9443 public int setVoNrEnabled(int subId, boolean enabled) {
9444 enforceModifyPermission();
9445 final Phone phone = getPhone(subId);
9446
9447 final long identity = Binder.clearCallingIdentity();
9448 if (phone == null) {
9449 loge("setVoNrEnabled fails with no phone object for subId: " + subId);
9450 return TelephonyManager.ENABLE_VONR_RADIO_NOT_AVAILABLE;
9451 }
9452
9453 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9454 try {
9455 int result = (int) sendRequest(CMD_ENABLE_VONR, enabled, subId,
9456 workSource);
9457 if (DBG) log("setVoNrEnabled result: " + result);
Gary Jian8dd305f2021-10-14 16:31:35 +08009458
9459 if (result == TelephonyManager.ENABLE_VONR_SUCCESS) {
9460 if (DBG) {
9461 log("Set VoNR settings in siminfo db; subId=" + subId + ", value:" + enabled);
9462 }
9463 SubscriptionManager.setSubscriptionProperty(
9464 subId, SubscriptionManager.NR_ADVANCED_CALLING_ENABLED,
9465 (enabled ? "1" : "0"));
9466 }
9467
Sooraj Sasindrandaf060f2021-06-15 14:52:55 -07009468 return result;
9469 } finally {
9470 Binder.restoreCallingIdentity(identity);
9471 }
9472 }
9473
9474 /**
9475 * Is voice over NR enabled
9476 * @return true if VoNR is enabled else false
9477 */
9478 @Override
9479 public boolean isVoNrEnabled(int subId) {
9480 enforceReadPrivilegedPermission("isVoNrEnabled");
9481 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9482 final long identity = Binder.clearCallingIdentity();
9483 try {
9484 boolean isEnabled = (boolean) sendRequest(CMD_IS_VONR_ENABLED,
9485 null, subId, workSource);
9486 if (DBG) log("isVoNrEnabled: " + isEnabled);
9487 return isEnabled;
9488 } finally {
9489 Binder.restoreCallingIdentity(identity);
9490 }
9491 }
9492
9493 /**
fionaxu8da9cb12017-05-23 15:02:46 -07009494 * Action set from carrier signalling broadcast receivers to start/stop reporting the default
9495 * network status based on which carrier apps could apply actions accordingly,
9496 * enable/disable default url handler for example.
9497 *
9498 * @param subId the subscription ID that this action applies to.
9499 * @param report control start/stop reporting the default network status.
9500 * {@hide}
9501 */
9502 @Override
9503 public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
9504 enforceModifyPermission();
9505 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009506
9507 final long identity = Binder.clearCallingIdentity();
fionaxu8da9cb12017-05-23 15:02:46 -07009508 if (phone == null) {
9509 loge("carrierAction: ReportDefaultNetworkStatus fails with invalid sibId: " + subId);
9510 return;
9511 }
9512 try {
9513 phone.carrierActionReportDefaultNetworkStatus(report);
9514 } catch (Exception e) {
9515 Log.e(LOG_TAG, "carrierAction: ReportDefaultNetworkStatus fails. Exception ex=" + e);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009516 } finally {
9517 Binder.restoreCallingIdentity(identity);
fionaxu8da9cb12017-05-23 15:02:46 -07009518 }
9519 }
9520
9521 /**
fionaxud9622282017-07-17 17:51:30 -07009522 * Action set from carrier signalling broadcast receivers to reset all carrier actions
9523 * @param subId the subscription ID that this action applies to.
9524 * {@hide}
9525 */
9526 @Override
9527 public void carrierActionResetAll(int subId) {
9528 enforceModifyPermission();
9529 final Phone phone = getPhone(subId);
9530 if (phone == null) {
9531 loge("carrierAction: ResetAll fails with invalid sibId: " + subId);
9532 return;
9533 }
9534 try {
9535 phone.carrierActionResetAll();
9536 } catch (Exception e) {
9537 Log.e(LOG_TAG, "carrierAction: ResetAll fails. Exception ex=" + e);
9538 }
9539 }
9540
9541 /**
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07009542 * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
9543 * bug report is being generated.
9544 */
9545 @Override
Ta-wei Yen99282e02016-06-21 18:19:35 -07009546 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009547 if (mApp.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
9548 != PackageManager.PERMISSION_GRANTED) {
dcashman22b950d2016-06-27 11:39:02 -07009549 writer.println("Permission Denial: can't dump Phone from pid="
9550 + Binder.getCallingPid()
9551 + ", uid=" + Binder.getCallingUid()
9552 + "without permission "
9553 + android.Manifest.permission.DUMP);
9554 return;
9555 }
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009556 DumpsysHandler.dump(mApp, fd, writer, args);
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07009557 }
Jack Yueb89b242016-06-22 13:27:47 -07009558
Brad Ebingerdac2f002018-04-03 15:17:52 -07009559 @Override
Hall Liua1548bd2019-12-24 14:14:12 -08009560 public int handleShellCommand(@NonNull ParcelFileDescriptor in,
9561 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
9562 @NonNull String[] args) {
9563 return new TelephonyShellCommand(this, getDefaultPhone().getContext()).exec(
9564 this, in.getFileDescriptor(), out.getFileDescriptor(),
Thomas Nguyen8ee49682023-02-01 11:46:09 -08009565 err.getFileDescriptor(), args);
Brad Ebingerdac2f002018-04-03 15:17:52 -07009566 }
9567
Jack Yueb89b242016-06-22 13:27:47 -07009568 /**
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009569 * Policy control of data connection with reason {@@TelephonyManager.DataEnabledReason}
Greg Kaiser17f41752020-05-05 16:47:47 +00009570 * @param subId Subscription index
Sarah Chinecc78c42022-03-31 21:16:48 -07009571 * @param reason The reason the data enable change is taking place.
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009572 * @param enabled True if enabling the data, otherwise disabling.
Sarah Chinecc78c42022-03-31 21:16:48 -07009573 * @param callingPackage The package that changed the data enabled state.
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009574 * @hide
Jack Yu75ab2952016-07-08 14:29:33 -07009575 */
9576 @Override
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07009577 public void setDataEnabledForReason(int subId, @TelephonyManager.DataEnabledReason int reason,
Sarah Chinecc78c42022-03-31 21:16:48 -07009578 boolean enabled, String callingPackage) {
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009579 if (reason == TelephonyManager.DATA_ENABLED_REASON_USER
9580 || reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
9581 try {
9582 TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
Sooraj Sasindran95c07a92020-07-15 01:35:24 -07009583 mApp, subId, "setDataEnabledForReason");
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009584 } catch (SecurityException se) {
9585 enforceModifyPermission();
9586 }
9587 } else {
9588 enforceModifyPermission();
9589 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009590
9591 final long identity = Binder.clearCallingIdentity();
9592 try {
9593 Phone phone = getPhone(subId);
9594 if (phone != null) {
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009595 if (reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
9596 phone.carrierActionSetMeteredApnsEnabled(enabled);
9597 } else {
Jack Yu7968c6d2022-07-31 00:43:21 -07009598 phone.getDataSettingsManager().setDataEnabled(
9599 reason, enabled, callingPackage);
Sooraj Sasindranaf1b5132020-05-05 21:06:20 +00009600 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009601 }
9602 } finally {
9603 Binder.restoreCallingIdentity(identity);
Jack Yu75ab2952016-07-08 14:29:33 -07009604 }
9605 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009606
9607 /**
9608 * Get Client request stats
9609 * @return List of Client Request Stats
9610 * @hide
9611 */
9612 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009613 public List<ClientRequestStats> getClientRequestStats(String callingPackage,
9614 String callingFeatureId, int subId) {
Jeff Davidson7e17e312018-02-13 18:17:36 -08009615 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009616 mApp, subId, callingPackage, callingFeatureId, "getClientRequestStats")) {
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009617 return null;
9618 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009619 Phone phone = getPhone(subId);
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009620
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009621 final long identity = Binder.clearCallingIdentity();
9622 try {
9623 if (phone != null) {
9624 return phone.getClientRequestStats();
9625 }
9626
9627 return null;
9628 } finally {
9629 Binder.restoreCallingIdentity(identity);
9630 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009631 }
9632
Narayan Kamathf04b5a12018-01-09 11:47:15 +00009633 private WorkSource getWorkSource(int uid) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009634 String packageName = mApp.getPackageManager().getNameForUid(uid);
Hunter Knepshieldd03383b2022-03-29 22:47:54 +00009635 if (uid == Process.ROOT_UID && packageName == null) {
9636 // Downstream WorkSource attribution inside the RIL requires both a UID and package name
9637 // to be set for wakelock tracking, otherwise RIL requests fail with a runtime
9638 // exception. ROOT_UID seems not to have a valid package name returned by
9639 // PackageManager, so just fake it here to avoid issues when running telephony shell
9640 // commands that plumb through the RIL as root, like so:
9641 // $ adb root
9642 // $ adb shell cmd phone ...
9643 packageName = "root";
9644 }
Narayan Kamathf04b5a12018-01-09 11:47:15 +00009645 return new WorkSource(uid, packageName);
Sooraj Sasindran9a909312016-07-18 11:57:25 -07009646 }
Jack Yueb4124c2017-02-16 15:32:43 -08009647
9648 /**
Grace Chen70990072017-03-24 17:21:30 -07009649 * Set SIM card power state.
Jack Yueb4124c2017-02-16 15:32:43 -08009650 *
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009651 * @param slotIndex SIM slot id.
Grace Chen70990072017-03-24 17:21:30 -07009652 * @param state State of SIM (power down, power up, pass through)
9653 * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
9654 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
9655 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
Jack Yueb4124c2017-02-16 15:32:43 -08009656 *
9657 **/
9658 @Override
Grace Chen70990072017-03-24 17:21:30 -07009659 public void setSimPowerStateForSlot(int slotIndex, int state) {
Jack Yueb4124c2017-02-16 15:32:43 -08009660 enforceModifyPermission();
Sanket Padawe13bac7b2017-03-20 15:04:47 -07009661 Phone phone = PhoneFactory.getPhone(slotIndex);
9662
vagdeviaf9a5b92018-08-15 16:01:53 -07009663 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9664
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009665 final long identity = Binder.clearCallingIdentity();
9666 try {
9667 if (phone != null) {
Jordan Liu109698e2020-11-24 14:50:34 -08009668 phone.setSimPowerState(state, null, workSource);
9669 }
9670 } finally {
9671 Binder.restoreCallingIdentity(identity);
9672 }
9673 }
9674
9675 /**
9676 * Set SIM card power state.
9677 *
9678 * @param slotIndex SIM slot id.
9679 * @param state State of SIM (power down, power up, pass through)
9680 * @param callback callback to trigger after success or failure
9681 * - {@link android.telephony.TelephonyManager#CARD_POWER_DOWN}
9682 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP}
9683 * - {@link android.telephony.TelephonyManager#CARD_POWER_UP_PASS_THROUGH}
9684 *
9685 **/
9686 @Override
9687 public void setSimPowerStateForSlotWithCallback(int slotIndex, int state,
9688 IIntegerConsumer callback) {
9689 enforceModifyPermission();
9690 Phone phone = PhoneFactory.getPhone(slotIndex);
9691
9692 WorkSource workSource = getWorkSource(Binder.getCallingUid());
9693
9694 final long identity = Binder.clearCallingIdentity();
9695 try {
9696 if (phone != null) {
9697 Pair<Integer, IIntegerConsumer> arguments = Pair.create(state, callback);
9698 sendRequestAsync(CMD_SET_SIM_POWER, arguments, phone, workSource);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009699 }
9700 } finally {
9701 Binder.restoreCallingIdentity(identity);
Jack Yueb4124c2017-02-16 15:32:43 -08009702 }
9703 }
Shuo Qiandd210312017-04-12 22:11:33 +00009704
Tyler Gunn65d45c22017-06-05 11:22:26 -07009705 private boolean isUssdApiAllowed(int subId) {
9706 CarrierConfigManager configManager =
Nazanin Bakhshif782e562018-12-11 15:15:39 -08009707 (CarrierConfigManager) mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Tyler Gunn65d45c22017-06-05 11:22:26 -07009708 if (configManager == null) {
9709 return false;
9710 }
9711 PersistableBundle pb = configManager.getConfigForSubId(subId);
9712 if (pb == null) {
9713 return false;
9714 }
9715 return pb.getBoolean(
9716 CarrierConfigManager.KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL);
9717 }
9718
Shuo Qiandd210312017-04-12 22:11:33 +00009719 /**
9720 * Check if phone is in emergency callback mode
9721 * @return true if phone is in emergency callback mode
9722 * @param subId sub id
9723 */
goneil9c5f4872017-12-05 14:07:56 -08009724 @Override
Shuo Qiandd210312017-04-12 22:11:33 +00009725 public boolean getEmergencyCallbackMode(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -07009726 enforceReadPrivilegedPermission("getEmergencyCallbackMode");
Shuo Qiandd210312017-04-12 22:11:33 +00009727 final Phone phone = getPhone(subId);
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009728
9729 final long identity = Binder.clearCallingIdentity();
9730 try {
9731 if (phone != null) {
9732 return phone.isInEcm();
9733 } else {
9734 return false;
9735 }
9736 } finally {
9737 Binder.restoreCallingIdentity(identity);
Shuo Qiandd210312017-04-12 22:11:33 +00009738 }
9739 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08009740
9741 /**
9742 * Get the current signal strength information for the given subscription.
9743 * Because this information is not updated when the device is in a low power state
9744 * it should not be relied-upon to be current.
9745 * @param subId Subscription index
9746 * @return the most recent cached signal strength info from the modem
9747 */
9748 @Override
9749 public SignalStrength getSignalStrength(int subId) {
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009750 final long identity = Binder.clearCallingIdentity();
9751 try {
9752 Phone p = getPhone(subId);
9753 if (p == null) {
9754 return null;
9755 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08009756
Malcolm Chenaa4a8532018-02-28 15:00:40 -08009757 return p.getSignalStrength();
9758 } finally {
9759 Binder.restoreCallingIdentity(identity);
9760 }
Nathan Harold46b42aa2017-03-10 19:38:22 -08009761 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00009762
Pengquan Meng77b7f132018-08-22 14:49:57 -07009763 /**
Chen Xuf792fd62018-10-17 17:54:36 +00009764 * Get the current modem radio state for the given slot.
9765 * @param slotIndex slot index.
9766 * @param callingPackage the name of the package making the call.
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009767 * @param callingFeatureId The feature in the package.
Chen Xuf792fd62018-10-17 17:54:36 +00009768 * @return the current radio power state from the modem
9769 */
9770 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009771 public int getRadioPowerState(int slotIndex, String callingPackage, String callingFeatureId) {
Chen Xuf792fd62018-10-17 17:54:36 +00009772 Phone phone = PhoneFactory.getPhone(slotIndex);
9773 if (phone != null) {
Philip P. Moltmann700a9592019-10-03 11:53:50 -07009774 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, phone.getSubId(),
9775 callingPackage, callingFeatureId, "getRadioPowerState")) {
Chen Xuf792fd62018-10-17 17:54:36 +00009776 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
9777 }
9778
9779 final long identity = Binder.clearCallingIdentity();
9780 try {
9781 return phone.getRadioPowerState();
9782 } finally {
9783 Binder.restoreCallingIdentity(identity);
9784 }
9785 }
9786 return TelephonyManager.RADIO_POWER_UNAVAILABLE;
9787 }
9788
9789 /**
Pengquan Meng77b7f132018-08-22 14:49:57 -07009790 * Checks if data roaming is enabled on the subscription with id {@code subId}.
9791 *
9792 * <p>Requires one of the following permissions:
9793 * {@link android.Manifest.permission#ACCESS_NETWORK_STATE},
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009794 * {@link android.Manifest.permission#READ_BASIC_PHONE_STATE},
Pengquan Meng77b7f132018-08-22 14:49:57 -07009795 * {@link android.Manifest.permission#READ_PHONE_STATE} or that the calling app has carrier
9796 * privileges.
9797 *
9798 * @param subId subscription id
9799 * @return {@code true} if data roaming is enabled on this subscription, otherwise return
9800 * {@code false}.
9801 */
9802 @Override
9803 public boolean isDataRoamingEnabled(int subId) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009804 String functionName = "isDataRoamingEnabled";
Shuo Qian093013d2020-08-13 15:42:55 -07009805 try {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009806 try {
9807 mApp.enforceCallingOrSelfPermission(
9808 android.Manifest.permission.ACCESS_NETWORK_STATE,
9809 functionName);
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07009810 } catch (SecurityException e) {
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009811 mApp.enforceCallingOrSelfPermission(
9812 permission.READ_BASIC_PHONE_STATE, functionName);
9813 }
Sooraj Sasindran12545cc2022-08-22 14:30:25 -07009814 } catch (SecurityException e) {
Nathan Harold62c68512021-04-06 11:26:02 -07009815 TelephonyPermissions.enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
Sooraj Sasindran5d051bf2021-11-05 13:14:15 -07009816 mApp, subId, functionName);
Shuo Qian093013d2020-08-13 15:42:55 -07009817 }
Pengquan Meng44e66f12019-04-01 10:48:20 -07009818
Pengquan Menga1bb6272018-09-06 09:59:22 -07009819 boolean isEnabled = false;
9820 final long identity = Binder.clearCallingIdentity();
Pengquan Meng77b7f132018-08-22 14:49:57 -07009821 try {
Pengquan Menga1bb6272018-09-06 09:59:22 -07009822 Phone phone = getPhone(subId);
9823 isEnabled = phone != null ? phone.getDataRoamingEnabled() : false;
Pengquan Menga1bb6272018-09-06 09:59:22 -07009824 } finally {
9825 Binder.restoreCallingIdentity(identity);
Pengquan Meng77b7f132018-08-22 14:49:57 -07009826 }
Pengquan Menga1bb6272018-09-06 09:59:22 -07009827 return isEnabled;
Pengquan Meng77b7f132018-08-22 14:49:57 -07009828 }
9829
9830
9831 /**
9832 * Enables/Disables the data roaming on the subscription with id {@code subId}.
9833 *
9834 * <p> Requires permission:
9835 * {@link android.Manifest.permission#MODIFY_PHONE_STATE} or that the calling app has carrier
9836 * privileges.
9837 *
9838 * @param subId subscription id
9839 * @param isEnabled {@code true} means enable, {@code false} means disable.
9840 */
9841 @Override
9842 public void setDataRoamingEnabled(int subId, boolean isEnabled) {
Pengquan Meng44e66f12019-04-01 10:48:20 -07009843 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
9844 mApp, subId, "setDataRoamingEnabled");
9845
Pengquan Menga1bb6272018-09-06 09:59:22 -07009846 final long identity = Binder.clearCallingIdentity();
9847 try {
Pengquan Menga1bb6272018-09-06 09:59:22 -07009848 Phone phone = getPhone(subId);
9849 if (phone != null) {
9850 phone.setDataRoamingEnabled(isEnabled);
9851 }
9852 } finally {
9853 Binder.restoreCallingIdentity(identity);
Pengquan Meng77b7f132018-08-22 14:49:57 -07009854 }
9855 }
9856
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00009857 @Override
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009858 public boolean isManualNetworkSelectionAllowed(int subId) {
tom hsuc91afc72020-01-06 23:46:07 +08009859 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -07009860 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Thomas Nguyen8ee49682023-02-01 11:46:09 -08009861 mApp, subId, "isManualNetworkSelectionAllowed");
Pengquan Meng44e66f12019-04-01 10:48:20 -07009862
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009863 boolean isAllowed = true;
9864 final long identity = Binder.clearCallingIdentity();
9865 try {
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009866 Phone phone = getPhone(subId);
9867 if (phone != null) {
9868 isAllowed = phone.isCspPlmnEnabled();
9869 }
9870 } finally {
9871 Binder.restoreCallingIdentity(identity);
9872 }
9873 return isAllowed;
9874 }
9875
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009876 private boolean haveCarrierPrivilegeAccess(UiccPort port, String callingPackage) {
9877 UiccProfile profile = port.getUiccProfile();
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08009878 if (profile == null) {
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009879 return false;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00009880 }
Hunter Knepshieldcad7f0b2021-12-13 15:08:35 -08009881 Phone phone = PhoneFactory.getPhone(profile.getPhoneId());
9882 if (phone == null) {
9883 return false;
9884 }
9885 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
9886 return cpt != null && cpt.getCarrierPrivilegeStatusForPackage(callingPackage)
9887 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +00009888 }
9889
Pengquan Meng6884a2c2018-10-03 12:19:13 -07009890 @Override
Jordan Liu75f43ea2019-01-17 16:56:37 -08009891 public List<UiccCardInfo> getUiccCardsInfo(String callingPackage) {
sandeepjsa208e3b2021-11-17 04:05:58 +00009892 // Verify that the callingPackage belongs to the calling UID
Jordan Liu4cda4552020-03-23 11:55:07 -07009893 mApp.getSystemService(AppOpsManager.class)
9894 .checkPackage(Binder.getCallingUid(), callingPackage);
9895
Jordan Liu1e142fc2019-04-22 15:10:43 -07009896 boolean hasReadPermission = false;
sandeepjsb6c87872021-09-27 15:34:44 +00009897 boolean isIccIdAccessRestricted = false;
Jordan Liuc65bc952019-02-12 17:54:02 -08009898 try {
9899 enforceReadPrivilegedPermission("getUiccCardsInfo");
Jordan Liu1e142fc2019-04-22 15:10:43 -07009900 hasReadPermission = true;
Jordan Liuc65bc952019-02-12 17:54:02 -08009901 } catch (SecurityException e) {
9902 // even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
9903 // has carrier privileges on an active UICC
Rambo Wange7209ce2022-02-23 13:41:02 -08009904 if (checkCarrierPrivilegesForPackageAnyPhoneWithPermission(callingPackage)
Thomas Nguyen8ee49682023-02-01 11:46:09 -08009905 != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Jordan Liu1e142fc2019-04-22 15:10:43 -07009906 throw new SecurityException("Caller does not have permission.");
Jordan Liuc65bc952019-02-12 17:54:02 -08009907 }
Jordan Liu75f43ea2019-01-17 16:56:37 -08009908 }
sandeepjsb6c87872021-09-27 15:34:44 +00009909 // checking compatibility, if calling app's target SDK is T and beyond.
9910 if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
9911 Binder.getCallingUid())) {
9912 isIccIdAccessRestricted = true;
9913 }
Jordan Liu5aa07002018-12-18 15:44:48 -08009914 final long identity = Binder.clearCallingIdentity();
9915 try {
Jordan Liu75f43ea2019-01-17 16:56:37 -08009916 UiccController uiccController = UiccController.getInstance();
9917 ArrayList<UiccCardInfo> cardInfos = uiccController.getAllUiccCardInfos();
Jordan Liu1e142fc2019-04-22 15:10:43 -07009918 if (hasReadPermission) {
9919 return cardInfos;
Jordan Liu75f43ea2019-01-17 16:56:37 -08009920 }
Jordan Liu1e142fc2019-04-22 15:10:43 -07009921
9922 // Remove private info if the caller doesn't have access
9923 ArrayList<UiccCardInfo> filteredInfos = new ArrayList<>();
9924 for (UiccCardInfo cardInfo : cardInfos) {
sandeepjsb6c87872021-09-27 15:34:44 +00009925 //setting the value after compatibility check
9926 cardInfo.setIccIdAccessRestricted(isIccIdAccessRestricted);
Jordan Liu1e142fc2019-04-22 15:10:43 -07009927 // For an inactive eUICC, the UiccCard will be null even though the UiccCardInfo
9928 // is available
sandeepjsb6c87872021-09-27 15:34:44 +00009929 UiccCard card = uiccController.getUiccCardForSlot(cardInfo.getPhysicalSlotIndex());
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009930 if (card == null) {
9931 // assume no access if the card is unavailable
sandeepjsb6c87872021-09-27 15:34:44 +00009932 filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
Jordan Liu1e142fc2019-04-22 15:10:43 -07009933 continue;
9934 }
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009935 Collection<UiccPortInfo> portInfos = cardInfo.getPorts();
9936 if (portInfos.isEmpty()) {
sandeepjsb6c87872021-09-27 15:34:44 +00009937 filteredInfos.add(getUiccCardInfoUnPrivileged(cardInfo));
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009938 continue;
Jordan Liu1e142fc2019-04-22 15:10:43 -07009939 }
Muralidhar Reddyeb809e32021-11-19 03:07:54 +00009940 List<UiccPortInfo> uiccPortInfos = new ArrayList<>();
9941 for (UiccPortInfo portInfo : portInfos) {
9942 UiccPort port = uiccController.getUiccPortForSlot(
9943 cardInfo.getPhysicalSlotIndex(), portInfo.getPortIndex());
9944 if (port == null) {
9945 // assume no access if port is null
9946 uiccPortInfos.add(getUiccPortInfoUnPrivileged(portInfo));
9947 continue;
9948 }
9949 if (haveCarrierPrivilegeAccess(port, callingPackage)) {
9950 uiccPortInfos.add(portInfo);
9951 } else {
9952 uiccPortInfos.add(getUiccPortInfoUnPrivileged(portInfo));
9953 }
9954 }
9955 filteredInfos.add(new UiccCardInfo(
9956 cardInfo.isEuicc(),
9957 cardInfo.getCardId(),
9958 null,
9959 cardInfo.getPhysicalSlotIndex(),
9960 cardInfo.isRemovable(),
9961 cardInfo.isMultipleEnabledProfilesSupported(),
9962 uiccPortInfos));
Jordan Liu1e142fc2019-04-22 15:10:43 -07009963 }
9964 return filteredInfos;
Jordan Liu5aa07002018-12-18 15:44:48 -08009965 } finally {
9966 Binder.restoreCallingIdentity(identity);
9967 }
9968 }
9969
sandeepjsb6c87872021-09-27 15:34:44 +00009970 /**
9971 * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
9972 * generally private and require carrier privileges to view.
9973 *
9974 * @hide
9975 */
9976 @NonNull
9977 public UiccCardInfo getUiccCardInfoUnPrivileged(UiccCardInfo cardInfo) {
9978 List<UiccPortInfo> portinfo = new ArrayList<>();
9979 for (UiccPortInfo portinfos : cardInfo.getPorts()) {
9980 portinfo.add(getUiccPortInfoUnPrivileged(portinfos));
9981 }
9982 return new UiccCardInfo(
9983 cardInfo.isEuicc(),
9984 cardInfo.getCardId(),
9985 null,
9986 cardInfo.getPhysicalSlotIndex(),
9987 cardInfo.isRemovable(),
9988 cardInfo.isMultipleEnabledProfilesSupported(),
9989 portinfo
9990 );
9991 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +00009992
sandeepjsb6c87872021-09-27 15:34:44 +00009993 /**
9994 * @hide
9995 * @return a copy of the UiccPortInfo with ICCID set to {@link UiccPortInfo#ICCID_REDACTED}.
9996 * These values are generally private and require carrier privileges to view.
9997 */
9998 @NonNull
9999 public UiccPortInfo getUiccPortInfoUnPrivileged(UiccPortInfo portInfo) {
10000 return new UiccPortInfo(
10001 UiccPortInfo.ICCID_REDACTED,
10002 portInfo.getPortIndex(),
10003 portInfo.getLogicalSlotIndex(),
10004 portInfo.isActive()
10005 );
10006 }
10007 @Override
10008 public UiccSlotInfo[] getUiccSlotsInfo(String callingPackage) {
sandeepjsa208e3b2021-11-17 04:05:58 +000010009 // Verify that the callingPackage belongs to the calling UID
sandeepjsb6c87872021-09-27 15:34:44 +000010010 mApp.getSystemService(AppOpsManager.class)
10011 .checkPackage(Binder.getCallingUid(), callingPackage);
10012
sandeepjsb6c87872021-09-27 15:34:44 +000010013 boolean isLogicalSlotAccessRestricted = false;
sandeepjsb6c87872021-09-27 15:34:44 +000010014
Aman Guptaf3c90b32022-03-17 04:54:16 +000010015 // This will make sure caller has the READ_PRIVILEGED_PHONE_STATE. Do not remove this as
10016 // we are reading iccId which is PII data.
10017 enforceReadPrivilegedPermission("getUiccSlotsInfo");
sandeepjsb6c87872021-09-27 15:34:44 +000010018
10019 // checking compatibility, if calling app's target SDK is T and beyond.
10020 if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
10021 Binder.getCallingUid())) {
10022 isLogicalSlotAccessRestricted = true;
10023 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010024 final long identity = Binder.clearCallingIdentity();
10025 try {
10026 UiccSlot[] slots = UiccController.getInstance().getUiccSlots();
Muralidhar Reddyd196bbf2022-01-17 17:56:30 +000010027 if (slots == null || slots.length == 0) {
10028 Rlog.i(LOG_TAG, "slots is null or empty.");
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010029 return null;
10030 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010031 UiccSlotInfo[] infos = new UiccSlotInfo[slots.length];
10032 for (int i = 0; i < slots.length; i++) {
10033 UiccSlot slot = slots[i];
10034 if (slot == null) {
10035 continue;
10036 }
10037
Jordan Liu7be7e652019-05-06 18:55:02 +000010038 String cardId;
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010039 UiccCard card = slot.getUiccCard();
10040 if (card != null) {
10041 cardId = card.getCardId();
Jordan Liu7be7e652019-05-06 18:55:02 +000010042 } else {
Jordan Liu01bd00d2019-09-12 16:19:43 -070010043 cardId = slot.getEid();
10044 if (TextUtils.isEmpty(cardId)) {
Aman Guptaf3c90b32022-03-17 04:54:16 +000010045 // If cardId is null, use iccId of default port as cardId.
10046 cardId = slot.getIccId(TelephonyManager.DEFAULT_PORT_INDEX);
Jordan Liu01bd00d2019-09-12 16:19:43 -070010047 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010048 }
10049
Jordan Liu857451f2019-05-09 16:35:35 -070010050 if (cardId != null) {
10051 // if cardId is an ICCID, strip off trailing Fs before exposing to user
10052 // if cardId is an EID, it's all digits so this is fine
10053 cardId = IccUtils.stripTrailingFs(cardId);
10054 }
10055
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010056 int cardState = 0;
10057 switch (slot.getCardState()) {
10058 case CARDSTATE_ABSENT:
10059 cardState = UiccSlotInfo.CARD_STATE_INFO_ABSENT;
10060 break;
10061 case CARDSTATE_PRESENT:
10062 cardState = UiccSlotInfo.CARD_STATE_INFO_PRESENT;
10063 break;
10064 case CARDSTATE_ERROR:
10065 cardState = UiccSlotInfo.CARD_STATE_INFO_ERROR;
10066 break;
10067 case CARDSTATE_RESTRICTED:
10068 cardState = UiccSlotInfo.CARD_STATE_INFO_RESTRICTED;
10069 break;
10070 default:
10071 break;
10072
10073 }
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010074 List<UiccPortInfo> portInfos = new ArrayList<>();
10075 int[] portIndexes = slot.getPortList();
10076 for (int portIdx : portIndexes) {
10077 String iccId = IccUtils.stripTrailingFs(getIccId(slot, portIdx,
Aman Guptaf3c90b32022-03-17 04:54:16 +000010078 callingPackage, /* hasReadPermission= */ true));
Muralidhar Reddyfbcff0c2022-01-19 13:07:57 +000010079 portInfos.add(new UiccPortInfo(iccId, portIdx,
10080 slot.getPhoneIdFromPortIndex(portIdx), slot.isPortActive(portIdx)));
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010081 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010082 infos[i] = new UiccSlotInfo(
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010083 slot.isEuicc(),
10084 cardId,
10085 cardState,
Jordan Liua2619582019-02-14 12:56:40 -080010086 slot.isExtendedApduSupported(),
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010087 slot.isRemovable(), portInfos);
sandeepjsb6c87872021-09-27 15:34:44 +000010088 //setting the value after compatibility check
10089 infos[i].setLogicalSlotAccessRestricted(isLogicalSlotAccessRestricted);
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010090 }
10091 return infos;
10092 } finally {
10093 Binder.restoreCallingIdentity(identity);
Holly Jiuyu Sun1d957c52018-04-04 13:52:42 -070010094 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010095 }
10096
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010097 /* Returns null if doesn't have read permission or carrier privilege access. */
10098 private String getIccId(UiccSlot slot, int portIndex, String callingPackage,
10099 boolean hasReadPermission) {
10100 String iccId = slot.getIccId(portIndex);
10101 if (hasReadPermission) { // if has read permission
10102 return iccId;
10103 } else {
10104 if (slot.getUiccCard() != null && slot.getUiccCard().getUiccPort(portIndex) != null) {
10105 UiccPort port = slot.getUiccCard().getUiccPort(portIndex);
10106 // if no read permission, checking carrier privilege access
10107 if (haveCarrierPrivilegeAccess(port, callingPackage)) {
10108 return iccId;
10109 }
10110 }
10111 }
10112 // No read permission or carrier privilege access.
10113 return UiccPortInfo.ICCID_REDACTED;
10114 }
10115
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010116 @Override
sandeepjsb6c87872021-09-27 15:34:44 +000010117 @Deprecated
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010118 public boolean switchSlots(int[] physicalSlots) {
10119 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010120
10121 final long identity = Binder.clearCallingIdentity();
10122 try {
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010123 List<UiccSlotMapping> slotMappings = new ArrayList<>();
10124 for (int i = 0; i < physicalSlots.length; i++) {
10125 // Deprecated API, hence MEP is not supported. Adding default portIndex 0.
10126 slotMappings.add(new UiccSlotMapping(TelephonyManager.DEFAULT_PORT_INDEX,
10127 physicalSlots[i], i));
10128 }
10129 return (Boolean) sendRequest(CMD_SWITCH_SLOTS, slotMappings);
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010130 } finally {
10131 Binder.restoreCallingIdentity(identity);
10132 }
Holly Jiuyu Sun01c47ad2018-01-24 17:56:33 +000010133 }
Jack Yu4c988042018-02-27 15:30:01 -080010134
10135 @Override
sandeepjsb6c87872021-09-27 15:34:44 +000010136 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
10137 public boolean setSimSlotMapping(@NonNull List<UiccSlotMapping> slotMapping) {
10138 enforceModifyPermission();
10139
10140 final long identity = Binder.clearCallingIdentity();
10141 try {
Muralidhar Reddyeb809e32021-11-19 03:07:54 +000010142 return (Boolean) sendRequest(CMD_SWITCH_SLOTS, slotMapping);
sandeepjsb6c87872021-09-27 15:34:44 +000010143 } finally {
10144 Binder.restoreCallingIdentity(identity);
10145 }
10146 }
10147
10148 @Override
Jordan Liu7de49fa2018-12-06 14:48:49 -080010149 public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
Jordan Liu7de49fa2018-12-06 14:48:49 -080010150 final long identity = Binder.clearCallingIdentity();
10151 try {
10152 return UiccController.getInstance().getCardIdForDefaultEuicc();
10153 } finally {
10154 Binder.restoreCallingIdentity(identity);
10155 }
10156 }
10157
Pengquan Meng85728fb2018-03-12 16:31:21 -070010158 /**
goneil47ffb6e2018-04-06 15:40:58 -070010159 * A test API to reload the UICC profile.
10160 *
10161 * <p>Requires that the calling app has permission
10162 * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
10163 * @hide
10164 */
10165 @Override
10166 public void refreshUiccProfile(int subId) {
10167 enforceModifyPermission();
10168
10169 final long identity = Binder.clearCallingIdentity();
10170 try {
10171 Phone phone = getPhone(subId);
10172 if (phone == null) {
10173 return;
10174 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010175 UiccPort uiccPort = phone.getUiccPort();
10176 if (uiccPort == null) {
goneil47ffb6e2018-04-06 15:40:58 -070010177 return;
10178 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010179 UiccProfile uiccProfile = uiccPort.getUiccProfile();
goneil47ffb6e2018-04-06 15:40:58 -070010180 if (uiccProfile == null) {
10181 return;
10182 }
10183 uiccProfile.refresh();
10184 } finally {
10185 Binder.restoreCallingIdentity(identity);
10186 }
10187 }
10188
10189 /**
Pengquan Meng85728fb2018-03-12 16:31:21 -070010190 * Returns false if the mobile data is disabled by default, otherwise return true.
10191 */
10192 private boolean getDefaultDataEnabled() {
Inseob Kim14bb3d02018-12-13 17:11:34 +090010193 return TelephonyProperties.mobile_data().orElse(true);
Pengquan Meng85728fb2018-03-12 16:31:21 -070010194 }
10195
10196 /**
10197 * Returns true if the data roaming is enabled by default, i.e the system property
10198 * of {@link #DEFAULT_DATA_ROAMING_PROPERTY_NAME} is true or the config of
10199 * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} is true.
10200 */
10201 private boolean getDefaultDataRoamingEnabled(int subId) {
10202 final CarrierConfigManager configMgr = (CarrierConfigManager)
Nazanin Bakhshif782e562018-12-11 15:15:39 -080010203 mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Shuo Qian1d84a0e2020-07-15 12:36:44 -070010204 boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
Pengquan Meng85728fb2018-03-12 16:31:21 -070010205 isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
10206 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
10207 return isDataRoamingEnabled;
10208 }
10209
10210 /**
10211 * Returns the default network type for the given {@code subId}, if the default network type is
10212 * not set, return {@link Phone#PREFERRED_NT_MODE}.
10213 */
10214 private int getDefaultNetworkType(int subId) {
Inseob Kim14bb3d02018-12-13 17:11:34 +090010215 List<Integer> list = TelephonyProperties.default_network();
Jack Yu285100e2022-12-02 22:48:35 -080010216 int phoneId = SubscriptionManager.getPhoneId(subId);
Inseob Kim14bb3d02018-12-13 17:11:34 +090010217 if (phoneId >= 0 && phoneId < list.size() && list.get(phoneId) != null) {
10218 return list.get(phoneId);
10219 }
10220 return Phone.PREFERRED_NT_MODE;
Pengquan Meng85728fb2018-03-12 16:31:21 -070010221 }
fionaxua13278b2018-03-21 00:08:13 -070010222
10223 @Override
10224 public void setCarrierTestOverride(int subId, String mccmnc, String imsi, String iccid, String
chen xueaba88a2019-03-15 13:15:10 -070010225 gid1, String gid2, String plmn, String spn, String carrierPrivilegeRules, String apn) {
fionaxua13278b2018-03-21 00:08:13 -070010226 enforceModifyPermission();
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010227
10228 final long identity = Binder.clearCallingIdentity();
10229 try {
10230 final Phone phone = getPhone(subId);
10231 if (phone == null) {
10232 loge("setCarrierTestOverride fails with invalid subId: " + subId);
10233 return;
10234 }
Rambo Wang9c9ffdd2022-01-13 21:51:44 -080010235 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
10236 if (cpt != null) {
10237 cpt.setTestOverrideCarrierPrivilegeRules(carrierPrivilegeRules);
10238 }
10239 // TODO(b/211796398): remove the legacy logic below once CPT migration is done.
chen xueaba88a2019-03-15 13:15:10 -070010240 phone.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, plmn, spn,
10241 carrierPrivilegeRules, apn);
Jeff Davidson8ab02b22020-03-28 12:24:40 -070010242 if (carrierPrivilegeRules == null) {
10243 mCarrierPrivilegeTestOverrideSubIds.remove(subId);
10244 } else {
10245 mCarrierPrivilegeTestOverrideSubIds.add(subId);
10246 }
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010247 } finally {
10248 Binder.restoreCallingIdentity(identity);
fionaxua13278b2018-03-21 00:08:13 -070010249 }
fionaxua13278b2018-03-21 00:08:13 -070010250 }
10251
10252 @Override
10253 public int getCarrierIdListVersion(int subId) {
Brad Ebinger35c841c2018-10-01 10:40:55 -070010254 enforceReadPrivilegedPermission("getCarrierIdListVersion");
Malcolm Chenaa4a8532018-02-28 15:00:40 -080010255
10256 final long identity = Binder.clearCallingIdentity();
10257 try {
10258 final Phone phone = getPhone(subId);
10259 if (phone == null) {
10260 loge("getCarrierIdListVersion fails with invalid subId: " + subId);
10261 return TelephonyManager.UNKNOWN_CARRIER_ID_LIST_VERSION;
10262 }
10263 return phone.getCarrierIdListVersion();
10264 } finally {
10265 Binder.restoreCallingIdentity(identity);
fionaxua13278b2018-03-21 00:08:13 -070010266 }
fionaxua13278b2018-03-21 00:08:13 -070010267 }
Malcolm Chen2c63d402018-08-14 16:00:53 -070010268
10269 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010270 public int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage,
10271 String callingFeatureId) {
Malcolm Chen2c63d402018-08-14 16:00:53 -070010272 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010273 mApp, subId, callingPackage, callingFeatureId,
10274 "getNumberOfModemsWithSimultaneousDataConnections")) {
Malcolm Chen2c63d402018-08-14 16:00:53 -070010275 return -1;
10276 }
10277
10278 final long identity = Binder.clearCallingIdentity();
10279 try {
10280 return mPhoneConfigurationManager.getNumberOfModemsWithSimultaneousDataConnections();
10281 } finally {
10282 Binder.restoreCallingIdentity(identity);
10283 }
10284 }
Pengquan Menga1bb6272018-09-06 09:59:22 -070010285
10286 @Override
10287 public int getCdmaRoamingMode(int subId) {
zoey chen7e6d4e52019-12-17 18:18:59 +080010288 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010289 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Thomas Nguyen8ee49682023-02-01 11:46:09 -080010290 mApp, subId, "getCdmaRoamingMode");
Pengquan Menga1bb6272018-09-06 09:59:22 -070010291
10292 final long identity = Binder.clearCallingIdentity();
10293 try {
10294 return (int) sendRequest(CMD_GET_CDMA_ROAMING_MODE, null /* argument */, subId);
10295 } finally {
10296 Binder.restoreCallingIdentity(identity);
10297 }
10298 }
10299
10300 @Override
10301 public boolean setCdmaRoamingMode(int subId, int mode) {
10302 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
10303 mApp, subId, "setCdmaRoamingMode");
10304
10305 final long identity = Binder.clearCallingIdentity();
10306 try {
10307 return (boolean) sendRequest(CMD_SET_CDMA_ROAMING_MODE, mode, subId);
10308 } finally {
10309 Binder.restoreCallingIdentity(identity);
10310 }
10311 }
10312
10313 @Override
Sarah Chinbaab1432020-10-28 13:46:24 -070010314 public int getCdmaSubscriptionMode(int subId) {
10315 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010316 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Sarah Chinbaab1432020-10-28 13:46:24 -070010317 mApp, subId, "getCdmaSubscriptionMode");
10318
10319 final long identity = Binder.clearCallingIdentity();
10320 try {
10321 return (int) sendRequest(CMD_GET_CDMA_SUBSCRIPTION_MODE, null /* argument */, subId);
10322 } finally {
10323 Binder.restoreCallingIdentity(identity);
10324 }
10325 }
10326
10327 @Override
Pengquan Menga1bb6272018-09-06 09:59:22 -070010328 public boolean setCdmaSubscriptionMode(int subId, int mode) {
10329 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
10330 mApp, subId, "setCdmaSubscriptionMode");
10331
10332 final long identity = Binder.clearCallingIdentity();
10333 try {
10334 return (boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION_MODE, mode, subId);
10335 } finally {
10336 Binder.restoreCallingIdentity(identity);
10337 }
10338 }
Makoto Onukida3bf792018-09-18 16:06:29 -070010339
sqianc5eccab2018-10-19 18:46:41 -070010340 @Override
sqian8c685422019-02-22 15:55:18 -080010341 public Map<Integer, List<EmergencyNumber>> getEmergencyNumberList(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010342 String callingPackage, String callingFeatureId) {
sqian11b7a0e2018-12-05 18:48:28 -080010343 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010344 mApp, getDefaultSubscription(), callingPackage, callingFeatureId,
10345 "getEmergencyNumberList")) {
sqian11b7a0e2018-12-05 18:48:28 -080010346 throw new SecurityException("Requires READ_PHONE_STATE permission.");
10347 }
10348 final long identity = Binder.clearCallingIdentity();
10349 try {
sqian854d44b2018-12-12 16:48:18 -080010350 Map<Integer, List<EmergencyNumber>> emergencyNumberListInternal = new HashMap<>();
10351 for (Phone phone: PhoneFactory.getPhones()) {
10352 if (phone.getEmergencyNumberTracker() != null
10353 && phone.getEmergencyNumberTracker().getEmergencyNumberList() != null) {
10354 emergencyNumberListInternal.put(
10355 phone.getSubId(),
10356 phone.getEmergencyNumberTracker().getEmergencyNumberList());
10357 }
sqian11b7a0e2018-12-05 18:48:28 -080010358 }
sqian854d44b2018-12-12 16:48:18 -080010359 return emergencyNumberListInternal;
sqian11b7a0e2018-12-05 18:48:28 -080010360 } finally {
10361 Binder.restoreCallingIdentity(identity);
10362 }
sqianc5eccab2018-10-19 18:46:41 -070010363 }
10364
10365 @Override
sqian8c685422019-02-22 15:55:18 -080010366 public boolean isEmergencyNumber(String number, boolean exactMatch) {
Nazanin Bakhshif782e562018-12-11 15:15:39 -080010367 final Phone defaultPhone = getDefaultPhone();
sqian11b7a0e2018-12-05 18:48:28 -080010368 if (!exactMatch) {
10369 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010370 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
sqian8c685422019-02-22 15:55:18 -080010371 mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
sqian11b7a0e2018-12-05 18:48:28 -080010372 }
10373 final long identity = Binder.clearCallingIdentity();
10374 try {
sqian854d44b2018-12-12 16:48:18 -080010375 for (Phone phone: PhoneFactory.getPhones()) {
Chinmay Dhodapkard521bb12022-08-16 15:49:54 -070010376 //Note: we ignore passed in param exactMatch. We can remove it once
10377 // TelephonyManager#isPotentialEmergencyNumber is removed completely
sqian854d44b2018-12-12 16:48:18 -080010378 if (phone.getEmergencyNumberTracker() != null
Taesu Leee050c002020-10-13 17:19:35 +090010379 && phone.getEmergencyNumberTracker()
Thomas Nguyen8ee49682023-02-01 11:46:09 -080010380 .isEmergencyNumber(number)) {
Taesu Leee050c002020-10-13 17:19:35 +090010381 return true;
sqian11b7a0e2018-12-05 18:48:28 -080010382 }
sqian11b7a0e2018-12-05 18:48:28 -080010383 }
10384 return false;
10385 } finally {
10386 Binder.restoreCallingIdentity(identity);
10387 }
10388 }
10389
sqianf4ca7ed2019-01-15 18:32:07 -080010390 /**
Shuo Qianccbaf742021-02-22 18:32:21 -080010391 * Start emergency callback mode for GsmCdmaPhone for testing.
10392 */
10393 @Override
10394 public void startEmergencyCallbackMode() {
10395 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
10396 "startEmergencyCallbackMode");
10397 enforceModifyPermission();
10398 final long identity = Binder.clearCallingIdentity();
10399 try {
10400 for (Phone phone : PhoneFactory.getPhones()) {
10401 Rlog.d(LOG_TAG, "startEmergencyCallbackMode phone type: " + phone.getPhoneType());
10402 if (phone != null && ((phone.getPhoneType() == PHONE_TYPE_GSM)
10403 || (phone.getPhoneType() == PHONE_TYPE_CDMA))) {
10404 GsmCdmaPhone gsmCdmaPhone = (GsmCdmaPhone) phone;
10405 gsmCdmaPhone.obtainMessage(
10406 GsmCdmaPhone.EVENT_EMERGENCY_CALLBACK_MODE_ENTER).sendToTarget();
10407 Rlog.d(LOG_TAG, "startEmergencyCallbackMode: triggered");
10408 }
10409 }
10410 } finally {
10411 Binder.restoreCallingIdentity(identity);
10412 }
10413 }
10414
10415 /**
sqianf4ca7ed2019-01-15 18:32:07 -080010416 * Update emergency number list for test mode.
10417 */
10418 @Override
10419 public void updateEmergencyNumberListTestMode(int action, EmergencyNumber num) {
10420 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
10421 "updateEmergencyNumberListTestMode");
10422
10423 final long identity = Binder.clearCallingIdentity();
10424 try {
10425 for (Phone phone: PhoneFactory.getPhones()) {
10426 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10427 if (tracker != null) {
10428 tracker.executeEmergencyNumberTestModeCommand(action, num);
10429 }
10430 }
10431 } finally {
10432 Binder.restoreCallingIdentity(identity);
10433 }
10434 }
10435
10436 /**
10437 * Get the full emergency number list for test mode.
10438 */
10439 @Override
10440 public List<String> getEmergencyNumberListTestMode() {
10441 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
10442 "getEmergencyNumberListTestMode");
10443
10444 final long identity = Binder.clearCallingIdentity();
10445 try {
10446 Set<String> emergencyNumbers = new HashSet<>();
10447 for (Phone phone: PhoneFactory.getPhones()) {
10448 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10449 if (tracker != null) {
10450 for (EmergencyNumber num : tracker.getEmergencyNumberList()) {
10451 emergencyNumbers.add(num.getNumber());
10452 }
10453 }
10454 }
10455 return new ArrayList<>(emergencyNumbers);
10456 } finally {
10457 Binder.restoreCallingIdentity(identity);
10458 }
10459 }
10460
chen xud6b45bd2018-10-30 22:27:10 -070010461 @Override
Shuo Qian3b6ee772019-11-13 17:43:31 -080010462 public int getEmergencyNumberDbVersion(int subId) {
10463 enforceReadPrivilegedPermission("getEmergencyNumberDbVersion");
10464
10465 final long identity = Binder.clearCallingIdentity();
10466 try {
10467 final Phone phone = getPhone(subId);
10468 if (phone == null) {
10469 loge("getEmergencyNumberDbVersion fails with invalid subId: " + subId);
10470 return TelephonyManager.INVALID_EMERGENCY_NUMBER_DB_VERSION;
10471 }
10472 return phone.getEmergencyNumberDbVersion();
10473 } finally {
10474 Binder.restoreCallingIdentity(identity);
10475 }
10476 }
10477
10478 @Override
10479 public void notifyOtaEmergencyNumberDbInstalled() {
10480 enforceModifyPermission();
10481
10482 final long identity = Binder.clearCallingIdentity();
10483 try {
10484 for (Phone phone: PhoneFactory.getPhones()) {
10485 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10486 if (tracker != null) {
10487 tracker.updateOtaEmergencyNumberDatabase();
10488 }
10489 }
10490 } finally {
10491 Binder.restoreCallingIdentity(identity);
10492 }
10493 }
10494
10495 @Override
Shuo Qianc373f112020-03-05 17:55:34 -080010496 public void updateOtaEmergencyNumberDbFilePath(ParcelFileDescriptor otaParcelFileDescriptor) {
Shuo Qian3b6ee772019-11-13 17:43:31 -080010497 enforceActiveEmergencySessionPermission();
10498
10499 final long identity = Binder.clearCallingIdentity();
10500 try {
10501 for (Phone phone: PhoneFactory.getPhones()) {
10502 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10503 if (tracker != null) {
Shuo Qianc373f112020-03-05 17:55:34 -080010504 tracker.updateOtaEmergencyNumberDbFilePath(otaParcelFileDescriptor);
10505 }
10506 }
10507 } finally {
10508 Binder.restoreCallingIdentity(identity);
10509 }
10510 }
10511
10512 @Override
10513 public void resetOtaEmergencyNumberDbFilePath() {
10514 enforceActiveEmergencySessionPermission();
10515
10516 final long identity = Binder.clearCallingIdentity();
10517 try {
10518 for (Phone phone: PhoneFactory.getPhones()) {
10519 EmergencyNumberTracker tracker = phone.getEmergencyNumberTracker();
10520 if (tracker != null) {
10521 tracker.resetOtaEmergencyNumberDbFilePath();
Shuo Qian3b6ee772019-11-13 17:43:31 -080010522 }
10523 }
10524 } finally {
10525 Binder.restoreCallingIdentity(identity);
10526 }
10527 }
10528
10529 @Override
chen xud6b45bd2018-10-30 22:27:10 -070010530 public List<String> getCertsFromCarrierPrivilegeAccessRules(int subId) {
10531 enforceReadPrivilegedPermission("getCertsFromCarrierPrivilegeAccessRules");
10532 Phone phone = getPhone(subId);
10533 if (phone == null) {
10534 return null;
10535 }
10536 final long identity = Binder.clearCallingIdentity();
10537 try {
10538 UiccProfile profile = UiccController.getInstance()
10539 .getUiccProfileForPhone(phone.getPhoneId());
10540 if (profile != null) {
10541 return profile.getCertsFromCarrierPrivilegeAccessRules();
10542 }
10543 } finally {
10544 Binder.restoreCallingIdentity(identity);
10545 }
10546 return null;
10547 }
Malcolm Chen8e4ed912019-01-15 20:22:16 -080010548
10549 /**
10550 * Enable or disable a modem stack.
10551 */
10552 @Override
10553 public boolean enableModemForSlot(int slotIndex, boolean enable) {
10554 enforceModifyPermission();
10555
10556 final long identity = Binder.clearCallingIdentity();
10557 try {
10558 Phone phone = PhoneFactory.getPhone(slotIndex);
10559 if (phone == null) {
10560 return false;
10561 } else {
10562 return (Boolean) sendRequest(CMD_REQUEST_ENABLE_MODEM, enable, phone, null);
10563 }
10564 } finally {
10565 Binder.restoreCallingIdentity(identity);
10566 }
10567 }
Michelecea4cf22018-12-21 15:00:11 -080010568
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010569 /**
10570 * Whether a modem stack is enabled or not.
10571 */
10572 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010573 public boolean isModemEnabledForSlot(int slotIndex, String callingPackage,
10574 String callingFeatureId) {
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010575 Phone phone = PhoneFactory.getPhone(slotIndex);
10576 if (phone == null) return false;
10577
10578 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010579 mApp, phone.getSubId(), callingPackage, callingFeatureId,
10580 "isModemEnabledForSlot")) {
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010581 throw new SecurityException("Requires READ_PHONE_STATE permission.");
10582 }
10583
10584 final long identity = Binder.clearCallingIdentity();
10585 try {
Nazanin Bakhshif71371d2019-04-29 17:29:44 -070010586 try {
10587 return mPhoneConfigurationManager.getPhoneStatusFromCache(phone.getPhoneId());
10588 } catch (NoSuchElementException ex) {
10589 return (Boolean) sendRequest(CMD_GET_MODEM_STATUS, null, phone, null);
10590 }
Malcolm Chen4bcd9822019-03-27 18:34:05 -070010591 } finally {
10592 Binder.restoreCallingIdentity(identity);
10593 }
10594 }
10595
Michelecea4cf22018-12-21 15:00:11 -080010596 @Override
Michele0ea7d782019-03-19 14:58:42 -070010597 public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
Michelecea4cf22018-12-21 15:00:11 -080010598 enforceModifyPermission();
10599
10600 final long identity = Binder.clearCallingIdentity();
10601 try {
10602 mTelephonySharedPreferences.edit()
Michele0ea7d782019-03-19 14:58:42 -070010603 .putBoolean(PREF_MULTI_SIM_RESTRICTED, isMultiSimCarrierRestricted)
Michelecea4cf22018-12-21 15:00:11 -080010604 .commit();
10605 } finally {
10606 Binder.restoreCallingIdentity(identity);
10607 }
10608 }
10609
10610 @Override
Michele0ea7d782019-03-19 14:58:42 -070010611 @TelephonyManager.IsMultiSimSupportedResult
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010612 public int isMultiSimSupported(String callingPackage, String callingFeatureId) {
Michele4245e952019-02-04 11:36:23 -080010613 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp,
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010614 getDefaultPhone().getSubId(), callingPackage, callingFeatureId,
10615 "isMultiSimSupported")) {
Michele0ea7d782019-03-19 14:58:42 -070010616 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele4245e952019-02-04 11:36:23 -080010617 }
Michelecea4cf22018-12-21 15:00:11 -080010618
10619 final long identity = Binder.clearCallingIdentity();
10620 try {
Michele0ea7d782019-03-19 14:58:42 -070010621 return isMultiSimSupportedInternal();
Michelecea4cf22018-12-21 15:00:11 -080010622 } finally {
10623 Binder.restoreCallingIdentity(identity);
10624 }
10625 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010626
Michele0ea7d782019-03-19 14:58:42 -070010627 @TelephonyManager.IsMultiSimSupportedResult
10628 private int isMultiSimSupportedInternal() {
Michele30b57b22019-03-01 12:01:14 -080010629 // If the device has less than 2 SIM cards, indicate that multisim is restricted.
10630 int numPhysicalSlots = UiccController.getInstance().getUiccSlots().length;
10631 if (numPhysicalSlots < 2) {
Michele0ea7d782019-03-19 14:58:42 -070010632 loge("isMultiSimSupportedInternal: requires at least 2 cards");
10633 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -080010634 }
10635 // Check if the hardware supports multisim functionality. If usage of multisim is not
10636 // supported by the modem, indicate that it is restricted.
10637 PhoneCapability staticCapability =
10638 mPhoneConfigurationManager.getStaticPhoneCapability();
10639 if (staticCapability == null) {
Michele0ea7d782019-03-19 14:58:42 -070010640 loge("isMultiSimSupportedInternal: no static configuration available");
10641 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -080010642 }
SongFerngWang8236caa2021-01-17 21:51:44 +080010643 if (staticCapability.getLogicalModemList().size() < 2) {
Michele0ea7d782019-03-19 14:58:42 -070010644 loge("isMultiSimSupportedInternal: maximum number of modem is < 2");
10645 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
Michele30b57b22019-03-01 12:01:14 -080010646 }
10647 // Check if support of multiple SIMs is restricted by carrier
10648 if (mTelephonySharedPreferences.getBoolean(PREF_MULTI_SIM_RESTRICTED, false)) {
Michele0ea7d782019-03-19 14:58:42 -070010649 return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_CARRIER;
Michele30b57b22019-03-01 12:01:14 -080010650 }
10651
Michele0ea7d782019-03-19 14:58:42 -070010652 return TelephonyManager.MULTISIM_ALLOWED;
Michele30b57b22019-03-01 12:01:14 -080010653 }
10654
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010655 /**
10656 * Switch configs to enable multi-sim or switch back to single-sim
Nazanin Bakhshi17318782019-03-01 11:56:08 -080010657 * Note: Switch from multi-sim to single-sim is only possible with MODIFY_PHONE_STATE
10658 * permission, but the other way around is possible with either MODIFY_PHONE_STATE
10659 * or carrier privileges
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010660 * @param numOfSims number of active sims we want to switch to
10661 */
10662 @Override
10663 public void switchMultiSimConfig(int numOfSims) {
Nazanin Bakhshi17318782019-03-01 11:56:08 -080010664 if (numOfSims == 1) {
10665 enforceModifyPermission();
10666 } else {
10667 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
10668 mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
10669 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010670 final long identity = Binder.clearCallingIdentity();
Michele30b57b22019-03-01 12:01:14 -080010671
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010672 try {
Michele30b57b22019-03-01 12:01:14 -080010673 //only proceed if multi-sim is not restricted
Michele0ea7d782019-03-19 14:58:42 -070010674 if (isMultiSimSupportedInternal() != TelephonyManager.MULTISIM_ALLOWED) {
Michele30b57b22019-03-01 12:01:14 -080010675 loge("switchMultiSimConfig not possible. It is restricted or not supported.");
10676 return;
10677 }
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010678 mPhoneConfigurationManager.switchMultiSimConfig(numOfSims);
10679 } finally {
10680 Binder.restoreCallingIdentity(identity);
10681 }
10682 }
10683
Hyungjun Parkbb07fde2019-01-10 15:28:51 +090010684 @Override
10685 public boolean isApplicationOnUicc(int subId, int appType) {
10686 enforceReadPrivilegedPermission("isApplicationOnUicc");
10687 Phone phone = getPhone(subId);
10688 if (phone == null) {
10689 return false;
10690 }
10691 final long identity = Binder.clearCallingIdentity();
10692 try {
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010693 UiccPort uiccPort = phone.getUiccPort();
10694 if (uiccPort == null) {
Hyungjun Parkbb07fde2019-01-10 15:28:51 +090010695 return false;
10696 }
Muralidhar Reddy472c2ae2021-09-29 19:38:40 +000010697 UiccProfile uiccProfile = uiccPort.getUiccProfile();
Hyungjun Parkbb07fde2019-01-10 15:28:51 +090010698 if (uiccProfile == null) {
10699 return false;
10700 }
10701 if (TelephonyManager.APPTYPE_SIM <= appType
10702 && appType <= TelephonyManager.APPTYPE_ISIM) {
10703 return uiccProfile.isApplicationOnIcc(AppType.values()[appType]);
10704 }
10705 return false;
10706 } finally {
10707 Binder.restoreCallingIdentity(identity);
10708 }
10709 }
10710
Nazanin Bakhshi628473f2019-01-29 17:37:52 -080010711 /**
chen xub4baa772019-04-03 10:23:41 -070010712 * Get whether making changes to modem configurations will trigger reboot.
10713 * Return value defaults to true.
Nazanin Bakhshi5fe5ef22019-01-30 10:52:09 -080010714 */
10715 @Override
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010716 public boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage,
10717 String callingFeatureId) {
chen xub4baa772019-04-03 10:23:41 -070010718 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
Philip P. Moltmann700a9592019-10-03 11:53:50 -070010719 mApp, subId, callingPackage, callingFeatureId,
10720 "doesSwitchMultiSimConfigTriggerReboot")) {
chen xub4baa772019-04-03 10:23:41 -070010721 return false;
10722 }
Nazanin Bakhshi5fe5ef22019-01-30 10:52:09 -080010723 final long identity = Binder.clearCallingIdentity();
10724 try {
10725 return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
10726 } finally {
10727 Binder.restoreCallingIdentity(identity);
10728 }
10729 }
10730
Nathan Harold29f5f052019-02-15 13:41:57 -080010731 private void updateModemStateMetrics() {
10732 TelephonyMetrics metrics = TelephonyMetrics.getInstance();
10733 // TODO: check the state for each modem if the api is ready.
10734 metrics.updateEnabledModemBitmap((1 << TelephonyManager.from(mApp).getPhoneCount()) - 1);
10735 }
10736
Pengquan Meng3889a572019-01-23 11:16:29 -080010737 @Override
sandeepjsa208e3b2021-11-17 04:05:58 +000010738 public List<UiccSlotMapping> getSlotsMapping(String callingPackage) {
Pengquan Meng3889a572019-01-23 11:16:29 -080010739 enforceReadPrivilegedPermission("getSlotsMapping");
sandeepjsa208e3b2021-11-17 04:05:58 +000010740 // Verify that the callingPackage belongs to the calling UID
10741 mApp.getSystemService(AppOpsManager.class)
10742 .checkPackage(Binder.getCallingUid(), callingPackage);
Pengquan Meng3889a572019-01-23 11:16:29 -080010743 final long identity = Binder.clearCallingIdentity();
sandeepjsa208e3b2021-11-17 04:05:58 +000010744 List<UiccSlotMapping> slotMap = new ArrayList<>();
Pengquan Meng3889a572019-01-23 11:16:29 -080010745 try {
sandeepjsa208e3b2021-11-17 04:05:58 +000010746 UiccSlotInfo[] slotInfos = getUiccSlotsInfo(mApp.getOpPackageName());
10747 if (slotInfos != null) {
10748 for (int i = 0; i < slotInfos.length; i++) {
10749 for (UiccPortInfo portInfo : slotInfos[i].getPorts()) {
10750 if (SubscriptionManager.isValidPhoneId(portInfo.getLogicalSlotIndex())) {
10751 slotMap.add(new UiccSlotMapping(portInfo.getPortIndex(), i,
10752 portInfo.getLogicalSlotIndex()));
10753 }
10754 }
Pengquan Meng3889a572019-01-23 11:16:29 -080010755 }
10756 }
sandeepjsa208e3b2021-11-17 04:05:58 +000010757 return slotMap;
Pengquan Meng3889a572019-01-23 11:16:29 -080010758 } finally {
10759 Binder.restoreCallingIdentity(identity);
10760 }
10761 }
Nathan Harold48d6fd52019-02-06 19:01:40 -080010762
10763 /**
10764 * Get the IRadio HAL Version
jimsunf9ec1622022-09-13 21:18:43 +080010765 * @deprecated use getHalVersion instead
Nathan Harold48d6fd52019-02-06 19:01:40 -080010766 */
jimsunf9ec1622022-09-13 21:18:43 +080010767 @Deprecated
Nathan Harold48d6fd52019-02-06 19:01:40 -080010768 @Override
10769 public int getRadioHalVersion() {
jimsunf9ec1622022-09-13 21:18:43 +080010770 return getHalVersion(HAL_SERVICE_RADIO);
10771 }
10772
10773 /**
10774 * Get the HAL Version of a specific service
10775 */
10776 @Override
10777 public int getHalVersion(int service) {
Nathan Harold48d6fd52019-02-06 19:01:40 -080010778 Phone phone = getDefaultPhone();
10779 if (phone == null) return -1;
jimsunf9ec1622022-09-13 21:18:43 +080010780 HalVersion hv = phone.getHalVersion(service);
Nathan Harold48d6fd52019-02-06 19:01:40 -080010781 if (hv.equals(HalVersion.UNKNOWN)) return -1;
10782 return hv.major * 100 + hv.minor;
10783 }
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010784
10785 /**
Shuo Qianda2d6ec2020-01-14 15:18:28 -080010786 * Get the current calling package name.
10787 * @return the current calling package name
10788 */
10789 @Override
10790 public String getCurrentPackageName() {
10791 return mApp.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0];
10792 }
10793
10794 /**
Malcolm Chene5ad5792019-04-18 13:51:02 -070010795 * Return whether data is enabled for certain APN type. This will tell if framework will accept
10796 * corresponding network requests on a subId.
10797 *
10798 * Data is enabled if:
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010799 * 1) user data is turned on, or
Malcolm Chene5ad5792019-04-18 13:51:02 -070010800 * 2) APN is un-metered for this subscription, or
10801 * 3) APN type is whitelisted. E.g. MMS is whitelisted if
Hall Liu746e03c2020-09-25 11:13:49 -070010802 * {@link TelephonyManager#MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED} is enabled.
Malcolm Chene5ad5792019-04-18 13:51:02 -070010803 *
10804 * @return whether data is allowed for a apn type.
10805 *
10806 * @hide
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010807 */
10808 @Override
Malcolm Chene5ad5792019-04-18 13:51:02 -070010809 public boolean isDataEnabledForApn(int apnType, int subId, String callingPackage) {
Amit Mahajan5d4e1922019-10-07 16:20:43 -070010810 enforceReadPrivilegedPermission("Needs READ_PRIVILEGED_PHONE_STATE for "
10811 + "isDataEnabledForApn");
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010812
10813 // Now that all security checks passes, perform the operation as ourselves.
10814 final long identity = Binder.clearCallingIdentity();
10815 try {
10816 Phone phone = getPhone(subId);
10817 if (phone == null) return false;
10818
Jack Yu27422a52022-03-21 10:38:05 -070010819 boolean isMetered;
Jack Yu99e87332021-12-17 23:14:15 -080010820 boolean isDataEnabled;
Jack Yu7968c6d2022-07-31 00:43:21 -070010821 isMetered = phone.getDataNetworkController().getDataConfigManager()
10822 .isMeteredCapability(DataUtils.apnTypeToNetworkCapability(apnType),
10823 phone.getServiceState().getDataRoaming());
10824 isDataEnabled = phone.getDataSettingsManager().isDataEnabled(apnType);
Jack Yu99e87332021-12-17 23:14:15 -080010825 return !isMetered || isDataEnabled;
Malcolm Chene5ad5792019-04-18 13:51:02 -070010826 } finally {
10827 Binder.restoreCallingIdentity(identity);
10828 }
10829 }
10830
10831 @Override
Jack Yu41407ee2019-05-13 16:54:09 -070010832 public boolean isApnMetered(@ApnType int apnType, int subId) {
Malcolm Chene5ad5792019-04-18 13:51:02 -070010833 enforceReadPrivilegedPermission("isApnMetered");
10834
10835 // Now that all security checks passes, perform the operation as ourselves.
10836 final long identity = Binder.clearCallingIdentity();
10837 try {
10838 Phone phone = getPhone(subId);
10839 if (phone == null) return true; // By default return true.
Jack Yu7968c6d2022-07-31 00:43:21 -070010840 return phone.getDataNetworkController().getDataConfigManager().isMeteredCapability(
10841 DataUtils.apnTypeToNetworkCapability(apnType),
10842 phone.getServiceState().getDataRoaming());
Malcolm Chendc8c10e2019-04-10 18:25:07 -070010843 } finally {
10844 Binder.restoreCallingIdentity(identity);
10845 }
10846 }
Brad Ebingera63db5f2019-04-23 16:31:13 -070010847
10848 @Override
Hall Liu73f5d362020-01-20 13:42:00 -080010849 public void setSystemSelectionChannels(List<RadioAccessSpecifier> specifiers,
10850 int subscriptionId, IBooleanConsumer resultCallback) {
10851 enforceModifyPermission();
10852 long token = Binder.clearCallingIdentity();
10853 try {
10854 Phone phone = getPhone(subscriptionId);
10855 if (phone == null) {
10856 try {
10857 if (resultCallback != null) {
10858 resultCallback.accept(false);
10859 }
10860 } catch (RemoteException e) {
10861 // ignore
10862 }
10863 return;
10864 }
10865 Pair<List<RadioAccessSpecifier>, Consumer<Boolean>> argument =
10866 Pair.create(specifiers, (x) -> {
10867 try {
10868 if (resultCallback != null) {
10869 resultCallback.accept(x);
10870 }
10871 } catch (RemoteException e) {
10872 // ignore
10873 }
10874 });
10875 sendRequestAsync(CMD_SET_SYSTEM_SELECTION_CHANNELS, argument, phone, null);
10876 } finally {
10877 Binder.restoreCallingIdentity(token);
10878 }
10879 }
10880
10881 @Override
Sarah Chin679c08a2020-11-18 13:39:35 -080010882 public List<RadioAccessSpecifier> getSystemSelectionChannels(int subId) {
10883 TelephonyPermissions
Nathan Harold62c68512021-04-06 11:26:02 -070010884 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
Sarah Chin679c08a2020-11-18 13:39:35 -080010885 mApp, subId, "getSystemSelectionChannels");
10886 WorkSource workSource = getWorkSource(Binder.getCallingUid());
10887 final long identity = Binder.clearCallingIdentity();
10888 try {
Sarah Chin428d1d62021-03-13 03:17:40 -080010889 Object result = sendRequest(CMD_GET_SYSTEM_SELECTION_CHANNELS, null, subId, workSource);
10890 if (result instanceof IllegalStateException) {
10891 throw (IllegalStateException) result;
10892 }
10893 List<RadioAccessSpecifier> specifiers = (List<RadioAccessSpecifier>) result;
Sarah Chin679c08a2020-11-18 13:39:35 -080010894 if (DBG) log("getSystemSelectionChannels: " + specifiers);
10895 return specifiers;
10896 } finally {
10897 Binder.restoreCallingIdentity(identity);
10898 }
10899 }
10900
10901 @Override
Jack Yu8b766fc2022-03-21 09:42:33 -070010902 public boolean isMvnoMatched(int slotIndex, int mvnoType, @NonNull String mvnoMatchData) {
changbettyca3d40d2020-03-03 16:27:31 +080010903 enforceReadPrivilegedPermission("isMvnoMatched");
Jack Yu8b766fc2022-03-21 09:42:33 -070010904 return UiccController.getInstance().mvnoMatches(slotIndex, mvnoType, mvnoMatchData);
changbetty7157e9e2019-12-06 18:16:37 +080010905 }
10906
10907 @Override
Philip P. Moltmannd02b7372020-03-18 17:06:12 -070010908 public void enqueueSmsPickResult(String callingPackage, String callingAttributionTag,
10909 IIntegerConsumer pendingSubIdResult) {
Shuo Qianda2d6ec2020-01-14 15:18:28 -080010910 if (callingPackage == null) {
10911 callingPackage = getCurrentPackageName();
10912 }
Brad Ebingera63db5f2019-04-23 16:31:13 -070010913 SmsPermissions permissions = new SmsPermissions(getDefaultPhone(), mApp,
10914 (AppOpsManager) mApp.getSystemService(Context.APP_OPS_SERVICE));
Philip P. Moltmannd02b7372020-03-18 17:06:12 -070010915 if (!permissions.checkCallingCanSendSms(callingPackage, callingAttributionTag,
10916 "Sending message")) {
Brad Ebingera63db5f2019-04-23 16:31:13 -070010917 throw new SecurityException("Requires SEND_SMS permission to perform this operation");
10918 }
10919 PickSmsSubscriptionActivity.addPendingResult(pendingSubIdResult);
10920 Intent intent = new Intent();
10921 intent.setClass(mApp, PickSmsSubscriptionActivity.class);
10922 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
10923 // Bring up choose default SMS subscription dialog right now
10924 intent.putExtra(PickSmsSubscriptionActivity.DIALOG_TYPE_KEY,
10925 PickSmsSubscriptionActivity.SMS_PICK_FOR_MESSAGE);
10926 mApp.startActivity(intent);
10927 }
chen xud5ca2d52019-05-28 15:20:57 -070010928
10929 @Override
Ayush Sharma787854b2022-12-12 14:55:02 +000010930 public void showSwitchToManagedProfileDialog() {
10931 enforceModifyPermission();
10932
10933 Intent intent = new Intent();
10934 intent.setClass(mApp, ErrorDialogActivity.class);
10935 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
10936 mApp.startActivity(intent);
10937 }
10938
10939 @Override
chen xud5ca2d52019-05-28 15:20:57 -070010940 public String getMmsUAProfUrl(int subId) {
10941 //TODO investigate if this API should require proper permission check in R b/133791609
10942 final long identity = Binder.clearCallingIdentity();
10943 try {
Guoqiang.Qiu171383d2020-07-13 09:38:32 +080010944 String carrierUAProfUrl = mApp.getCarrierConfigForSubId(subId).getString(
10945 CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING);
10946 if (!TextUtils.isEmpty(carrierUAProfUrl)) {
10947 return carrierUAProfUrl;
10948 }
Daniel Brightebb4eb72020-02-18 15:16:33 -080010949 return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
10950 .getString(com.android.internal.R.string.config_mms_user_agent_profile_url);
chen xud5ca2d52019-05-28 15:20:57 -070010951 } finally {
10952 Binder.restoreCallingIdentity(identity);
10953 }
10954 }
10955
10956 @Override
10957 public String getMmsUserAgent(int subId) {
10958 //TODO investigate if this API should require proper permission check in R b/133791609
10959 final long identity = Binder.clearCallingIdentity();
10960 try {
Guoqiang.Qiu171383d2020-07-13 09:38:32 +080010961 String carrierUserAgent = mApp.getCarrierConfigForSubId(subId).getString(
10962 CarrierConfigManager.KEY_MMS_USER_AGENT_STRING);
10963 if (!TextUtils.isEmpty(carrierUserAgent)) {
10964 return carrierUserAgent;
10965 }
Daniel Brightebb4eb72020-02-18 15:16:33 -080010966 return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
10967 .getString(com.android.internal.R.string.config_mms_user_agent);
chen xud5ca2d52019-05-28 15:20:57 -070010968 } finally {
10969 Binder.restoreCallingIdentity(identity);
10970 }
10971 }
Jack Yub07d4972019-05-28 16:12:25 -070010972
10973 @Override
Hall Liua62f5da2020-09-25 10:42:19 -070010974 public boolean isMobileDataPolicyEnabled(int subscriptionId, int policy) {
10975 enforceReadPrivilegedPermission("isMobileDataPolicyEnabled");
Jack Yub07d4972019-05-28 16:12:25 -070010976
Jack Yub07d4972019-05-28 16:12:25 -070010977 final long identity = Binder.clearCallingIdentity();
10978 try {
Hall Liua62f5da2020-09-25 10:42:19 -070010979 Phone phone = getPhone(subscriptionId);
Jack Yub07d4972019-05-28 16:12:25 -070010980 if (phone == null) return false;
10981
Ling Maf188d502022-09-16 15:22:36 -070010982 return phone.getDataSettingsManager().isMobileDataPolicyEnabled(policy);
Jack Yub07d4972019-05-28 16:12:25 -070010983 } finally {
10984 Binder.restoreCallingIdentity(identity);
10985 }
10986 }
10987
10988 @Override
Hall Liuc66bb112021-02-02 12:09:32 -080010989 public void setMobileDataPolicyEnabled(int subscriptionId, int policy,
Hall Liua62f5da2020-09-25 10:42:19 -070010990 boolean enabled) {
changbettyd5c246e2019-12-24 15:40:37 +080010991 enforceModifyPermission();
10992
changbettyd5c246e2019-12-24 15:40:37 +080010993 final long identity = Binder.clearCallingIdentity();
10994 try {
Hall Liua62f5da2020-09-25 10:42:19 -070010995 Phone phone = getPhone(subscriptionId);
10996 if (phone == null) return;
changbettyd5c246e2019-12-24 15:40:37 +080010997
Ling Maf188d502022-09-16 15:22:36 -070010998 phone.getDataSettingsManager().setMobileDataPolicy(policy, enabled);
changbettyd5c246e2019-12-24 15:40:37 +080010999 } finally {
11000 Binder.restoreCallingIdentity(identity);
11001 }
11002 }
11003
Tyler Gunn7bcdc742019-10-04 15:56:59 -070011004 /**
Hall Liu746e03c2020-09-25 11:13:49 -070011005 * Updates whether conference event package handling is enabled.
Tyler Gunn7bcdc742019-10-04 15:56:59 -070011006 * @param isCepEnabled {@code true} if CEP handling is enabled (default), or {@code false}
11007 * otherwise.
11008 */
11009 @Override
11010 public void setCepEnabled(boolean isCepEnabled) {
11011 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCepEnabled");
11012
11013 final long identity = Binder.clearCallingIdentity();
11014 try {
11015 Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled);
11016 for (Phone phone : PhoneFactory.getPhones()) {
11017 Phone defaultPhone = phone.getImsPhone();
11018 if (defaultPhone != null && defaultPhone.getPhoneType() == PHONE_TYPE_IMS) {
11019 ImsPhone imsPhone = (ImsPhone) defaultPhone;
11020 ImsPhoneCallTracker imsPhoneCallTracker =
11021 (ImsPhoneCallTracker) imsPhone.getCallTracker();
11022 imsPhoneCallTracker.setConferenceEventPackageEnabled(isCepEnabled);
11023 Rlog.i(LOG_TAG, "setCepEnabled isCepEnabled=" + isCepEnabled + ", for imsPhone "
11024 + imsPhone.getMsisdn());
11025 }
11026 }
11027 } finally {
11028 Binder.restoreCallingIdentity(identity);
11029 }
11030 }
allenwtsu46dcc572020-01-08 18:24:03 +080011031
11032 /**
11033 * Notify that an RCS autoconfiguration XML file has been received for provisioning.
11034 *
11035 * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
11036 * @param isCompressed The XML file is compressed in gzip format and must be decompressed
11037 * before being read.
11038 */
11039 @Override
11040 public void notifyRcsAutoConfigurationReceived(int subId, @NonNull byte[] config, boolean
11041 isCompressed) {
11042 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
11043 mApp, subId, "notifyRcsAutoConfigurationReceived");
Hui Wang761a6682020-10-31 05:12:53 +000011044 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11045 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11046 }
11047 if (!isImsAvailableOnDevice()) {
joonhunshin46b49a32022-12-21 05:33:23 +000011048 // ProvisioningManager can not handle ServiceSpecificException.
11049 // Throw the IllegalStateException and annotate ProvisioningManager.
11050 throw new IllegalStateException("IMS not available on device.");
Hui Wang761a6682020-10-31 05:12:53 +000011051 }
11052
11053 final long identity = Binder.clearCallingIdentity();
allenwtsu46dcc572020-01-08 18:24:03 +080011054 try {
Hui Wang761a6682020-10-31 05:12:53 +000011055 RcsProvisioningMonitor.getInstance().updateConfig(subId, config, isCompressed);
11056 } finally {
11057 Binder.restoreCallingIdentity(identity);
allenwtsu46dcc572020-01-08 18:24:03 +080011058 }
11059 }
zoey chene02881a2019-12-30 16:11:23 +080011060
11061 @Override
11062 public boolean isIccLockEnabled(int subId) {
11063 enforceReadPrivilegedPermission("isIccLockEnabled");
11064
11065 // Now that all security checks passes, perform the operation as ourselves.
11066 final long identity = Binder.clearCallingIdentity();
11067 try {
11068 Phone phone = getPhone(subId);
11069 if (phone != null && phone.getIccCard() != null) {
11070 return phone.getIccCard().getIccLockEnabled();
11071 } else {
11072 return false;
11073 }
11074 } finally {
11075 Binder.restoreCallingIdentity(identity);
11076 }
11077 }
11078
11079 /**
11080 * Set the ICC pin lock enabled or disabled.
11081 *
11082 * @return an integer representing the status of IccLock enabled or disabled in the following
11083 * three cases:
11084 * - {@link TelephonyManager#CHANGE_ICC_LOCK_SUCCESS} if enabled or disabled IccLock
11085 * successfully.
11086 * - Positive number and zero for remaining password attempts.
11087 * - Negative number for other failure cases (such like enabling/disabling PIN failed).
11088 *
11089 */
11090 @Override
11091 public int setIccLockEnabled(int subId, boolean enabled, String password) {
11092 enforceModifyPermission();
11093
11094 Phone phone = getPhone(subId);
11095 if (phone == null) {
11096 return 0;
11097 }
11098 // Now that all security checks passes, perform the operation as ourselves.
11099 final long identity = Binder.clearCallingIdentity();
11100 try {
11101 int attemptsRemaining = (int) sendRequest(CMD_SET_ICC_LOCK_ENABLED,
11102 new Pair<Boolean, String>(enabled, password), phone, null);
11103 return attemptsRemaining;
11104
11105 } catch (Exception e) {
11106 Log.e(LOG_TAG, "setIccLockEnabled. Exception e =" + e);
11107 } finally {
11108 Binder.restoreCallingIdentity(identity);
11109 }
11110 return 0;
11111 }
11112
11113 /**
11114 * Change the ICC password used in ICC pin lock.
11115 *
11116 * @return an integer representing the status of IccLock changed in the following three cases:
11117 * - {@link TelephonyManager#CHANGE_ICC_LOCK_SUCCESS} if changed IccLock successfully.
11118 * - Positive number and zero for remaining password attempts.
11119 * - Negative number for other failure cases (such like enabling/disabling PIN failed).
11120 *
11121 */
11122 @Override
11123 public int changeIccLockPassword(int subId, String oldPassword, String newPassword) {
11124 enforceModifyPermission();
11125
11126 Phone phone = getPhone(subId);
11127 if (phone == null) {
11128 return 0;
11129 }
11130 // Now that all security checks passes, perform the operation as ourselves.
11131 final long identity = Binder.clearCallingIdentity();
11132 try {
11133 int attemptsRemaining = (int) sendRequest(CMD_CHANGE_ICC_LOCK_PASSWORD,
11134 new Pair<String, String>(oldPassword, newPassword), phone, null);
11135 return attemptsRemaining;
11136
11137 } catch (Exception e) {
11138 Log.e(LOG_TAG, "changeIccLockPassword. Exception e =" + e);
11139 } finally {
11140 Binder.restoreCallingIdentity(identity);
11141 }
11142 return 0;
11143 }
Peter Wangdafb9ac2020-01-15 14:13:38 -080011144
11145 /**
11146 * Request for receiving user activity notification
11147 */
11148 @Override
11149 public void requestUserActivityNotification() {
11150 if (!mNotifyUserActivity.get()
11151 && !mMainThreadHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
11152 mNotifyUserActivity.set(true);
11153 }
11154 }
11155
11156 /**
11157 * Called when userActivity is signalled in the power manager.
11158 * This is safe to call from any thread, with any window manager locks held or not.
11159 */
11160 @Override
11161 public void userActivity() {
11162 // ***************************************
11163 // * Inherited from PhoneWindowManager *
11164 // ***************************************
11165 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
11166 // WITH ITS LOCKS HELD.
11167 //
11168 // This code must be VERY careful about the locks
11169 // it acquires.
11170 // In fact, the current code acquires way too many,
11171 // and probably has lurking deadlocks.
11172
11173 if (Binder.getCallingUid() != Process.SYSTEM_UID) {
11174 throw new SecurityException("Only the OS may call notifyUserActivity()");
11175 }
11176
11177 if (mNotifyUserActivity.getAndSet(false)) {
11178 mMainThreadHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
11179 USER_ACTIVITY_NOTIFICATION_DELAY);
11180 }
11181 }
Malcolm Chen4639c562020-04-13 11:59:40 -070011182
11183 @Override
11184 public boolean canConnectTo5GInDsdsMode() {
11185 return mApp.getResources().getBoolean(R.bool.config_5g_connection_in_dsds_mode);
11186 }
Jack Yud10cdd42020-09-28 20:28:01 -070011187
11188 @Override
11189 public @NonNull List<String> getEquivalentHomePlmns(int subId, String callingPackage,
11190 String callingFeatureId) {
11191 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
11192 mApp, subId, callingPackage, callingFeatureId, "getEquivalentHomePlmns")) {
11193 throw new SecurityException("Requires READ_PHONE_STATE permission.");
11194 }
11195
11196 Phone phone = getPhone(subId);
11197 if (phone == null) {
11198 throw new RuntimeException("phone is not available");
11199 }
11200 // Now that all security checks passes, perform the operation as ourselves.
11201 final long identity = Binder.clearCallingIdentity();
11202 try {
11203 return phone.getEquivalentHomePlmns();
11204 } finally {
11205 Binder.restoreCallingIdentity(identity);
11206 }
11207 }
Daniel Bright59e67312020-11-13 11:49:37 -080011208
11209 @Override
11210 public boolean isRadioInterfaceCapabilitySupported(
Daniel Bright95a4c1f2021-02-11 09:57:16 -080011211 final @NonNull @TelephonyManager.RadioInterfaceCapability String capability) {
11212 Set<String> radioInterfaceCapabilities =
Daniel Bright94f43662021-03-01 14:43:40 -080011213 mRadioInterfaceCapabilities.getCapabilities();
Daniel Bright59e67312020-11-13 11:49:37 -080011214 if (radioInterfaceCapabilities == null) {
11215 throw new RuntimeException("radio interface capabilities are not available");
Daniel Bright59e67312020-11-13 11:49:37 -080011216 }
Daniel Bright95a4c1f2021-02-11 09:57:16 -080011217 return radioInterfaceCapabilities.contains(capability);
Daniel Bright59e67312020-11-13 11:49:37 -080011218 }
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011219
Hui Wang641e81c2020-10-12 12:14:23 -070011220 @Override
11221 public void bootstrapAuthenticationRequest(int subId, int appType, Uri nafUrl,
11222 UaSecurityProtocolIdentifier securityProtocol,
Brad Ebinger34c09a52021-02-17 23:23:21 +000011223 boolean forceBootStrapping, IBootstrapAuthenticationCallback callback) {
11224 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
11225 Binder.getCallingUid(), "bootstrapAuthenticationRequest",
11226 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11227 Manifest.permission.MODIFY_PHONE_STATE);
Hui Wang641e81c2020-10-12 12:14:23 -070011228 if (DBG) {
11229 log("bootstrapAuthenticationRequest, subId:" + subId + ", appType:"
11230 + appType + ", NAF:" + nafUrl + ", sp:" + securityProtocol
11231 + ", forceBootStrapping:" + forceBootStrapping + ", callback:" + callback);
11232 }
11233
11234 if (!SubscriptionManager.isValidSubscriptionId(subId)
11235 || appType < TelephonyManager.APPTYPE_UNKNOWN
11236 || appType > TelephonyManager.APPTYPE_ISIM
11237 || nafUrl == null || securityProtocol == null || callback == null) {
11238 Log.d(LOG_TAG, "bootstrapAuthenticationRequest failed due to invalid parameters");
11239 if (callback != null) {
11240 try {
11241 callback.onAuthenticationFailure(
11242 0, TelephonyManager.GBA_FAILURE_REASON_FEATURE_NOT_SUPPORTED);
11243 } catch (RemoteException exception) {
11244 log("Fail to notify onAuthenticationFailure due to " + exception);
11245 }
11246 return;
11247 }
11248 }
11249
11250 final long token = Binder.clearCallingIdentity();
11251 try {
11252 getGbaManager(subId).bootstrapAuthenticationRequest(
11253 new GbaAuthRequest(subId, appType, nafUrl, securityProtocol.toByteArray(),
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011254 forceBootStrapping, callback));
Hui Wang641e81c2020-10-12 12:14:23 -070011255 } finally {
11256 Binder.restoreCallingIdentity(token);
11257 }
11258 }
11259
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011260 /**
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011261 * Attempts to set the radio power state for all phones for thermal reason.
11262 * This does not guarantee that the
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011263 * requested radio power state will actually be set. See {@link
11264 * PhoneInternalInterface#setRadioPowerForReason} for more details.
11265 *
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011266 * @param enable {@code true} if trying to turn radio on.
11267 * @return {@code true} if phone setRadioPowerForReason was called. Otherwise, returns {@code
11268 * false}.
11269 */
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011270 private boolean setRadioPowerForThermal(boolean enable) {
11271 boolean isPhoneAvailable = false;
11272 for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) {
11273 Phone phone = PhoneFactory.getPhone(i);
11274 if (phone != null) {
Thomas Nguyenfd0572f2022-07-15 22:28:49 +000011275 phone.setRadioPowerForReason(enable, TelephonyManager.RADIO_POWER_REASON_THERMAL);
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011276 isPhoneAvailable = true;
11277 }
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011278 }
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011279
11280 // return true if successfully informed the phone object about the thermal radio power
11281 // request.
11282 return isPhoneAvailable;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011283 }
11284
11285 private int handleDataThrottlingRequest(int subId,
Sarah Chinecc78c42022-03-31 21:16:48 -070011286 DataThrottlingRequest dataThrottlingRequest, String callingPackage) {
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011287 boolean isDataThrottlingSupported = isRadioInterfaceCapabilitySupported(
11288 TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING);
11289 if (!isDataThrottlingSupported && dataThrottlingRequest.getDataThrottlingAction()
11290 != DataThrottlingRequest.DATA_THROTTLING_ACTION_NO_DATA_THROTTLING) {
11291 throw new IllegalArgumentException("modem does not support data throttling");
11292 }
11293
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011294 // Ensure that radio is on. If not able to power on due to phone being unavailable, return
11295 // THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011296 if (!setRadioPowerForThermal(true)) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011297 return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11298 }
11299
Sarah Chinecc78c42022-03-31 21:16:48 -070011300 setDataEnabledForReason(
11301 subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL, true, callingPackage);
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011302
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011303 if (isDataThrottlingSupported) {
11304 int thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011305 (int) sendRequest(CMD_SET_DATA_THROTTLING, dataThrottlingRequest, subId);
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011306 if (thermalMitigationResult == SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS) {
11307 throw new IllegalArgumentException("modem returned INVALID_ARGUMENTS");
11308 } else if (thermalMitigationResult
11309 == MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE) {
Jack Nudelman760d0962021-05-20 13:57:30 -070011310 log("Modem likely does not support data throttling on secondary carrier. Data " +
11311 "throttling action = " + dataThrottlingRequest.getDataThrottlingAction());
11312 return TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011313 }
11314 return thermalMitigationResult;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011315 }
Jack Nudelman5d6a98b2021-03-04 14:26:25 -080011316
11317 return TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011318 }
11319
Jack Nudelman644b91a2021-03-12 14:09:48 -080011320 private static List<String> getThermalMitigationAllowlist(Context context) {
11321 if (sThermalMitigationAllowlistedPackages.isEmpty()) {
11322 for (String pckg : context.getResources()
11323 .getStringArray(R.array.thermal_mitigation_allowlisted_packages)) {
11324 sThermalMitigationAllowlistedPackages.add(pckg);
11325 }
11326 }
11327
11328 return sThermalMitigationAllowlistedPackages;
11329 }
11330
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011331 private boolean isAnyPhoneInEmergencyState() {
11332 TelecomManager tm = mApp.getSystemService(TelecomManager.class);
11333 if (tm.isInEmergencyCall()) {
11334 Log.e(LOG_TAG , "Phone state is not valid. One of the phones is in an emergency call");
11335 return true;
11336 }
11337 for (Phone phone : PhoneFactory.getPhones()) {
11338 if (phone.isInEmergencySmsMode() || phone.isInEcm()) {
11339 Log.e(LOG_TAG, "Phone state is not valid. isInEmergencySmsMode = "
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011340 + phone.isInEmergencySmsMode() + " isInEmergencyCallbackMode = "
11341 + phone.isInEcm());
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011342 return true;
11343 }
11344 }
11345
11346 return false;
11347 }
11348
Jack Nudelman644b91a2021-03-12 14:09:48 -080011349 /**
11350 * Used by shell commands to add an authorized package name for thermal mitigation.
11351 * @param packageName name of package to be allowlisted
11352 * @param context
11353 */
11354 static void addPackageToThermalMitigationAllowlist(String packageName, Context context) {
11355 sThermalMitigationAllowlistedPackages = getThermalMitigationAllowlist(context);
11356 sThermalMitigationAllowlistedPackages.add(packageName);
11357 }
11358
11359 /**
11360 * Used by shell commands to remove an authorized package name for thermal mitigation.
11361 * @param packageName name of package to remove from allowlist
11362 * @param context
11363 */
11364 static void removePackageFromThermalMitigationAllowlist(String packageName, Context context) {
11365 sThermalMitigationAllowlistedPackages = getThermalMitigationAllowlist(context);
11366 sThermalMitigationAllowlistedPackages.remove(packageName);
11367 }
11368
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011369 /**
11370 * Thermal mitigation request to control functionalities at modem.
11371 *
11372 * @param subId the id of the subscription.
11373 * @param thermalMitigationRequest holds all necessary information to be passed down to modem.
Jack Nudelman644b91a2021-03-12 14:09:48 -080011374 * @param callingPackage the package name of the calling package.
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011375 *
11376 * @return thermalMitigationResult enum as defined in android.telephony.Annotation.
11377 */
11378 @Override
11379 @ThermalMitigationResult
11380 public int sendThermalMitigationRequest(
11381 int subId,
Jack Nudelman644b91a2021-03-12 14:09:48 -080011382 ThermalMitigationRequest thermalMitigationRequest,
11383 String callingPackage) throws IllegalArgumentException {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011384 enforceModifyPermission();
11385
Jack Nudelman644b91a2021-03-12 14:09:48 -080011386 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
11387 if (!getThermalMitigationAllowlist(getDefaultPhone().getContext())
11388 .contains(callingPackage)) {
11389 throw new SecurityException("Calling package must be configured in the device config. "
11390 + "calling package: " + callingPackage);
11391 }
11392
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011393 WorkSource workSource = getWorkSource(Binder.getCallingUid());
11394 final long identity = Binder.clearCallingIdentity();
11395
11396 int thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR;
11397 try {
11398 int thermalMitigationAction = thermalMitigationRequest.getThermalMitigationAction();
11399 switch (thermalMitigationAction) {
11400 case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING:
11401 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011402 handleDataThrottlingRequest(subId,
11403 thermalMitigationRequest.getDataThrottlingRequest(),
11404 callingPackage);
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011405 break;
11406 case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY:
11407 if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
11408 throw new IllegalArgumentException("dataThrottlingRequest must be null for "
11409 + "ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY");
11410 }
11411
11412 // Ensure that radio is on. If not able to power on due to phone being
11413 // unavailable, return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011414 if (!setRadioPowerForThermal(true)) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011415 thermalMitigationResult =
11416 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11417 break;
11418 }
11419
11420 setDataEnabledForReason(subId, TelephonyManager.DATA_ENABLED_REASON_THERMAL,
Sarah Chinecc78c42022-03-31 21:16:48 -070011421 false, callingPackage);
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011422 thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
11423 break;
11424 case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF:
11425 if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
11426 throw new IllegalArgumentException("dataThrottlingRequest must be null for"
11427 + " ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_RADIO_OFF");
11428 }
11429
11430 TelecomAccountRegistry registry = TelecomAccountRegistry.getInstance(null);
11431 if (registry != null) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011432 Phone phone = getPhone(subId);
11433 if (phone == null) {
11434 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011435 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011436 break;
11437 }
11438
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011439 TelephonyConnectionService service =
11440 registry.getTelephonyConnectionService();
Jack Nudelmanb30ac302021-06-17 15:39:58 -070011441 if (service != null && service.isEmergencyCallPending()) {
Jack Nudelmane69bbc82021-05-13 10:00:15 -070011442 Log.e(LOG_TAG, "An emergency call is pending");
11443 thermalMitigationResult =
11444 TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
11445 break;
11446 } else if (isAnyPhoneInEmergencyState()) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011447 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011448 TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011449 break;
11450 }
11451 } else {
11452 thermalMitigationResult =
11453 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11454 break;
11455 }
11456
11457 // Turn radio off. If not able to power off due to phone being unavailable,
11458 // return THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE.
Sooraj Sasindran72cff492021-07-29 09:42:42 -070011459 if (!setRadioPowerForThermal(false)) {
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011460 thermalMitigationResult =
11461 TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
11462 break;
11463 }
11464 thermalMitigationResult =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080011465 TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
Jack Nudelmanb0b87642020-11-12 15:04:39 -080011466 break;
11467 default:
11468 throw new IllegalArgumentException("the requested thermalMitigationAction does "
11469 + "not exist. Requested action: " + thermalMitigationAction);
11470 }
11471 } catch (IllegalArgumentException e) {
11472 throw e;
11473 } catch (Exception e) {
11474 Log.e(LOG_TAG, "thermalMitigationRequest. Exception e =" + e);
11475 thermalMitigationResult = TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_ERROR;
11476 } finally {
11477 Binder.restoreCallingIdentity(identity);
11478 }
11479
11480 if (DBG) {
11481 log("thermalMitigationRequest returning with thermalMitigationResult: "
11482 + thermalMitigationResult);
11483 }
11484
11485 return thermalMitigationResult;
11486 }
Hui Wang641e81c2020-10-12 12:14:23 -070011487
11488 /**
11489 * Set the GbaService Package Name that Telephony will bind to.
11490 *
11491 * @param subId The sim that the GbaService is associated with.
11492 * @param packageName The name of the package to be replaced with.
11493 * @return true if setting the GbaService to bind to succeeded, false if it did not.
11494 */
11495 @Override
11496 public boolean setBoundGbaServiceOverride(int subId, String packageName) {
11497 enforceModifyPermission();
11498
11499 final long identity = Binder.clearCallingIdentity();
11500 try {
11501 return getGbaManager(subId).overrideServicePackage(packageName);
11502 } finally {
11503 Binder.restoreCallingIdentity(identity);
11504 }
11505 }
11506
11507 /**
11508 * Return the package name of the currently bound GbaService.
11509 *
11510 * @param subId The sim that the GbaService is associated with.
11511 * @return the package name of the GbaService configuration, null if GBA is not supported.
11512 */
11513 @Override
11514 public String getBoundGbaService(int subId) {
11515 enforceReadPrivilegedPermission("getBoundGbaServicePackage");
11516
11517 final long identity = Binder.clearCallingIdentity();
11518 try {
11519 return getGbaManager(subId).getServicePackage();
11520 } finally {
11521 Binder.restoreCallingIdentity(identity);
11522 }
11523 }
11524
11525 /**
11526 * Set the release time for telephony to unbind GbaService.
11527 *
11528 * @param subId The sim that the GbaService is associated with.
11529 * @param interval The release time to unbind GbaService by millisecond.
11530 * @return true if setting the GbaService to bind to succeeded, false if it did not.
11531 */
11532 @Override
11533 public boolean setGbaReleaseTimeOverride(int subId, int interval) {
11534 enforceModifyPermission();
11535
11536 final long identity = Binder.clearCallingIdentity();
11537 try {
11538 return getGbaManager(subId).overrideReleaseTime(interval);
11539 } finally {
11540 Binder.restoreCallingIdentity(identity);
11541 }
11542 }
11543
11544 /**
11545 * Return the release time for telephony to unbind GbaService.
11546 *
11547 * @param subId The sim that the GbaService is associated with.
11548 * @return The release time to unbind GbaService by millisecond.
11549 */
11550 @Override
11551 public int getGbaReleaseTime(int subId) {
11552 enforceReadPrivilegedPermission("getGbaReleaseTime");
11553
11554 final long identity = Binder.clearCallingIdentity();
11555 try {
11556 return getGbaManager(subId).getReleaseTime();
11557 } finally {
11558 Binder.restoreCallingIdentity(identity);
11559 }
11560 }
11561
11562 private GbaManager getGbaManager(int subId) {
11563 GbaManager instance = GbaManager.getInstance(subId);
11564 if (instance == null) {
11565 String packageName = mApp.getResources().getString(R.string.config_gba_package);
11566 int releaseTime = mApp.getResources().getInteger(R.integer.config_gba_release_time);
11567 instance = GbaManager.make(mApp, subId, packageName, releaseTime);
11568 }
11569 return instance;
11570 }
Hui Wang761a6682020-10-31 05:12:53 +000011571
11572 /**
11573 * indicate whether the device and the carrier can support
11574 * RCS VoLTE single registration.
11575 */
11576 @Override
11577 public boolean isRcsVolteSingleRegistrationCapable(int subId) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011578 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
11579 Binder.getCallingUid(), "isRcsVolteSingleRegistrationCapable",
11580 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11581 permission.READ_PRIVILEGED_PHONE_STATE);
Hui Wang761a6682020-10-31 05:12:53 +000011582
11583 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11584 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11585 }
11586
11587 final long identity = Binder.clearCallingIdentity();
11588 try {
11589 RcsProvisioningMonitor rpm = RcsProvisioningMonitor.getInstance();
11590 if (rpm != null) {
Hui Wang67af90e2021-06-04 16:57:15 -070011591 Boolean isCapable = rpm.isRcsVolteSingleRegistrationEnabled(subId);
11592 if (isCapable != null) {
11593 return isCapable;
11594 }
Hui Wang761a6682020-10-31 05:12:53 +000011595 }
Hui Wang67af90e2021-06-04 16:57:15 -070011596 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
11597 "service is temporarily unavailable.");
Hui Wang761a6682020-10-31 05:12:53 +000011598 } finally {
11599 Binder.restoreCallingIdentity(identity);
11600 }
11601 }
11602
11603 /**
11604 * Register RCS provisioning callback.
11605 */
11606 @Override
Hui Wang3cac7e52021-01-27 14:45:25 -080011607 public void registerRcsProvisioningCallback(int subId,
Hui Wang761a6682020-10-31 05:12:53 +000011608 IRcsConfigCallback callback) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011609 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
Hui Wang3cac7e52021-01-27 14:45:25 -080011610 Binder.getCallingUid(), "registerRcsProvisioningCallback",
Brad Ebinger34c09a52021-02-17 23:23:21 +000011611 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11612 permission.READ_PRIVILEGED_PHONE_STATE);
Hui Wang761a6682020-10-31 05:12:53 +000011613
11614 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11615 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11616 }
11617 if (!isImsAvailableOnDevice()) {
11618 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
11619 "IMS not available on device.");
11620 }
11621
11622 final long identity = Binder.clearCallingIdentity();
11623 try {
Hui Wang68cd3722021-01-11 20:04:53 -080011624 if (!RcsProvisioningMonitor.getInstance()
Hui Wang3cac7e52021-01-27 14:45:25 -080011625 .registerRcsProvisioningCallback(subId, callback)) {
Brad Ebinger919631e2021-06-02 17:46:35 -070011626 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
11627 "Active subscription not found.");
Hui Wang68cd3722021-01-11 20:04:53 -080011628 }
Hui Wang761a6682020-10-31 05:12:53 +000011629 } finally {
11630 Binder.restoreCallingIdentity(identity);
11631 }
11632 }
11633
11634 /**
11635 * Unregister RCS provisioning callback.
11636 */
11637 @Override
Hui Wang3cac7e52021-01-27 14:45:25 -080011638 public void unregisterRcsProvisioningCallback(int subId,
Hui Wang761a6682020-10-31 05:12:53 +000011639 IRcsConfigCallback callback) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011640 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
Hui Wang3cac7e52021-01-27 14:45:25 -080011641 Binder.getCallingUid(), "unregisterRcsProvisioningCallback",
Brad Ebinger34c09a52021-02-17 23:23:21 +000011642 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
11643 permission.READ_PRIVILEGED_PHONE_STATE);
Hui Wang761a6682020-10-31 05:12:53 +000011644
11645 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11646 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11647 }
11648 if (!isImsAvailableOnDevice()) {
joonhunshin46b49a32022-12-21 05:33:23 +000011649 // operation failed silently
11650 Rlog.w(LOG_TAG, "IMS not available on device.");
11651 return;
Hui Wang761a6682020-10-31 05:12:53 +000011652 }
11653
11654 final long identity = Binder.clearCallingIdentity();
11655 try {
Hui Wang68cd3722021-01-11 20:04:53 -080011656 RcsProvisioningMonitor.getInstance()
Hui Wang3cac7e52021-01-27 14:45:25 -080011657 .unregisterRcsProvisioningCallback(subId, callback);
Hui Wang761a6682020-10-31 05:12:53 +000011658 } finally {
11659 Binder.restoreCallingIdentity(identity);
11660 }
11661 }
11662
11663 /**
11664 * trigger RCS reconfiguration.
11665 */
11666 public void triggerRcsReconfiguration(int subId) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011667 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
11668 "triggerRcsReconfiguration",
11669 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
Hui Wang761a6682020-10-31 05:12:53 +000011670
11671 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11672 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11673 }
11674 if (!isImsAvailableOnDevice()) {
joonhunshin46b49a32022-12-21 05:33:23 +000011675 // ProvisioningManager can not handle ServiceSpecificException.
11676 // Throw the IllegalStateException and annotate ProvisioningManager.
11677 throw new IllegalStateException("IMS not available on device.");
Hui Wang761a6682020-10-31 05:12:53 +000011678 }
11679
11680 final long identity = Binder.clearCallingIdentity();
11681 try {
11682 RcsProvisioningMonitor.getInstance().requestReconfig(subId);
11683 } finally {
11684 Binder.restoreCallingIdentity(identity);
11685 }
11686 }
11687
11688 /**
11689 * Provide the client configuration parameters of the RCS application.
11690 */
11691 public void setRcsClientConfiguration(int subId, RcsClientConfiguration rcc) {
Brad Ebinger34c09a52021-02-17 23:23:21 +000011692 TelephonyPermissions.enforceAnyPermissionGranted(mApp, Binder.getCallingUid(),
11693 "setRcsClientConfiguration",
11694 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
Hui Wang761a6682020-10-31 05:12:53 +000011695
11696 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
11697 throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
11698 }
11699 if (!isImsAvailableOnDevice()) {
11700 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
11701 "IMS not available on device.");
11702 }
11703
11704 final long identity = Binder.clearCallingIdentity();
11705
11706 try {
11707 IImsConfig configBinder = getImsConfig(getSlotIndex(subId), ImsFeature.FEATURE_RCS);
11708 if (configBinder == null) {
11709 Rlog.e(LOG_TAG, "null result for setRcsClientConfiguration");
Brad Ebinger919631e2021-06-02 17:46:35 -070011710 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
11711 "could not find the requested subscription");
Hui Wang761a6682020-10-31 05:12:53 +000011712 } else {
11713 configBinder.setRcsClientConfiguration(rcc);
11714 }
joonhunshin3e154242021-09-17 06:33:39 +000011715
11716 RcsStats.getInstance().onRcsClientProvisioningStats(subId,
11717 RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT);
Hui Wang761a6682020-10-31 05:12:53 +000011718 } catch (RemoteException e) {
11719 Rlog.e(LOG_TAG, "fail to setRcsClientConfiguration " + e.getMessage());
Brad Ebinger919631e2021-06-02 17:46:35 -070011720 throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
11721 "service is temporarily unavailable.");
Hui Wang761a6682020-10-31 05:12:53 +000011722 } finally {
11723 Binder.restoreCallingIdentity(identity);
11724 }
11725 }
11726
11727 /**
Hui Wangbaaee6a2021-02-19 20:45:36 -080011728 * Enables or disables the test mode for RCS VoLTE single registration.
11729 */
11730 @Override
11731 public void setRcsSingleRegistrationTestModeEnabled(boolean enabled) {
11732 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11733 "setRcsSingleRegistrationTestModeEnabled");
11734
11735 RcsProvisioningMonitor.getInstance().setTestModeEnabled(enabled);
11736 }
11737
11738 /**
11739 * Gets the test mode for RCS VoLTE single registration.
11740 */
11741 @Override
11742 public boolean getRcsSingleRegistrationTestModeEnabled() {
11743 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11744 "getRcsSingleRegistrationTestModeEnabled");
11745
11746 return RcsProvisioningMonitor.getInstance().getTestModeEnabled();
11747 }
11748
11749 /**
Hui Wang761a6682020-10-31 05:12:53 +000011750 * Overrides the config of RCS VoLTE single registration enabled for the device.
11751 */
11752 @Override
11753 public void setDeviceSingleRegistrationEnabledOverride(String enabledStr) {
11754 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11755 "setDeviceSingleRegistrationEnabledOverride");
11756 enforceModifyPermission();
11757
11758 Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
11759 : Boolean.parseBoolean(enabledStr);
11760 RcsProvisioningMonitor.getInstance().overrideDeviceSingleRegistrationEnabled(enabled);
Brad Ebinger49a72b42021-01-29 00:55:24 +000011761 mApp.imsRcsController.setDeviceSingleRegistrationSupportOverride(enabled);
Hui Wang761a6682020-10-31 05:12:53 +000011762 }
11763
11764 /**
Tyler Gunn92479152021-01-20 16:30:10 -080011765 * Sends a device to device communication message. Only usable via shell.
11766 * @param message message to send.
11767 * @param value message value.
11768 */
11769 @Override
11770 public void sendDeviceToDeviceMessage(int message, int value) {
11771 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
Tyler Gunnbabbda02021-02-10 11:05:02 -080011772 "sendDeviceToDeviceMessage");
Tyler Gunn92479152021-01-20 16:30:10 -080011773 enforceModifyPermission();
11774
11775 final long identity = Binder.clearCallingIdentity();
11776 try {
11777 TelephonyConnectionService service =
11778 TelecomAccountRegistry.getInstance(null).getTelephonyConnectionService();
11779 if (service == null) {
11780 Rlog.e(LOG_TAG, "sendDeviceToDeviceMessage: not in a call.");
11781 return;
11782 }
11783 service.sendTestDeviceToDeviceMessage(message, value);
11784 } finally {
11785 Binder.restoreCallingIdentity(identity);
11786 }
11787 }
11788
Tyler Gunnbabbda02021-02-10 11:05:02 -080011789 /**
11790 * Sets the specified device to device transport active.
11791 * @param transport The transport to set active.
11792 */
11793 @Override
11794 public void setActiveDeviceToDeviceTransport(@NonNull String transport) {
11795 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11796 "setActiveDeviceToDeviceTransport");
11797 enforceModifyPermission();
11798
11799 final long identity = Binder.clearCallingIdentity();
11800 try {
11801 TelephonyConnectionService service =
11802 TelecomAccountRegistry.getInstance(null).getTelephonyConnectionService();
11803 if (service == null) {
11804 Rlog.e(LOG_TAG, "setActiveDeviceToDeviceTransport: not in a call.");
11805 return;
11806 }
11807 service.setActiveDeviceToDeviceTransport(transport);
11808 } finally {
11809 Binder.restoreCallingIdentity(identity);
11810 }
11811 }
Tyler Gunn92479152021-01-20 16:30:10 -080011812
Tyler Gunnd4339262021-05-03 14:46:49 -070011813 @Override
11814 public void setDeviceToDeviceForceEnabled(boolean isForceEnabled) {
11815 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11816 "setDeviceToDeviceForceEnabled");
11817
11818 final long identity = Binder.clearCallingIdentity();
11819 try {
11820 Arrays.stream(PhoneFactory.getPhones()).forEach(
11821 p -> {
11822 Phone thePhone = p.getImsPhone();
11823 if (thePhone != null && thePhone instanceof ImsPhone) {
11824 ImsPhone imsPhone = (ImsPhone) thePhone;
11825 CallTracker tracker = imsPhone.getCallTracker();
11826 if (tracker != null && tracker instanceof ImsPhoneCallTracker) {
11827 ImsPhoneCallTracker imsPhoneCallTracker =
11828 (ImsPhoneCallTracker) tracker;
11829 imsPhoneCallTracker.setDeviceToDeviceForceEnabled(isForceEnabled);
11830 }
11831 }
11832 }
11833 );
11834 } finally {
11835 Binder.restoreCallingIdentity(identity);
11836 }
11837 }
11838
Tyler Gunn92479152021-01-20 16:30:10 -080011839 /**
Hui Wang761a6682020-10-31 05:12:53 +000011840 * Gets the config of RCS VoLTE single registration enabled for the device.
11841 */
11842 @Override
11843 public boolean getDeviceSingleRegistrationEnabled() {
11844 enforceReadPrivilegedPermission("getDeviceSingleRegistrationEnabled");
11845 return RcsProvisioningMonitor.getInstance().getDeviceSingleRegistrationEnabled();
11846 }
11847
11848 /**
11849 * Overrides the config of RCS VoLTE single registration enabled for the carrier/subscription.
11850 */
11851 @Override
11852 public boolean setCarrierSingleRegistrationEnabledOverride(int subId, String enabledStr) {
11853 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11854 "setCarrierSingleRegistrationEnabledOverride");
11855 enforceModifyPermission();
11856
11857 Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
11858 : Boolean.parseBoolean(enabledStr);
11859 return RcsProvisioningMonitor.getInstance().overrideCarrierSingleRegistrationEnabled(
11860 subId, enabled);
11861 }
11862
11863 /**
11864 * Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
11865 */
11866 @Override
11867 public boolean getCarrierSingleRegistrationEnabled(int subId) {
11868 enforceReadPrivilegedPermission("getCarrierSingleRegistrationEnabled");
11869 return RcsProvisioningMonitor.getInstance().getCarrierSingleRegistrationEnabled(subId);
11870 }
Chiachang Wangd6d34772020-12-22 11:38:27 +080011871
11872 /**
Hui Wangb647abe2021-02-26 09:33:38 -080011873 * Overrides the ims feature validation result
11874 */
11875 @Override
11876 public boolean setImsFeatureValidationOverride(int subId, String enabledStr) {
11877 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11878 "setImsFeatureValidationOverride");
11879
11880 Boolean enabled = "NULL".equalsIgnoreCase(enabledStr) ? null
11881 : Boolean.parseBoolean(enabledStr);
11882 return RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(
11883 subId, enabled);
11884 }
11885
11886 /**
11887 * Gets the ims feature validation override value
11888 */
11889 @Override
11890 public boolean getImsFeatureValidationOverride(int subId) {
11891 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11892 "getImsFeatureValidationOverride");
11893 return RcsProvisioningMonitor.getInstance().getImsFeatureValidationOverride(subId);
11894 }
11895
11896 /**
Chiachang Wangd6d34772020-12-22 11:38:27 +080011897 * Get the mobile provisioning url that is used to launch a browser to allow users to manage
11898 * their mobile plan.
11899 */
11900 @Override
11901 public String getMobileProvisioningUrl() {
11902 enforceReadPrivilegedPermission("getMobileProvisioningUrl");
11903 final long identity = Binder.clearCallingIdentity();
11904 try {
11905 return getDefaultPhone().getMobileProvisioningUrl();
11906 } finally {
11907 Binder.restoreCallingIdentity(identity);
11908 }
11909 }
Rambo Wanga5cc9b72021-01-07 10:51:54 -080011910
James.cf Linbcdf8b32021-01-14 16:44:13 +080011911 /**
calvinpane4a8a1d2021-01-25 13:51:18 +080011912 * Get the EAB contact from the EAB database.
11913 */
11914 @Override
11915 public String getContactFromEab(String contact) {
11916 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getContactFromEab");
11917 enforceModifyPermission();
11918 final long identity = Binder.clearCallingIdentity();
11919 try {
11920 return EabUtil.getContactFromEab(getDefaultPhone().getContext(), contact);
11921 } finally {
11922 Binder.restoreCallingIdentity(identity);
11923 }
11924 }
11925
11926 /**
Calvin Pana1434322021-07-01 19:27:01 +080011927 * Get the EAB capability from the EAB database.
11928 */
11929 @Override
11930 public String getCapabilityFromEab(String contact) {
11931 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getCapabilityFromEab");
11932 enforceModifyPermission();
11933 final long identity = Binder.clearCallingIdentity();
11934 try {
11935 return EabUtil.getCapabilityFromEab(getDefaultPhone().getContext(), contact);
11936 } finally {
11937 Binder.restoreCallingIdentity(identity);
11938 }
11939 }
11940
11941 /**
James.cf Linbcdf8b32021-01-14 16:44:13 +080011942 * Remove the EAB contacts from the EAB database.
11943 */
11944 @Override
11945 public int removeContactFromEab(int subId, String contacts) {
11946 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "removeCapabilitiesFromEab");
11947 enforceModifyPermission();
11948 final long identity = Binder.clearCallingIdentity();
11949 try {
11950 return EabUtil.removeContactFromEab(subId, contacts, getDefaultPhone().getContext());
11951 } finally {
11952 Binder.restoreCallingIdentity(identity);
11953 }
11954 }
11955
Rambo Wanga5cc9b72021-01-07 10:51:54 -080011956 @Override
James.cf Lin4b784aa2021-01-31 03:25:15 +080011957 public boolean getDeviceUceEnabled() {
11958 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getDeviceUceEnabled");
11959 final long identity = Binder.clearCallingIdentity();
11960 try {
11961 return mApp.getDeviceUceEnabled();
11962 } finally {
11963 Binder.restoreCallingIdentity(identity);
11964 }
11965 }
11966
11967 @Override
11968 public void setDeviceUceEnabled(boolean isEnabled) {
11969 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setDeviceUceEnabled");
11970 final long identity = Binder.clearCallingIdentity();
11971 try {
11972 mApp.setDeviceUceEnabled(isEnabled);
11973 } finally {
11974 Binder.restoreCallingIdentity(identity);
11975 }
11976 }
11977
Brad Ebinger14d467f2021-02-12 06:18:28 +000011978 /**
11979 * Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
11980 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
11981 */
11982 // Used for SHELL command only right now.
11983 @Override
11984 public RcsContactUceCapability addUceRegistrationOverrideShell(int subId,
11985 List<String> featureTags) {
11986 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
11987 "addUceRegistrationOverrideShell");
11988 final long identity = Binder.clearCallingIdentity();
11989 try {
11990 return mApp.imsRcsController.addUceRegistrationOverrideShell(subId,
11991 new ArraySet<>(featureTags));
11992 } catch (ImsException e) {
11993 throw new ServiceSpecificException(e.getCode(), e.getMessage());
11994 } finally {
11995 Binder.restoreCallingIdentity(identity);
11996 }
11997 }
11998
11999 /**
12000 * Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
12001 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
12002 */
12003 // Used for SHELL command only right now.
12004 @Override
12005 public RcsContactUceCapability removeUceRegistrationOverrideShell(int subId,
12006 List<String> featureTags) {
12007 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
12008 "removeUceRegistrationOverrideShell");
12009 final long identity = Binder.clearCallingIdentity();
12010 try {
12011 return mApp.imsRcsController.removeUceRegistrationOverrideShell(subId,
12012 new ArraySet<>(featureTags));
12013 } catch (ImsException e) {
12014 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12015 } finally {
12016 Binder.restoreCallingIdentity(identity);
12017 }
12018 }
12019
12020 /**
12021 * Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
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 clearUceRegistrationOverrideShell(int subId) {
12027 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
12028 "clearUceRegistrationOverrideShell");
12029 final long identity = Binder.clearCallingIdentity();
12030 try {
12031 return mApp.imsRcsController.clearUceRegistrationOverrideShell(subId);
12032 } catch (ImsException e) {
12033 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12034 } finally {
12035 Binder.restoreCallingIdentity(identity);
12036 }
12037 }
12038
12039 /**
12040 * @return current RcsContactUceCapability instance that will be used for PUBLISH.
12041 */
12042 // Used for SHELL command only right now.
12043 @Override
12044 public RcsContactUceCapability getLatestRcsContactUceCapabilityShell(int subId) {
12045 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
12046 "getLatestRcsContactUceCapabilityShell");
12047 final long identity = Binder.clearCallingIdentity();
12048 try {
12049 return mApp.imsRcsController.getLatestRcsContactUceCapabilityShell(subId);
12050 } catch (ImsException e) {
12051 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12052 } finally {
12053 Binder.restoreCallingIdentity(identity);
12054 }
12055 }
12056
12057 /**
12058 * Returns the last PIDF XML sent to the network during the last PUBLISH or "none" if the
12059 * device does not have an active PUBLISH.
12060 */
12061 // Used for SHELL command only right now.
12062 @Override
12063 public String getLastUcePidfXmlShell(int subId) {
12064 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "uceGetLastPidfXml");
12065 final long identity = Binder.clearCallingIdentity();
12066 try {
12067 return mApp.imsRcsController.getLastUcePidfXmlShell(subId);
12068 } catch (ImsException e) {
12069 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12070 } finally {
12071 Binder.restoreCallingIdentity(identity);
12072 }
12073 }
12074
James.cf Line8713a42021-04-29 16:04:26 +080012075 /**
12076 * Remove UCE requests cannot be sent to the network status.
12077 */
12078 // Used for SHELL command only right now.
12079 @Override
12080 public boolean removeUceRequestDisallowedStatus(int subId) {
12081 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "uceRemoveDisallowedStatus");
12082 final long identity = Binder.clearCallingIdentity();
12083 try {
12084 return mApp.imsRcsController.removeUceRequestDisallowedStatus(subId);
12085 } catch (ImsException e) {
12086 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12087 } finally {
12088 Binder.restoreCallingIdentity(identity);
12089 }
12090 }
12091
James.cf Lin18bb9002021-05-25 01:37:38 +080012092 /**
12093 * Remove UCE requests cannot be sent to the network status.
12094 */
12095 // Used for SHELL command only.
12096 @Override
12097 public boolean setCapabilitiesRequestTimeout(int subId, long timeoutAfterMs) {
12098 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setCapRequestTimeout");
12099 final long identity = Binder.clearCallingIdentity();
12100 try {
12101 return mApp.imsRcsController.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
12102 } catch (ImsException e) {
12103 throw new ServiceSpecificException(e.getCode(), e.getMessage());
12104 } finally {
12105 Binder.restoreCallingIdentity(identity);
12106 }
12107 }
Brad Ebinger14d467f2021-02-12 06:18:28 +000012108
James.cf Lin4b784aa2021-01-31 03:25:15 +080012109 @Override
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012110 public void setSignalStrengthUpdateRequest(int subId, SignalStrengthUpdateRequest request,
12111 String callingPackage) {
12112 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
12113 mApp, subId, "setSignalStrengthUpdateRequest");
12114
12115 final int callingUid = Binder.getCallingUid();
12116 // Verify that tha callingPackage belongs to the calling UID
12117 mApp.getSystemService(AppOpsManager.class)
12118 .checkPackage(callingUid, callingPackage);
12119
Rambo Wang3607f502021-02-01 21:51:40 -080012120 validateSignalStrengthUpdateRequest(mApp, request, callingUid);
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012121
12122 final long identity = Binder.clearCallingIdentity();
12123 try {
12124 Object result = sendRequest(CMD_SET_SIGNAL_STRENGTH_UPDATE_REQUEST,
12125 new Pair<Integer, SignalStrengthUpdateRequest>(callingUid, request), subId);
12126
12127 if (result instanceof IllegalStateException) {
12128 throw (IllegalStateException) result;
12129 }
12130 } finally {
12131 Binder.restoreCallingIdentity(identity);
12132 }
12133 }
12134
12135 @Override
12136 public void clearSignalStrengthUpdateRequest(int subId, SignalStrengthUpdateRequest request,
12137 String callingPackage) {
12138 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
12139 mApp, subId, "clearSignalStrengthUpdateRequest");
12140
12141 final int callingUid = Binder.getCallingUid();
12142 // Verify that tha callingPackage belongs to the calling UID
12143 mApp.getSystemService(AppOpsManager.class)
12144 .checkPackage(callingUid, callingPackage);
12145
12146 final long identity = Binder.clearCallingIdentity();
12147 try {
12148 Object result = sendRequest(CMD_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST,
12149 new Pair<Integer, SignalStrengthUpdateRequest>(callingUid, request), subId);
12150
12151 if (result instanceof IllegalStateException) {
12152 throw (IllegalStateException) result;
12153 }
12154 } finally {
12155 Binder.restoreCallingIdentity(identity);
12156 }
12157 }
12158
Rambo Wang3607f502021-02-01 21:51:40 -080012159 private static void validateSignalStrengthUpdateRequest(Context context,
12160 SignalStrengthUpdateRequest request, int callingUid) {
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012161 if (callingUid == Process.PHONE_UID || callingUid == Process.SYSTEM_UID) {
12162 // phone/system process do not have further restriction on request
12163 return;
12164 }
12165
12166 // Applications has restrictions on how to use the request:
Rambo Wang3607f502021-02-01 21:51:40 -080012167 // Non-system callers need permission to set mIsSystemThresholdReportingRequestedWhileIdle
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012168 if (request.isSystemThresholdReportingRequestedWhileIdle()) {
Rambo Wang3607f502021-02-01 21:51:40 -080012169 context.enforceCallingOrSelfPermission(
12170 android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH,
12171 "validateSignalStrengthUpdateRequest");
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012172 }
12173
12174 for (SignalThresholdInfo info : request.getSignalThresholdInfos()) {
Nagendra Prasad Nagarle Basavarajufee544c2022-12-07 16:34:52 +000012175 // Only system caller can set mHysteresisMs/mIsEnabled.
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012176 if (info.getHysteresisMs() != SignalThresholdInfo.HYSTERESIS_MS_DISABLED
Rambo Wanga5cc9b72021-01-07 10:51:54 -080012177 || info.isEnabled()) {
12178 throw new IllegalArgumentException(
12179 "Only system can set hide fields in SignalThresholdInfo");
12180 }
12181
12182 // Thresholds length for each RAN need in range. This has been validated in
12183 // SignalThresholdInfo#Builder#setThreshold. Here we prevent apps calling hide method
12184 // setThresholdUnlimited (e.g. through reflection) with too short or too long thresholds
12185 final int[] thresholds = info.getThresholds();
12186 Objects.requireNonNull(thresholds);
12187 if (thresholds.length < SignalThresholdInfo.getMinimumNumberOfThresholdsAllowed()
12188 || thresholds.length
12189 > SignalThresholdInfo.getMaximumNumberOfThresholdsAllowed()) {
12190 throw new IllegalArgumentException(
12191 "thresholds length is out of range: " + thresholds.length);
12192 }
12193 }
12194 }
SongFerngWang8236caa2021-01-17 21:51:44 +080012195
12196 /**
12197 * Gets the current phone capability.
12198 *
12199 * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
12200 * @return the PhoneCapability which describes the data connection capability of modem.
12201 * It's used to evaluate possible phone config change, for example from single
12202 * SIM device to multi-SIM device.
12203 */
12204 @Override
12205 public PhoneCapability getPhoneCapability() {
12206 enforceReadPrivilegedPermission("getPhoneCapability");
12207 final long identity = Binder.clearCallingIdentity();
12208 try {
12209 return mPhoneConfigurationManager.getCurrentPhoneCapability();
12210 } finally {
12211 Binder.restoreCallingIdentity(identity);
12212 }
12213 }
Michele Berionne5e411512020-11-13 02:36:59 +000012214
12215 /**
12216 * Prepare TelephonyManager for an unattended reboot. The reboot is
12217 * required to be done shortly after the API is invoked.
12218 */
12219 @Override
12220 @TelephonyManager.PrepareUnattendedRebootResult
12221 public int prepareForUnattendedReboot() {
Rafael Higuera Silvad9630642021-09-20 15:32:01 +000012222 WorkSource workSource = getWorkSource(Binder.getCallingUid());
Michele Berionne5e411512020-11-13 02:36:59 +000012223 enforceRebootPermission();
12224
12225 final long identity = Binder.clearCallingIdentity();
12226 try {
Rafael Higuera Silvad9630642021-09-20 15:32:01 +000012227 return (int) sendRequest(CMD_PREPARE_UNATTENDED_REBOOT, null, workSource);
Michele Berionne5e411512020-11-13 02:36:59 +000012228 } finally {
12229 Binder.restoreCallingIdentity(identity);
12230 }
12231 }
Hongbo Zeng156aa4a2021-02-08 21:50:28 +080012232
12233 /**
12234 * Request to get the current slicing configuration including URSP rules and
12235 * NSSAIs (configured, allowed and rejected).
12236 *
12237 * Requires carrier privileges or READ_PRIVILEGED_PHONE_STATE permission.
12238 */
12239 @Override
12240 public void getSlicingConfig(ResultReceiver callback) {
Hongbo Zeng1b2063d2022-02-21 01:33:03 +000012241 TelephonyPermissions
12242 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
12243 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, "getSlicingConfig");
Hongbo Zeng156aa4a2021-02-08 21:50:28 +080012244
12245 final long identity = Binder.clearCallingIdentity();
12246 try {
12247 Phone phone = getDefaultPhone();
12248 sendRequestAsync(CMD_GET_SLICING_CONFIG, callback, phone, null);
12249 } finally {
12250 Binder.restoreCallingIdentity(identity);
12251 }
12252 }
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012253
12254 /**
Sarah Chin2ec39f62022-08-31 17:03:26 -070012255 * Check whether the given premium capability is available for purchase from the carrier.
12256 *
12257 * @param capability The premium capability to check.
12258 * @param subId The subId to check the premium capability for.
12259 *
12260 * @return Whether the given premium capability is available to purchase.
12261 */
12262 @Override
12263 public boolean isPremiumCapabilityAvailableForPurchase(int capability, int subId) {
12264 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
12265 mApp, "isPremiumCapabilityAvailableForPurchase")) {
12266 log("Premium capability "
12267 + TelephonyManager.convertPremiumCapabilityToString(capability)
12268 + " is not available for purchase due to missing permissions.");
12269 throw new SecurityException("isPremiumCapabilityAvailableForPurchase requires "
12270 + "permission READ_BASIC_PHONE_STATE.");
12271 }
12272
12273 Phone phone = getPhone(subId);
Thomas Nguyen7216ed62022-11-29 16:45:31 -080012274 if (phone == null) {
12275 loge("isPremiumCapabilityAvailableForPurchase: phone is null, subId=" + subId);
12276 return false;
12277 }
Sarah Chin2ec39f62022-08-31 17:03:26 -070012278 final long identity = Binder.clearCallingIdentity();
12279 try {
Sarah Chin46355ba2022-11-01 23:51:16 -070012280 return SlicePurchaseController.getInstance(phone)
Sarah Chin2ec39f62022-08-31 17:03:26 -070012281 .isPremiumCapabilityAvailableForPurchase(capability);
12282 } finally {
12283 Binder.restoreCallingIdentity(identity);
12284 }
12285 }
12286
12287 /**
12288 * Purchase the given premium capability from the carrier.
12289 *
12290 * @param capability The premium capability to purchase.
12291 * @param callback The result of the purchase request.
12292 * @param subId The subId to purchase the premium capability for.
12293 */
12294 @Override
12295 public void purchasePremiumCapability(int capability, IIntegerConsumer callback, int subId) {
12296 log("purchasePremiumCapability: capability="
12297 + TelephonyManager.convertPremiumCapabilityToString(capability) + ", caller="
12298 + getCurrentPackageName());
12299
12300 if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
12301 mApp, "purchasePremiumCapability")) {
12302 log("purchasePremiumCapability "
12303 + TelephonyManager.convertPremiumCapabilityToString(capability)
12304 + " failed due to missing permissions.");
12305 throw new SecurityException("purchasePremiumCapability requires permission "
12306 + "READ_BASIC_PHONE_STATE.");
Sarah Chin532d6bb2022-12-28 22:50:43 -080012307 } else if (!TelephonyPermissions.checkInternetPermissionNoThrow(
12308 mApp, "purchasePremiumCapability")) {
12309 log("purchasePremiumCapability "
12310 + TelephonyManager.convertPremiumCapabilityToString(capability)
12311 + " failed due to missing permissions.");
12312 throw new SecurityException("purchasePremiumCapability requires permission INTERNET.");
Sarah Chin2ec39f62022-08-31 17:03:26 -070012313 }
12314
12315 Phone phone = getPhone(subId);
Sarah Chin19694112022-12-06 15:41:37 -080012316 if (phone == null) {
12317 try {
12318 int result = TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_REQUEST_FAILED;
12319 callback.accept(result);
12320 loge("purchasePremiumCapability: phone is null, subId=" + subId);
12321 } catch (RemoteException e) {
12322 String logStr = "Purchase premium capability "
12323 + TelephonyManager.convertPremiumCapabilityToString(capability)
12324 + " failed due to RemoteException handling null phone: " + e;
12325 if (DBG) log(logStr);
12326 AnomalyReporter.reportAnomaly(
12327 UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
12328 }
12329 return;
12330 }
Sarah Chin532d6bb2022-12-28 22:50:43 -080012331
12332 String callingProcess;
Sarah Chin71b3a852022-09-28 15:54:19 -070012333 try {
Sarah Chin532d6bb2022-12-28 22:50:43 -080012334 callingProcess = mApp.getPackageManager().getApplicationInfo(
12335 getCurrentPackageName(), 0).processName;
Sarah Chin71b3a852022-09-28 15:54:19 -070012336 } catch (PackageManager.NameNotFoundException e) {
Sarah Chin532d6bb2022-12-28 22:50:43 -080012337 callingProcess = getCurrentPackageName();
Sarah Chin71b3a852022-09-28 15:54:19 -070012338 }
Sarah Chin532d6bb2022-12-28 22:50:43 -080012339
12340 boolean isVisible = false;
12341 ActivityManager am = mApp.getSystemService(ActivityManager.class);
12342 if (am != null) {
12343 List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
12344 if (processes != null) {
12345 for (ActivityManager.RunningAppProcessInfo process : processes) {
12346 log("purchasePremiumCapability: process " + process.processName
12347 + "has importance " + process.importance);
12348 if (process.processName.equals(callingProcess) && process.importance
12349 <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
12350 isVisible = true;
12351 break;
12352 }
12353 }
12354 }
12355 }
12356
12357 if (!isVisible) {
12358 try {
12359 int result = TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND;
12360 callback.accept(result);
12361 loge("purchasePremiumCapability: " + callingProcess + " is not in the foreground.");
12362 } catch (RemoteException e) {
12363 String logStr = "Purchase premium capability "
12364 + TelephonyManager.convertPremiumCapabilityToString(capability)
12365 + " failed due to RemoteException handling background application: " + e;
12366 if (DBG) log(logStr);
12367 AnomalyReporter.reportAnomaly(
12368 UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
12369 }
12370 return;
12371 }
12372
Sarah Chin71b3a852022-09-28 15:54:19 -070012373 sendRequestAsync(CMD_PURCHASE_PREMIUM_CAPABILITY,
Sarah Chinb8218c22023-01-04 13:35:29 -080012374 new PurchasePremiumCapabilityArgument(capability, callback), phone, null);
Sarah Chin2ec39f62022-08-31 17:03:26 -070012375 }
12376
12377 /**
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012378 * Register an IMS connection state callback
12379 */
12380 @Override
Hunsuk Choi89bd22c2021-11-01 13:04:54 +000012381 public void registerImsStateCallback(int subId, int feature, IImsStateCallback cb,
12382 String callingPackage) {
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012383 if (feature == ImsFeature.FEATURE_MMTEL) {
12384 // ImsMmTelManager
12385 // The following also checks READ_PRIVILEGED_PHONE_STATE.
12386 TelephonyPermissions
12387 .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
12388 mApp, subId, "registerImsStateCallback");
12389 } else if (feature == ImsFeature.FEATURE_RCS) {
12390 // ImsRcsManager or SipDelegateManager
12391 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(mApp, subId,
12392 Binder.getCallingUid(), "registerImsStateCallback",
12393 Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
12394 Manifest.permission.READ_PRECISE_PHONE_STATE,
12395 Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
12396 Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION);
12397 }
12398
12399 if (!ImsManager.isImsSupportedOnDevice(mApp)) {
12400 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
12401 "IMS not available on device.");
12402 }
12403
12404 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
12405 throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION);
12406 }
12407
12408 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
12409 if (controller == null) {
12410 throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
12411 "IMS not available on device.");
12412 }
12413
Hunsuk Choi89bd22c2021-11-01 13:04:54 +000012414 if (callingPackage == null) {
12415 callingPackage = getCurrentPackageName();
12416 }
12417
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012418 final long token = Binder.clearCallingIdentity();
12419 try {
12420 int slotId = getSlotIndexOrException(subId);
Hunsuk Choi89bd22c2021-11-01 13:04:54 +000012421 controller.registerImsStateCallback(subId, feature, cb, callingPackage);
Hunsuk Choi3b742d62021-10-25 19:48:34 +000012422 } catch (ImsException e) {
12423 throw new ServiceSpecificException(e.getCode());
12424 } finally {
12425 Binder.restoreCallingIdentity(token);
12426 }
12427 }
12428
12429 /**
12430 * Unregister an IMS connection state callback
12431 */
12432 @Override
12433 public void unregisterImsStateCallback(IImsStateCallback cb) {
12434 final long token = Binder.clearCallingIdentity();
12435 ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
12436 if (controller == null) {
12437 return;
12438 }
12439 try {
12440 controller.unregisterImsStateCallback(cb);
12441 } finally {
12442 Binder.restoreCallingIdentity(token);
12443 }
12444 }
Sooraj Sasindranfae41b32021-10-26 02:10:05 -070012445
12446 /**
12447 * @return {@CellIdentity} last known cell identity {@CellIdentity}.
12448 *
12449 * Require {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
12450 * com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID, otherwise throws
12451 * SecurityException.
12452 * If there is current registered network this value will be same as the registered cell
12453 * identity. If the device goes out of service the previous cell identity is cached and
12454 * will be returned. If the cache age of the Cell identity is more than 24 hours
12455 * it will be cleared and null will be returned.
12456 *
12457 */
12458 @Override
12459 public @Nullable CellIdentity getLastKnownCellIdentity(int subId, String callingPackage,
12460 String callingFeatureId) {
12461 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12462 LocationAccessPolicy.LocationPermissionResult fineLocationResult =
12463 LocationAccessPolicy.checkLocationPermission(mApp,
12464 new LocationAccessPolicy.LocationPermissionQuery.Builder()
12465 .setCallingPackage(callingPackage)
12466 .setCallingFeatureId(callingFeatureId)
12467 .setCallingPid(Binder.getCallingPid())
12468 .setCallingUid(Binder.getCallingUid())
12469 .setMethod("getLastKnownCellIdentity")
12470 .setLogAsInfo(true)
12471 .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
12472 .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
12473 .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
12474 .build());
12475
12476 boolean hasFinePermission =
12477 fineLocationResult == LocationAccessPolicy.LocationPermissionResult.ALLOWED;
12478 if (!hasFinePermission
12479 || !TelephonyPermissions.checkLastKnownCellIdAccessPermission(mApp)) {
12480 throw new SecurityException("getLastKnownCellIdentity need ACCESS_FINE_LOCATION "
Rambo Wang918993a2022-04-27 09:08:36 -070012481 + "and ACCESS_LAST_KNOWN_CELL_ID permission.");
Sooraj Sasindranfae41b32021-10-26 02:10:05 -070012482 }
12483
12484 final long identity = Binder.clearCallingIdentity();
12485 try {
12486 Phone phone = getPhone(subId);
12487 if (phone == null) return null;
12488 ServiceStateTracker sst = phone.getServiceStateTracker();
12489 if (sst == null) return null;
12490 return sst.getLastKnownCellIdentity();
12491 } finally {
12492 Binder.restoreCallingIdentity(identity);
12493 }
12494 }
Jack Yu4c0a5502021-12-03 23:58:26 -080012495
jimsun3b9ccac2021-10-26 15:01:23 +080012496 /**
12497 * Sets the modem service class Name that Telephony will bind to.
12498 *
12499 * @param serviceName The class name of the modem service.
12500 * @return true if the operation is succeed, otherwise false.
12501 */
12502 public boolean setModemService(String serviceName) {
12503 Log.d(LOG_TAG, "setModemService - " + serviceName);
12504 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setModemService");
12505 TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012506 SubscriptionManager.INVALID_SUBSCRIPTION_ID,
12507 "setModemService");
jimsun3b9ccac2021-10-26 15:01:23 +080012508 return mPhoneConfigurationManager.setModemService(serviceName);
12509 }
12510
12511 /**
12512 * Return the class name of the currently bounded modem service.
12513 *
12514 * @return the class name of the modem service.
12515 */
12516 public String getModemService() {
12517 String result;
12518 Log.d(LOG_TAG, "getModemService");
12519 TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getModemService");
12520 TelephonyPermissions
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012521 .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
jimsun3b9ccac2021-10-26 15:01:23 +080012522 mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
12523 "getModemService");
12524 result = mPhoneConfigurationManager.getModemService();
12525 Log.d(LOG_TAG, "result = " + result);
12526 return result;
12527 }
Hunter Knepshield2b076fa2022-01-19 02:26:22 -080012528
12529 @Override
12530 public void setVoiceServiceStateOverride(int subId, boolean hasService, String callingPackage) {
12531 // Only telecom (and shell, for CTS purposes) is allowed to call this method.
12532 mApp.enforceCallingOrSelfPermission(
12533 permission.BIND_TELECOM_CONNECTION_SERVICE, "setVoiceServiceStateOverride");
12534 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12535
12536 final long identity = Binder.clearCallingIdentity();
12537 try {
12538 Phone phone = getPhone(subId);
12539 if (phone == null) return;
Grant Menke63ade122023-01-20 14:31:54 -080012540 Log.i(LOG_TAG, "setVoiceServiceStateOverride: subId=" + subId + ", phone=" + phone
12541 + ", hasService=" + hasService + ", callingPackage=" + callingPackage);
Hunter Knepshield2b076fa2022-01-19 02:26:22 -080012542 phone.setVoiceServiceStateOverride(hasService);
12543 } finally {
12544 Binder.restoreCallingIdentity(identity);
12545 }
12546 }
Muralidhar Reddy4e5a8012022-05-11 14:49:00 +000012547
12548 /**
12549 * set removable eSIM as default eUICC.
12550 *
12551 * @hide
12552 */
12553 @Override
12554 public void setRemovableEsimAsDefaultEuicc(boolean isDefault, String callingPackage) {
12555 enforceModifyPermission();
12556 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12557
12558 final long identity = Binder.clearCallingIdentity();
12559 try {
12560 UiccController.getInstance().setRemovableEsimAsDefaultEuicc(isDefault);
12561 } finally {
12562 Binder.restoreCallingIdentity(identity);
12563 }
12564 }
12565
12566 /**
12567 * Returns whether the removable eSIM is default eUICC or not.
12568 *
12569 * @hide
12570 */
12571 @Override
12572 public boolean isRemovableEsimDefaultEuicc(String callingPackage) {
12573 enforceReadPrivilegedPermission("isRemovableEsimDefaultEuicc");
12574 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
12575
12576 final long identity = Binder.clearCallingIdentity();
12577 try {
12578 return UiccController.getInstance().isRemovableEsimDefaultEuicc();
12579 } finally {
12580 Binder.restoreCallingIdentity(identity);
12581 }
12582 }
12583
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +000012584 /**
12585 * Get the component name of the default app to direct respond-via-message intent for the
12586 * user associated with this subscription, update the cache if there is no respond-via-message
12587 * application currently configured for this user.
12588 * @return component name of the app and class to direct Respond Via Message intent to, or
12589 * {@code null} if the functionality is not supported.
12590 * @hide
12591 */
12592 @Override
12593 public @Nullable ComponentName getDefaultRespondViaMessageApplication(int subId,
12594 boolean updateIfNeeded) {
12595 enforceInteractAcrossUsersPermission("getDefaultRespondViaMessageApplication");
Muralidhar Reddy4e5a8012022-05-11 14:49:00 +000012596
Aishwarya Mallampati5e581e12023-01-17 21:57:06 +000012597 Context context = getPhoneFromSubIdOrDefault(subId).getContext();
12598
Aishwarya Mallampatifbc70d32022-11-10 20:33:02 +000012599 UserHandle userHandle = null;
12600 final long identity = Binder.clearCallingIdentity();
12601 try {
12602 userHandle = TelephonyUtils.getSubscriptionUserHandle(context, subId);
12603 } finally {
12604 Binder.restoreCallingIdentity(identity);
12605 }
12606 return SmsApplication.getDefaultRespondViaMessageApplicationAsUser(context,
12607 updateIfNeeded, userHandle);
12608 }
Jack Yuf5badd92022-12-08 00:50:53 -080012609
12610 /**
Gil Cukierman1c0eb932022-12-06 22:28:24 +000012611 * Set whether the device is able to connect with null ciphering or integrity
12612 * algorithms. This is a global setting and will apply to all active subscriptions
12613 * and all new subscriptions after this.
12614 *
12615 * @param enabled when true, null cipher and integrity algorithms are allowed.
12616 * @hide
12617 */
12618 @Override
12619 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
12620 public void setNullCipherAndIntegrityEnabled(boolean enabled) {
12621 enforceModifyPermission();
12622 checkForNullCipherAndIntegritySupport();
12623
12624 // Persist the state of our preference. Each GsmCdmaPhone instance is responsible
12625 // for listening to these preference changes and applying them immediately.
12626 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
12627 editor.putBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, enabled);
12628 editor.apply();
12629
12630 for (Phone phone: PhoneFactory.getPhones()) {
12631 phone.handleNullCipherEnabledChange();
12632 }
12633 }
12634
12635
12636 /**
12637 * Get whether the device is able to connect with null ciphering or integrity
12638 * algorithms. Note that this retrieves the phone-global preference and not
12639 * the state of the radio.
12640 *
12641 * @throws SecurityException if {@link permission#MODIFY_PHONE_STATE} is not satisfied
12642 * @throws UnsupportedOperationException if the device does not support the minimum HAL
12643 * version for this feature.
12644 * @hide
12645 */
12646 @Override
12647 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
12648 public boolean isNullCipherAndIntegrityPreferenceEnabled() {
12649 enforceReadPermission();
12650 checkForNullCipherAndIntegritySupport();
12651 return getDefaultPhone().getNullCipherAndIntegrityEnabledPreference();
12652 }
12653
12654 private void checkForNullCipherAndIntegritySupport() {
12655 if (getHalVersion(HAL_SERVICE_NETWORK) < MIN_NULL_CIPHER_AND_INTEGRITY_VERSION) {
12656 throw new UnsupportedOperationException(
12657 "Null cipher and integrity operations require HAL 2.1 or above");
12658 }
Gil Cukierman92cc7db2023-01-06 19:25:53 +000012659 if (!getDefaultPhone().isNullCipherAndIntegritySupported()) {
12660 throw new UnsupportedOperationException(
12661 "Null cipher and integrity operations unsupported by modem");
12662 }
Gil Cukierman1c0eb932022-12-06 22:28:24 +000012663 }
12664
12665 /**
Jack Yuf5badd92022-12-08 00:50:53 -080012666 * Get the SIM state for the slot index.
12667 * For Remote-SIMs, this method returns {@link IccCardConstants.State#UNKNOWN}
12668 *
12669 * @return SIM state as the ordinal of {@link IccCardConstants.State}
12670 */
12671 @Override
12672 @SimState
12673 public int getSimStateForSlotIndex(int slotIndex) {
12674 IccCardConstants.State simState;
12675 if (slotIndex < 0) {
12676 simState = IccCardConstants.State.UNKNOWN;
12677 } else {
12678 Phone phone = null;
12679 try {
12680 phone = PhoneFactory.getPhone(slotIndex);
12681 } catch (IllegalStateException e) {
12682 // ignore
12683 }
12684 if (phone == null) {
12685 simState = IccCardConstants.State.UNKNOWN;
12686 } else {
12687 IccCard icc = phone.getIccCard();
12688 if (icc == null) {
12689 simState = IccCardConstants.State.UNKNOWN;
12690 } else {
12691 simState = icc.getState();
12692 }
12693 }
12694 }
12695 return simState.ordinal();
12696 }
Hui Wang9b5793a2022-12-05 14:38:06 -060012697
12698 /**
12699 * Get current cell broadcast ranges.
12700 */
12701 @Override
12702 @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
12703 public List<CellBroadcastIdRange> getCellBroadcastIdRanges(int subId) {
12704 mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
12705 "getCellBroadcastIdRanges");
12706 final long identity = Binder.clearCallingIdentity();
12707 try {
12708 return getPhone(subId).getCellBroadcastIdRanges();
12709 } finally {
12710 Binder.restoreCallingIdentity(identity);
12711 }
12712 }
12713
12714 /**
12715 * Set reception of cell broadcast messages with the list of the given ranges
12716 *
12717 * @param ranges the list of {@link CellBroadcastIdRange} to be enabled
12718 */
12719 @Override
12720 @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
12721 public void setCellBroadcastIdRanges(int subId, @NonNull List<CellBroadcastIdRange> ranges,
12722 @Nullable IIntegerConsumer callback) {
12723 mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
12724 "setCellBroadcastIdRanges");
12725 final long identity = Binder.clearCallingIdentity();
12726 try {
12727 Phone phone = getPhoneFromSubId(subId);
12728 if (DBG) {
12729 log("setCellBroadcastIdRanges for subId :" + subId + ", phone:" + phone);
12730 }
12731 phone.setCellBroadcastIdRanges(ranges, result -> {
12732 if (callback != null) {
12733 try {
12734 callback.accept(result);
12735 } catch (RemoteException e) {
12736 Log.w(LOG_TAG, "setCellBroadcastIdRanges: callback not available.");
12737 }
12738 }
12739 });
12740 } finally {
12741 Binder.restoreCallingIdentity(identity);
12742 }
12743 }
Hunsuk Choi42cc62a2022-10-16 06:03:40 +000012744
12745 /**
12746 * Returns whether the device supports the domain selection service.
12747 *
12748 * @return {@code true} if the device supports the domain selection service.
12749 */
12750 @Override
12751 public boolean isDomainSelectionSupported() {
12752 mApp.enforceCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
12753 "isDomainSelectionSupported");
12754
12755 final long identity = Binder.clearCallingIdentity();
12756 try {
12757 return DomainSelectionResolver.getInstance().isDomainSelectionSupported();
12758 } finally {
12759 Binder.restoreCallingIdentity(identity);
12760 }
12761 }
arunvoddud5c6ce02022-12-11 06:03:12 +000012762
12763 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012764 * Enable or disable the satellite modem. If the satellite modem is enabled, this will also
12765 * disable the cellular modem, and if the satellite modem is disabled, this will also re-enable
12766 * the cellular modem.
Sarah Chin503828c2023-02-01 23:54:20 -080012767 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012768 * @param subId The subId of the subscription to set satellite enabled for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012769 * @param enable {@code true} to enable the satellite modem and {@code false} to disable.
12770 * @param callback The callback to get the error code of the request.
Sarah Chin503828c2023-02-01 23:54:20 -080012771 *
12772 * @throws SecurityException if the caller doesn't have the required permission.
12773 */
12774 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012775 public void setSatelliteEnabled(int subId, boolean enable, @NonNull IIntegerConsumer callback) {
12776 enforceSatelliteCommunicationPermission("setSatelliteEnabled");
12777 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012778 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012779 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
12780 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012781 }
Sarah Chin503828c2023-02-01 23:54:20 -080012782
12783 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012784 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012785 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
12786 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012787 }
12788
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012789 Phone phone = getPhoneOrDefault(validSubId, "setSatelliteEnabled");
Sarah Chin503828c2023-02-01 23:54:20 -080012790 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012791 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
12792 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012793 }
12794
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012795 Pair<Boolean, Consumer<Integer>> arg = new Pair<>(enable, result);
12796 sendRequestAsync(CMD_SET_SATELLITE_ENABLED, arg, phone, null);
Sarah Chin503828c2023-02-01 23:54:20 -080012797 }
12798
12799 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012800 * Request to get whether the satellite modem is enabled.
Sarah Chin503828c2023-02-01 23:54:20 -080012801 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012802 * @param subId The subId of the subscription to check whether satellite is enabled for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012803 * @param result The result receiver that returns whether the satellite modem is enabled
12804 * if the request is successful or an error code if the request failed.
Sarah Chin503828c2023-02-01 23:54:20 -080012805 *
12806 * @throws SecurityException if the caller doesn't have the required permission.
12807 */
12808 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012809 public void requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result) {
12810 enforceSatelliteCommunicationPermission("requestIsSatelliteEnabled");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012811 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012812 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
12813 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012814 }
Sarah Chin503828c2023-02-01 23:54:20 -080012815
12816 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012817 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012818 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
12819 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012820 }
12821
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012822 Phone phone = getPhoneOrDefault(validSubId, "requestIsSatelliteEnabled");
Sarah Chin503828c2023-02-01 23:54:20 -080012823 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012824 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
12825 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012826 }
12827
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012828 sendRequest(CMD_IS_SATELLITE_ENABLED, result, subId);
Sarah Chin503828c2023-02-01 23:54:20 -080012829 }
12830
12831 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012832 * Request to get whether the satellite service is supported on the device.
Sarah Chin503828c2023-02-01 23:54:20 -080012833 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012834 * @param subId The subId of the subscription to check satellite service support for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012835 * @param result The result receiver that returns whether the satellite service is supported on
12836 * the device if the request is successful or an error code if the request failed.
Sarah Chin503828c2023-02-01 23:54:20 -080012837 */
12838 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012839 public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012840 synchronized (mIsSatelliteSupportedLock) {
12841 if (mIsSatelliteSupported != null) {
12842 /* We have already successfully queried the satellite modem. */
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012843 Bundle bundle = new Bundle();
12844 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported);
12845 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, bundle);
12846 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012847 }
12848 }
Sarah Chin503828c2023-02-01 23:54:20 -080012849
12850 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012851 Phone phone = getPhoneOrDefault(validSubId, "requestIsSatelliteSupported");
Sarah Chin503828c2023-02-01 23:54:20 -080012852 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012853 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
12854 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012855 }
12856
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012857 sendRequestAsync(CMD_IS_SATELLITE_SUPPORTED, result, phone, null);
Sarah Chin503828c2023-02-01 23:54:20 -080012858 }
12859
12860 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012861 * Request to get the {@link SatelliteCapabilities} of the satellite service.
Sarah Chin503828c2023-02-01 23:54:20 -080012862 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012863 * @param subId The subId of the subscription to get the satellite capabilities for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012864 * @param result The result receiver that returns the {@link SatelliteCapabilities}
12865 * if the request is successful or an error code if the request failed.
Sarah Chin503828c2023-02-01 23:54:20 -080012866 *
12867 * @throws SecurityException if the caller doesn't have required permission.
12868 */
12869 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012870 public void requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result) {
12871 enforceSatelliteCommunicationPermission("requestSatelliteCapabilities");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012872 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012873 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
12874 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012875 }
Sarah Chin503828c2023-02-01 23:54:20 -080012876
12877 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012878 Phone phone = getPhoneOrDefault(validSubId, "requestSatelliteCapabilities");
Sarah Chin503828c2023-02-01 23:54:20 -080012879 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012880 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
12881 return;
Sarah Chin503828c2023-02-01 23:54:20 -080012882 }
12883
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012884 sendRequestAsync(CMD_GET_SATELLITE_CAPABILITIES, result, phone, null);
Sarah Chin503828c2023-02-01 23:54:20 -080012885 }
12886
12887 /**
Sarah Chineccfbd12023-01-20 19:00:35 -080012888 * Start receiving satellite position updates.
12889 * This can be called by the pointing UI when the user starts pointing to the satellite.
12890 * Modem should continue to report the pointing input as the device or satellite moves.
12891 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012892 * @param subId The subId of the subscription to start satellite position updates for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012893 * @param errorCallback The callback to get the error code of the request.
Sarah Chineccfbd12023-01-20 19:00:35 -080012894 * @param callback The callback to notify of changes in satellite position.
Sarah Chin503828c2023-02-01 23:54:20 -080012895 *
12896 * @throws SecurityException if the caller doesn't have the required permission.
Sarah Chineccfbd12023-01-20 19:00:35 -080012897 */
12898 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012899 public void startSatellitePositionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012900 @NonNull ISatelliteStateListener callback) {
Sarah Chinf75afa72023-02-01 01:32:19 -080012901 enforceSatelliteCommunicationPermission("startSatellitePositionUpdates");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012902 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012903 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012904 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
12905 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012906 }
Sarah Chinf75afa72023-02-01 01:32:19 -080012907
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012908 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012909 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012910 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
12911 return;
Sarah Chinf75afa72023-02-01 01:32:19 -080012912 }
12913
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012914 Phone phone = getPhoneOrDefault(validSubId, "startSatellitePositionUpdates");
Sarah Chineccfbd12023-01-20 19:00:35 -080012915 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012916 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
12917 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012918 }
12919
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012920 if (mSatellitePositionUpdateHandlers.containsKey(callback.asBinder())) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012921 if (DBG) {
12922 log("startSatellitePositionUpdates: callback already registered: "
12923 + callback.asBinder());
12924 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012925 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
12926 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012927 }
12928
12929 SatellitePositionUpdateHandler handler =
12930 new SatellitePositionUpdateHandler(callback, Looper.getMainLooper());
12931 phone.registerForSatellitePointingInfoChanged(handler,
12932 SatellitePositionUpdateHandler.EVENT_POSITION_UPDATE, null);
12933 phone.registerForSatelliteMessagesTransferComplete(handler,
12934 SatellitePositionUpdateHandler.EVENT_MESSAGE_TRANSFER_STATE_UPDATE, null);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012935 mSatellitePositionUpdateHandlers.put(callback.asBinder(), handler);
Sarah Chineccfbd12023-01-20 19:00:35 -080012936
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012937 sendRequestAsync(CMD_START_SATELLITE_POSITION_UPDATES, result, phone, null);
Sarah Chineccfbd12023-01-20 19:00:35 -080012938 }
12939
12940 /**
12941 * Stop receiving satellite position updates.
12942 * This can be called by the pointing UI when the user stops pointing to the satellite.
12943 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012944 * @param subId The subId of the subscription to stop satellite position updates for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012945 * @param errorCallback The callback to get the error code of the request.
12946 * @param callback The callback that was passed to {@link
12947 * #startSatellitePositionUpdates(int, IIntegerConsumer, ISatelliteStateListener)}
Sarah Chin503828c2023-02-01 23:54:20 -080012948 *
12949 * @throws SecurityException if the caller doesn't have the required permission.
Sarah Chineccfbd12023-01-20 19:00:35 -080012950 */
12951 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012952 public void stopSatellitePositionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012953 @NonNull ISatelliteStateListener callback) {
Sarah Chinf75afa72023-02-01 01:32:19 -080012954 enforceSatelliteCommunicationPermission("stopSatellitePositionUpdates");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012955 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(errorCallback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012956 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012957 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
12958 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012959 }
Sarah Chinf75afa72023-02-01 01:32:19 -080012960
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012961 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080012962 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012963 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
12964 return;
Sarah Chinf75afa72023-02-01 01:32:19 -080012965 }
12966
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012967 Phone phone = getPhoneOrDefault(validSubId, "stopSatellitePositionUpdates");
Sarah Chineccfbd12023-01-20 19:00:35 -080012968 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012969 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
12970 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012971 }
12972
12973 SatellitePositionUpdateHandler handler =
Thomas Nguyen8ee49682023-02-01 11:46:09 -080012974 mSatellitePositionUpdateHandlers.remove(callback.asBinder());
Sarah Chineccfbd12023-01-20 19:00:35 -080012975 if (handler == null) {
Sarah Chindf715ec2023-02-13 13:46:24 -080012976 loge("stopSatellitePositionUpdates: No SatellitePositionUpdateHandler");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012977 result.accept(SatelliteManager.SATELLITE_INVALID_ARGUMENTS);
12978 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012979 } else {
12980 phone.unregisterForSatellitePointingInfoChanged(handler);
12981 phone.unregisterForSatelliteMessagesTransferComplete(handler);
12982 }
12983
12984 if (!mSatellitePositionUpdateHandlers.isEmpty()) {
12985 log("stopSatellitePositionUpdates: other listeners still exist.");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012986 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
12987 return;
Sarah Chineccfbd12023-01-20 19:00:35 -080012988 }
12989
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012990 sendRequestAsync(CMD_STOP_SATELLITE_POSITION_UPDATES, result, phone, null);
Sarah Chineccfbd12023-01-20 19:00:35 -080012991 }
12992
12993 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012994 * Request to get the maximum number of characters per text message on satellite.
12995 *
Sarah Chindf715ec2023-02-13 13:46:24 -080012996 * @param subId The subId of the subscription to get the maximum number of characters for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080012997 * @param result The result receiver that returns the maximum number of characters per text
12998 * message on satellite if the request is successful or an error code
12999 * if the request failed.
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013000 *
13001 * @throws SecurityException if the caller doesn't have the required permission.
13002 */
13003 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013004 public void requestMaxCharactersPerSatelliteTextMessage(int subId,
13005 @NonNull ResultReceiver result) {
13006 enforceSatelliteCommunicationPermission("requestMaxCharactersPerSatelliteTextMessage");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013007 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013008 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13009 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013010 }
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013011
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013012 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013013 if (!isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013014 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
13015 return;
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013016 }
13017
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013018 Phone phone = getPhoneOrDefault(validSubId, "requestMaxCharactersPerSatelliteTextMessage");
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013019 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013020 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
13021 return;
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013022 }
13023
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013024 sendRequestAsync(CMD_GET_MAX_CHAR_PER_SATELLITE_TEXT_MSG, result, phone, null);
Aishwarya Mallampati60fe1132023-01-24 19:07:21 +000013025 }
13026
13027 /**
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013028 * Register the subscription with a satellite provider.
13029 * This is needed to register the subscription if the provider allows dynamic registration.
13030 *
13031 * @param subId The subId of the subscription to be provisioned.
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013032 * @param token The token to be used as a unique identifier for provisioning with satellite
13033 * gateway.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013034 * @param callback The callback to get the error code of the request.
Sarah Chindf715ec2023-02-13 13:46:24 -080013035 *
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013036 * @return The signal transport used by the caller to cancel the provision request,
13037 * or {@code null} if the request failed.
13038 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013039 * @throws SecurityException if the caller doesn't have the required permission.
13040 */
13041 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013042 @Nullable public ICancellationSignal provisionSatelliteService(int subId,
13043 @NonNull String token, @NonNull IIntegerConsumer callback) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013044 enforceSatelliteCommunicationPermission("provisionSatelliteService");
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013045 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013046 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013047 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013048 return null;
13049 }
13050
13051 final int validSubId = getValidSatelliteSubId(subId);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013052 Phone phone = getPhoneOrDefault(validSubId, "provisionSatelliteService");
13053 if (phone == null) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013054 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013055 return null;
13056 }
13057
13058 if (mSatelliteProvisionCallbacks.containsKey(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013059 result.accept(SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013060 return null;
13061 }
13062
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013063 if (isSatelliteProvisioned(validSubId)) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013064 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013065 return null;
13066 }
13067
13068 sendRequestAsync(CMD_PROVISION_SATELLITE_SERVICE,
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013069 new ProvisionSatelliteServiceArgument(token, result, validSubId), phone, null);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013070
13071 ICancellationSignal cancelTransport = CancellationSignal.createTransport();
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013072 CancellationSignal.fromTransport(cancelTransport).setOnCancelListener(() -> {
13073 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
13074 new ProvisionSatelliteServiceArgument(token, null, validSubId),
13075 phone, null);
13076 });
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013077 return cancelTransport;
13078 }
13079
13080 /**
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013081 * Unregister the device/subscription with the satellite provider.
13082 * This is needed if the provider allows dynamic registration. Once deprovisioned,
13083 * {@link SatelliteCallback.SatelliteProvisionStateListener#onSatelliteProvisionStateChanged}
13084 * should report as deprovisioned.
13085 *
13086 * @param subId The subId of the subscription to be deprovisioned.
13087 * @param token The token of the device/subscription to be deprovisioned.
13088 * @param callback The callback to get the error code of the request.
13089 *
13090 * @throws SecurityException if the caller doesn't have the required permission.
13091 */
13092 @Override
13093 public void deprovisionSatelliteService(int subId,
13094 @NonNull String token, @NonNull IIntegerConsumer callback) {
13095 enforceSatelliteCommunicationPermission("deprovisionSatelliteService");
13096 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
13097 if (!isSatelliteSupported()) {
13098 result.accept(SatelliteManager.SATELLITE_NOT_SUPPORTED);
13099 return;
13100 }
13101
13102 final int validSubId = getValidSatelliteSubId(subId);
13103 if (!isSatelliteProvisioned(validSubId)) {
13104 result.accept(SatelliteManager.SATELLITE_ERROR_NONE);
13105 return;
13106 }
13107
13108 Phone phone = getPhoneOrDefault(validSubId, "deprovisionSatelliteService");
13109 if (phone == null) {
13110 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13111 return;
13112 }
13113
13114 sendRequestAsync(CMD_DEPROVISION_SATELLITE_SERVICE,
13115 new ProvisionSatelliteServiceArgument(token, result, validSubId), phone, null);
13116 }
13117
13118 /**
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013119 * Register for the satellite provision state change.
13120 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013121 * @param subId The subId of the subscription to register for provision state changes.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013122 * @param callback The callback to handle the satellite provision state changed event.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013123 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013124 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13125 *
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 registerForSatelliteProvisionStateChanged(int subId,
13130 @NonNull ISatelliteStateListener callback) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013131 enforceSatelliteCommunicationPermission("registerForSatelliteProvisionStateChanged");
Sarah Chindf715ec2023-02-13 13:46:24 -080013132 return registerForSatelliteProvisionStateChangedInternal(subId, callback);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013133 }
13134
13135 /**
13136 * Unregister for the satellite provision state change.
13137 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013138 * @param subId The subId of the subscription to unregister for provision state changes.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013139 * @param errorCallback The callback to get the error code of the request.
13140 * @param callback The callback that was passed to {@link
Sarah Chindf715ec2023-02-13 13:46:24 -080013141 * #registerForSatelliteProvisionStateChanged(int, ISatelliteStateListener)}.
13142 *
13143 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013144 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013145 * @throws SecurityException if the caller doesn't have the required permission.
13146 */
13147 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013148 @SatelliteManager.SatelliteError public int unregisterForSatelliteProvisionStateChanged(
13149 int subId, @NonNull ISatelliteStateListener callback) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013150 enforceSatelliteCommunicationPermission("unregisterForSatelliteProvisionStateChanged");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013151 if (!isSatelliteSupported()) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013152 return SatelliteManager.SATELLITE_NOT_SUPPORTED;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013153 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013154
13155 final int validSubId = getValidSatelliteSubId(subId);
13156 SatelliteProvisionStateChangedHandler satelliteProvisionStateChangedHandler =
13157 mSatelliteProvisionStateChangedHandlers.get(validSubId);
13158 if (satelliteProvisionStateChangedHandler != null) {
13159 if (satelliteProvisionStateChangedHandler.removeListener(callback)) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013160 return SatelliteManager.SATELLITE_ERROR_NONE;
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013161 }
13162 }
Sarah Chindf715ec2023-02-13 13:46:24 -080013163 return SatelliteManager.SATELLITE_INVALID_ARGUMENTS;
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013164 }
13165
13166 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013167 * Request to get whether the device is provisioned with a satellite provider.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013168 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013169 * @param subId The subId of the subscription to get whether the device is provisioned for.
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013170 * @param result The result receiver that returns whether the device is provisioned with a
13171 * satellite provider if the request is successful or an error code if the
13172 * request failed.
13173 *
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013174 * @throws SecurityException if the caller doesn't have the required permission.
13175 */
13176 @Override
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013177 public void requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result) {
13178 enforceSatelliteCommunicationPermission("requestIsSatelliteProvisioned");
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013179 if (!isSatelliteSupported()) {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013180 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13181 return;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013182 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013183
13184 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013185 Bundle bundle = new Bundle();
13186 bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED,
13187 isSatelliteProvisioned(validSubId));
13188 result.send(SatelliteManager.SATELLITE_ERROR_NONE, bundle);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013189 }
13190
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013191 /**
13192 * Register for listening to satellite state changes.
13193 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013194 * @param subId The subId of the subscription to register for satellite modem state changes.
13195 * @param callback The callback to handle the satellite state change event.
13196 *
13197 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13198 *
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013199 * @throws SecurityException if the caller doesn't have the required permission.
13200 */
13201 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013202 @SatelliteManager.SatelliteError public int registerForSatelliteModemStateChange(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013203 @NonNull ISatelliteStateListener callback) {
13204 enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChange");
13205
13206 final int validSubId = getValidSatelliteSubId(subId);
13207 Phone phone = getPhoneOrDefault(
13208 validSubId, "registerForSatelliteModemStateChange");
13209 if (phone == null) {
13210 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13211 }
13212
13213 SatelliteStateListenerHandler satelliteStateListenerHandler =
13214 mSatelliteStateListenerHandlers.get(validSubId);
13215 if (satelliteStateListenerHandler == null) {
13216 satelliteStateListenerHandler = new SatelliteStateListenerHandler(
13217 Looper.getMainLooper(), validSubId);
13218 phone.registerForSatelliteModemStateChange(satelliteStateListenerHandler,
13219 SatelliteStateListenerHandler.EVENT_SATELLITE_MODEM_STATE_CHANGE, null);
13220 phone.registerForPendingMessageCount(satelliteStateListenerHandler,
13221 SatelliteStateListenerHandler.EVENT_PENDING_MESSAGE_COUNT, null);
13222 }
13223
13224 satelliteStateListenerHandler.addListener(callback);
13225 mSatelliteStateListenerHandlers.put(validSubId, satelliteStateListenerHandler);
13226 return SatelliteManager.SATELLITE_ERROR_NONE;
13227 }
13228
13229 /**
13230 * Unregister from listening to satellite state changes.
13231 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013232 * @param subId The subId of the subscription to unregister for satellite modem state changes.
13233 * @param callback The callback that was passed to
13234 * {@link #registerForSatelliteModemStateChange(int, ISatelliteStateListener)}.
13235 *
13236 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013237 *
13238 * @throws SecurityException if the caller doesn't have the required permission.
13239 */
13240 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013241 @SatelliteManager.SatelliteError public int unregisterForSatelliteModemStateChange(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013242 @NonNull ISatelliteStateListener callback) {
13243 enforceSatelliteCommunicationPermission("unregisterForSatelliteModemStateChange");
13244
13245 final int validSubId = getValidSatelliteSubId(subId);
13246 SatelliteStateListenerHandler satelliteStateListenerHandler =
13247 mSatelliteStateListenerHandlers.get(validSubId);
13248 if (satelliteStateListenerHandler != null) {
13249 if (satelliteStateListenerHandler.removeListener(callback)) {
13250 return SatelliteManager.SATELLITE_ERROR_NONE;
13251 }
13252 }
13253 return SatelliteManager.SATELLITE_INVALID_ARGUMENTS;
13254 }
13255
13256 /**
13257 * Register to receive incoming datagrams over satellite.
13258 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013259 * @param subId The subId of the subscription to register for incoming satellite datagrams.
13260 * @param datagramType Type of datagram.
13261 * @param callback The callback to handle incoming datagrams over satellite.
13262 *
13263 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13264 *
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013265 * @throws SecurityException if the caller doesn't have the required permission.
13266 */
13267 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013268 @SatelliteManager.SatelliteError public int registerForSatelliteDatagram(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013269 @SatelliteManager.DatagramType int datagramType,
13270 @NonNull ISatelliteStateListener callback) {
13271 enforceSatelliteCommunicationPermission("registerForSatelliteDatagram");
13272
13273 final int validSubId = getValidSatelliteSubId(subId);
Sarah Chindf715ec2023-02-13 13:46:24 -080013274 Phone phone = getPhoneOrDefault(validSubId, "registerForSatelliteDatagram");
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013275 if (phone == null) {
13276 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13277 }
13278
13279 SatelliteDatagramListenerHandler satelliteDatagramListenerHandler =
13280 mSatelliteDatagramListenerHandlers.get(validSubId);
13281 if (satelliteDatagramListenerHandler == null) {
13282 satelliteDatagramListenerHandler = new SatelliteDatagramListenerHandler(
13283 Looper.getMainLooper(), validSubId);
13284 phone.registerForNewSatelliteDatagram(satelliteDatagramListenerHandler,
13285 SatelliteDatagramListenerHandler.EVENT_SATELLITE_DATAGRAMS_RECEIVED, null);
13286 }
13287
13288 satelliteDatagramListenerHandler.addListener(callback);
13289 mSatelliteDatagramListenerHandlers.put(validSubId, satelliteDatagramListenerHandler);
13290 return SatelliteManager.SATELLITE_ERROR_NONE;
13291 }
13292
13293 /**
13294 * Unregister to stop receiving incoming datagrams over satellite.
13295 *
Sarah Chindf715ec2023-02-13 13:46:24 -080013296 * @param subId The subId of the subscription to unregister for incoming satellite datagrams.
13297 * @param callback The callback that was passed to
13298 * {@link #registerForSatelliteDatagram(int, int, ISatelliteStateListener)}.
13299 *
13300 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013301 *
13302 * @throws SecurityException if the caller doesn't have the required permission.
13303 */
13304 @Override
Sarah Chindf715ec2023-02-13 13:46:24 -080013305 @SatelliteManager.SatelliteError public int unregisterForSatelliteDatagram(int subId,
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013306 @NonNull ISatelliteStateListener callback) {
13307 enforceSatelliteCommunicationPermission("unregisterForSatelliteDatagram");
13308
13309 final int validSubId = getValidSatelliteSubId(subId);
13310 SatelliteDatagramListenerHandler satelliteDatagramListenerHandler =
13311 mSatelliteDatagramListenerHandlers.get(validSubId);
13312 if (satelliteDatagramListenerHandler != null) {
13313 if (satelliteDatagramListenerHandler.removeListener(callback)) {
13314 return SatelliteManager.SATELLITE_ERROR_NONE;
13315 }
13316 }
13317 return SatelliteManager.SATELLITE_INVALID_ARGUMENTS;
13318 }
13319
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013320 /**
13321 * Poll pending satellite datagrams over satellite.
Sarah Chindf715ec2023-02-13 13:46:24 -080013322 *
13323 * @param subId The subId of the subscription to poll pending satellite datagrams for.
13324 *
13325 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
13326 *
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013327 * @throws SecurityException if the caller doesn't have the required permission.
13328 */
Sarah Chindf715ec2023-02-13 13:46:24 -080013329 @Override @SatelliteManager.SatelliteError public int pollPendingSatelliteDatagrams(int subId) {
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013330 enforceSatelliteCommunicationPermission("pollPendingSatelliteDatagrams");
13331
13332 final int validSubId = getValidSatelliteSubId(subId);
13333 if (!isSatelliteProvisioned(validSubId)) {
13334 return SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED;
13335 }
13336
13337 Phone phone = getPhoneOrDefault(validSubId, "pollPendingSatelliteDatagrams");
13338 if (phone == null) {
13339 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13340 }
13341
13342 int result = (int) sendRequest(CMD_POLL_PENDING_SATELLITE_DATAGRAMS, null, validSubId);
13343 if (DBG) log("pollPendingSatelliteDatagrams result: " + result);
13344 return result;
13345 }
13346
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +000013347 /**
13348 * Send datagram over satellite.
Sarah Chindf715ec2023-02-13 13:46:24 -080013349 *
13350 * @param subId The subId of the subscription to send satellite datagrams for.
13351 * @param datagramType Type of datagram.
13352 * @param datagram Datagram to send over satellite.
13353 * @param callback The callback to get the error code of the request.
13354 *
Aishwarya Mallampatie8ac6862023-02-09 22:13:02 +000013355 * @throws SecurityException if the caller doesn't have the required permission.
13356 */
13357 @Override
13358 public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
13359 SatelliteDatagram datagram, IIntegerConsumer callback) {
13360 enforceSatelliteCommunicationPermission("sendSatelliteDatagram");
13361 Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
13362
13363 final int validSubId = getValidSatelliteSubId(subId);
13364 if (!isSatelliteProvisioned(validSubId)) {
13365 result.accept(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED);
13366 return;
13367 }
13368
13369 Phone phone = getPhoneOrDefault(validSubId, "sendSatelliteDatagram");
13370 if (phone == null) {
13371 result.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13372 return;
13373 }
13374
13375 // check if we need to start PointingUI.
13376
13377 sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM,
13378 new SendSatelliteDatagramArgument(datagramType, datagram, result),
13379 phone, null);
13380 }
13381
Sarah Chindf715ec2023-02-13 13:46:24 -080013382 /**
13383 * Request to get whether satellite communication is allowed for the current location.
13384 *
13385 * @param subId The subId of the subscription to check whether satellite communication is
13386 * allowed for the current location for.
13387 * @param result The result receiver that returns whether satellite communication is allowed
13388 * for the current location if the request is successful or an error code
13389 * if the request failed.
13390 *
13391 * @throws SecurityException if the caller doesn't have the required permission.
13392 */
13393 @Override
13394 public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId,
13395 @NonNull ResultReceiver result) {
13396 enforceSatelliteCommunicationPermission(
13397 "requestIsSatelliteCommunicationAllowedForCurrentLocation");
13398 if (!isSatelliteSupported()) {
13399 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13400 return;
13401 }
13402
13403 final int validSubId = getValidSatelliteSubId(subId);
13404 if (!isSatelliteProvisioned(validSubId)) {
13405 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
13406 return;
13407 }
13408
13409 Phone phone = getPhoneOrDefault(validSubId,
13410 "requestIsSatelliteCommunicationAllowedForCurrentLocation");
13411 if (phone == null) {
13412 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
13413 return;
13414 }
13415
13416 sendRequest(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED, result, subId);
13417 }
13418
13419 /**
13420 * Request to get the time after which the satellite will next be visible
13421 *
13422 * @param subId The subId to get the time after which the satellite will next be visible for.
13423 * @param result The result receiver that returns the time after which the satellite will next
13424 * be visible if the request is successful or an error code if the request failed.
13425 *
13426 * @throws SecurityException if the caller doesn't have the required permission.
13427 */
13428 @Override
13429 public void requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result) {
13430 enforceSatelliteCommunicationPermission("requestTimeForNextSatelliteVisibility");
13431 if (!isSatelliteSupported()) {
13432 result.send(SatelliteManager.SATELLITE_NOT_SUPPORTED, null);
13433 return;
13434 }
13435
13436 final int validSubId = getValidSatelliteSubId(subId);
13437 if (!isSatelliteProvisioned(validSubId)) {
13438 result.send(SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED, null);
13439 return;
13440 }
13441
13442 Phone phone = getPhoneOrDefault(validSubId, "requestTimeForNextSatelliteVisibility");
13443 if (phone == null) {
13444 result.send(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE, null);
13445 return;
13446 }
13447
13448 sendRequestAsync(CMD_GET_TIME_SATELLITE_NEXT_VISIBLE, result, phone, null);
13449 }
13450
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013451 private void handleCmdProvisionSatelliteService(@NonNull ProvisionSatelliteServiceArgument arg,
13452 @NonNull Phone phone, Message onCompleted) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013453 if (!mSatelliteProvisionCallbacks.containsKey(arg.subId)) {
13454 mSatelliteProvisionCallbacks.put(arg.subId, arg.callback);
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013455 phone.provisionSatelliteService(onCompleted, arg.token);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013456 } else {
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013457 arg.callback.accept(SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013458 }
13459 }
13460
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013461 private void handleEventProvisionSatelliteServiceDone(
13462 @NonNull ProvisionSatelliteServiceArgument arg,
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013463 @SatelliteManager.SatelliteError int result) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013464 log("handleEventProvisionSatelliteServiceDone: result="
13465 + result + ", subId=" + arg.subId);
13466
13467 Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013468 if (callback == null) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013469 loge("handleEventProvisionSatelliteServiceDone: callback is null for subId="
13470 + arg.subId);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013471 return;
13472 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013473 callback.accept(result);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013474
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013475 if (result == SatelliteManager.SATELLITE_ERROR_NONE) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013476 setSatelliteProvisioned(arg.subId, true);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013477 }
13478
13479 /**
13480 * We need to update satellite provision status in SubscriptionController
13481 * or SatelliteController.
13482 * TODO (b/267826133) we need to do this for all subscriptions on the device.
13483 */
Sarah Chindf715ec2023-02-13 13:46:24 -080013484 registerForSatelliteProvisionStateChangedInternal(arg.subId, null);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013485 }
13486
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013487 private void handleCmdDeprovisionSatelliteService(
Sarah Chindf715ec2023-02-13 13:46:24 -080013488 @NonNull ProvisionSatelliteServiceArgument arg, @NonNull Phone phone,
13489 @NonNull Message onCompleted) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013490 if (arg == null) {
13491 loge("handleCmdDeprovisionSatelliteService: arg is null");
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013492 return;
13493 }
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013494 if (phone == null) {
13495 loge("handleCmdDeprovisionSatelliteService: phone is null");
13496 if (arg.callback != null) {
13497 arg.callback.accept(SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE);
13498 }
13499 return;
13500 }
13501 phone.deprovisionSatelliteService(onCompleted, arg.token);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013502 }
13503
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013504 private void handleEventDeprovisionSatelliteServiceDone(
13505 @NonNull ProvisionSatelliteServiceArgument arg,
13506 @SatelliteManager.SatelliteError int result) {
13507 if (arg == null) {
13508 loge("handleEventDeprovisionSatelliteServiceDone: arg is null");
13509 return;
13510 }
13511 log("handleEventDeprovisionSatelliteServiceDone: result="
13512 + result + ", subId=" + arg.subId);
13513
13514 if (arg.callback != null) {
13515 arg.callback.accept(result);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013516 }
13517
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013518 if (result == SatelliteManager.SATELLITE_ERROR_NONE) {
13519 setSatelliteProvisioned(arg.subId, false);
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013520 }
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013521 }
13522
13523 private Phone getPhoneOrDefault(int subId, String caller) {
13524 Phone phone = getPhone(subId);
13525 if (phone == null) {
13526 loge(caller + " called with invalid subId: " + subId
13527 + ". Retrying with default phone.");
13528 phone = getDefaultPhone();
13529 if (phone == null) {
13530 loge(caller + " failed with no phone object.");
13531 }
13532 }
13533 return phone;
13534 }
13535
13536 /**
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013537 * Check if satellite is provisioned for a subscription or the device.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013538 *
13539 * Note: this is the version without permission check for telephony internal use only. The
13540 * caller need to take care of the permission check.
13541 */
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013542 private boolean isSatelliteProvisioned(int subId) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013543 if (subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
13544 if (mSubscriptionController == null) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013545 loge("isSatelliteProvisioned mSubscriptionController is null");
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013546 return false;
13547 }
13548
13549 String strResult = mSubscriptionController.getSubscriptionProperty(
13550 subId, SubscriptionManager.SATELLITE_ENABLED);
13551 if (strResult != null) {
13552 int intResult = Integer.parseInt(strResult);
13553 return (intResult == 1) ? true : false;
13554 }
13555 } else {
13556 //TODO (b/267826133): check via SatelliteController
13557 }
13558 return false;
13559 }
13560
13561 /**
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013562 * Set satellite provisioned for a subscription or the device.
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013563 *
13564 * The permission {@link android.Manifest.permission#MODIFY_PHONE_STATE} will be enforced by
13565 * {@link SubscriptionController} when setting satellite enabled for an active subscription.
13566 * Otherwise, {@link android.Manifest.permission#SATELLITE_COMMUNICATION} will be enforced.
13567 */
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013568 private synchronized void setSatelliteProvisioned(int subId, boolean isEnabled) {
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013569 if (subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
13570 if (mSubscriptionController == null) {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013571 loge("setSatelliteProvisioned mSubscriptionController is null");
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013572 return;
13573 }
13574 mSubscriptionController.setSubscriptionProperty(
13575 subId, SubscriptionManager.SATELLITE_ENABLED, isEnabled ? "1" : "0");
13576 } else {
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013577 //TODO (b/267826133): set via SatelliteController
Thomas Nguyen8ee49682023-02-01 11:46:09 -080013578 }
13579 }
13580
13581 private int getValidSatelliteSubId(int subId) {
13582 if (mSubscriptionController == null) {
13583 loge("getValidSatelliteSubId mSubscriptionController is null. "
13584 + "Use DEFAULT_SUBSCRIPTION_ID for subId=" + subId);
13585 return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
13586 }
13587 final long identity = Binder.clearCallingIdentity();
13588 try {
13589 Context context = getDefaultPhone().getContext();
13590 if (mSubscriptionController.isActiveSubId(
13591 subId, context.getOpPackageName(), context.getAttributionTag())) {
13592 return subId;
13593 }
13594 } finally {
13595 Binder.restoreCallingIdentity(identity);
13596 }
13597 if (DBG) log("getValidSatelliteSubId: use DEFAULT_SUBSCRIPTION_ID for subId=" + subId);
13598 return SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
13599 }
13600
13601 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013602 * If we have not successfully queried the satellite modem for its satellite service support,
13603 * we will retry the query one more time. Otherwise, we will return the queried result.
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013604 */
13605 private boolean isSatelliteSupported() {
13606 synchronized (mIsSatelliteSupportedLock) {
13607 if (mIsSatelliteSupported != null) {
13608 /* We have already successfully queried the satellite modem. */
13609 return mIsSatelliteSupported;
13610 }
13611 }
13612 /**
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013613 * We have not successfully checked whether the modem supports satellite service.
13614 * Thus, we need to retry it now.
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013615 */
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013616 requestIsSatelliteSupported(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
13617 mSatelliteSupportedReceiver);
13618 return false;
13619 }
13620
13621 /**
13622 * Get the {@link SatelliteManager.SatelliteError} from the provided result.
Sarah Chindf715ec2023-02-13 13:46:24 -080013623 *
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013624 * @param ar AsyncResult used to determine the error code.
13625 * @param caller The satellite request.
13626 * @param checkResult Whether to check if the result exists.
Sarah Chindf715ec2023-02-13 13:46:24 -080013627 *
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013628 * @return The {@link SatelliteManager.SatelliteError} error code from the request.
13629 */
13630 @SatelliteManager.SatelliteError private int getSatelliteError(@NonNull AsyncResult ar,
13631 @NonNull String caller, boolean checkResult) {
13632 int errorCode;
13633 if (ar.exception == null) {
13634 errorCode = SatelliteManager.SATELLITE_ERROR_NONE;
13635 if (checkResult && ar.result == null) {
13636 loge(caller + ": result is null");
13637 errorCode = SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
13638 }
13639 } else {
13640 errorCode = SatelliteManager.SATELLITE_ERROR;
13641 if (ar.exception instanceof CommandException) {
13642 CommandException.Error error =
13643 ((CommandException) (ar.exception)).getCommandError();
13644 errorCode = RILUtils.convertToSatelliteError(error);
13645 loge(caller + " CommandException: " + ar.exception);
13646 } else {
13647 loge(caller + " unknown exception: " + ar.exception);
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013648 }
13649 }
Sarah Chin4a9e8b82023-02-10 21:10:57 -080013650 log(caller + " error: " + errorCode);
13651 return errorCode;
Thomas Nguyene77de6d2023-02-10 17:42:43 -080013652 }
13653
13654 /**
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013655 * Register for the satellite provision state change.
13656 *
13657 * @param subId The subId of the subscription associated with the satellite service.
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013658 * @param callback The callback to handle the satellite provision state changed event.
Sarah Chindf715ec2023-02-13 13:46:24 -080013659 *
13660 * @return The {@link SatelliteManager.SatelliteError} result of the operation.
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013661 */
Sarah Chindf715ec2023-02-13 13:46:24 -080013662 @SatelliteManager.SatelliteError private int registerForSatelliteProvisionStateChangedInternal(
13663 int subId, @Nullable ISatelliteStateListener callback) {
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013664 if (!isSatelliteSupported()) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013665 return SatelliteManager.SATELLITE_NOT_SUPPORTED;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013666 }
13667
13668 final int validSubId = getValidSatelliteSubId(subId);
13669 Phone phone = getPhoneOrDefault(validSubId, "registerForSatelliteProvisionStateChanged");
13670 if (phone == null) {
Sarah Chindf715ec2023-02-13 13:46:24 -080013671 return SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013672 }
13673
13674 SatelliteProvisionStateChangedHandler satelliteProvisionStateChangedHandler =
13675 mSatelliteProvisionStateChangedHandlers.get(validSubId);
13676 if (satelliteProvisionStateChangedHandler == null) {
13677 satelliteProvisionStateChangedHandler = new SatelliteProvisionStateChangedHandler(
13678 Looper.getMainLooper(), validSubId);
13679 phone.registerForSatelliteProvisionStateChanged(satelliteProvisionStateChangedHandler,
13680 SatelliteProvisionStateChangedHandler.EVENT_PROVISION_STATE_CHANGED, null);
13681 }
13682
13683 if (callback != null) {
13684 satelliteProvisionStateChangedHandler.addListener(callback);
13685 }
13686 mSatelliteProvisionStateChangedHandlers.put(
13687 validSubId, satelliteProvisionStateChangedHandler);
Sarah Chindf715ec2023-02-13 13:46:24 -080013688 return SatelliteManager.SATELLITE_ERROR_NONE;
Thomas Nguyen4a29b8e2023-02-13 09:26:15 -080013689 }
13690
13691 /**
arunvoddud5c6ce02022-12-11 06:03:12 +000013692 * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
13693 *
13694 * <p>This method behaves in one of the following ways:
13695 * <ul>
13696 * <li>return true : if the calling package has the appop permission {@link
13697 * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} in the manifest </>
13698 * <li>return true : if any one subscription has the READ_PRIVILEGED_PHONE_STATE
13699 * permission, the calling package passes a DevicePolicyManager Device Owner / Profile
13700 * Owner device identifier access check, or the calling package has carrier privileges</>
13701 * <li>throw SecurityException: if the caller does not meet any of the requirements.
13702 * </ul>
13703 */
13704 private static boolean checkCallingOrSelfReadDeviceIdentifiersForAnySub(Context context,
13705 String callingPackage, @Nullable String callingFeatureId, String message) {
13706 for (Phone phone : PhoneFactory.getPhones()) {
13707 if (TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(context,
13708 phone.getSubId(), callingPackage, callingFeatureId, message)) {
13709 return true;
13710 }
13711 }
13712 return false;
13713 }
arunvoddud7401012022-12-15 16:08:12 +000013714
13715 /**
Jack Yufa8ed012023-02-11 15:42:28 -080013716 * @return The subscription manager service instance.
13717 */
13718 public SubscriptionManagerService getSubscriptionManagerService() {
13719 return SubscriptionManagerService.getInstance();
13720 }
13721
13722 /**
arunvoddud7401012022-12-15 16:08:12 +000013723 * Class binds the consumer[callback] and carrierId.
13724 */
13725 private static class CallerCallbackInfo {
13726 private final Consumer<Integer> mConsumer;
13727 private final int mCarrierId;
13728
13729 public CallerCallbackInfo(Consumer<Integer> consumer, int carrierId) {
13730 mConsumer = consumer;
13731 mCarrierId = carrierId;
13732 }
13733
13734 public Consumer<Integer> getConsumer() {
13735 return mConsumer;
13736 }
13737
13738 public int getCarrierId() {
13739 return mCarrierId;
13740 }
13741 }
Aishwarya Mallampati740d9ab2023-02-08 23:07:05 +000013742
13743 private static SatelliteDatagram[] convertToSatelliteDatagramArray(byte[][] datagrams) {
13744 // Convert 2D byte array into SatelliteDatagramArray.
13745 SatelliteDatagram[] satelliteDatagramArray =
13746 new SatelliteDatagram[datagrams.length];
13747 for (int i = 0; i < datagrams.length; i++) {
13748 satelliteDatagramArray[i] = new SatelliteDatagram(datagrams[i]);
13749 }
13750 return satelliteDatagramArray;
13751 }
Jack Yufa8ed012023-02-11 15:42:28 -080013752}