blob: 7e64b696a6d7e1ea2f634874563bb82bde0fa0fa [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
Ta-wei Yen87c49842016-05-13 21:19:52 -070019import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
20
Santos Cordon7d4ddf62013-07-10 11:58:08 -070021import android.app.ActivityManager;
22import android.app.AppOpsManager;
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -070023import android.content.ComponentName;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070024import android.content.Context;
25import android.content.Intent;
Derek Tan97ebb422014-09-05 16:55:38 -070026import android.content.SharedPreferences;
Amith Yamasani6e118872016-02-19 12:53:51 -080027import android.content.pm.PackageInfo;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070028import android.content.pm.PackageManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070029import android.net.Uri;
30import android.os.AsyncResult;
31import android.os.Binder;
32import android.os.Bundle;
33import android.os.Handler;
34import android.os.Looper;
35import android.os.Message;
36import android.os.Process;
Adam Lesinski903a54c2016-04-11 14:49:52 -070037import android.os.ResultReceiver;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070038import android.os.ServiceManager;
39import android.os.UserHandle;
Stuart Scott981d8582015-04-21 14:09:50 -070040import android.os.UserManager;
Sooraj Sasindran600a37a2016-07-18 11:57:25 -070041import android.os.WorkSource;
Derek Tan97ebb422014-09-05 16:55:38 -070042import android.preference.PreferenceManager;
Ihab Awadf2177b72013-11-25 13:33:23 -080043import android.provider.Settings;
Meng Wang1a7c35a2016-05-05 20:56:15 -070044import android.service.carrier.CarrierIdentifier;
Santos Cordon7a1885b2015-02-03 11:15:19 -080045import android.telecom.PhoneAccount;
Nancy Chen31f9ba12016-01-06 11:42:12 -080046import android.telecom.PhoneAccountHandle;
Andrew Lee9431b832015-03-09 18:46:45 -070047import android.telecom.TelecomManager;
Junda Liu12f7d802015-05-01 12:06:44 -070048import android.telephony.CarrierConfigManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070049import android.telephony.CellInfo;
Sooraj Sasindran600a37a2016-07-18 11:57:25 -070050import android.telephony.ClientRequestStats;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070051import android.telephony.IccOpenLogicalChannelResponse;
Ta-wei Yen87c49842016-05-13 21:19:52 -070052import android.telephony.ModemActivityInfo;
Jake Hambye994d462014-02-03 13:10:13 -080053import android.telephony.NeighboringCellInfo;
Wink Saville5d475dd2014-10-17 15:00:58 -070054import android.telephony.RadioAccessFamily;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070055import android.telephony.ServiceState;
Wink Saville0f3b5fc2014-11-11 08:40:49 -080056import android.telephony.SubscriptionInfo;
Jeff Sharkey85190e62014-12-05 09:40:12 -080057import android.telephony.SubscriptionManager;
Sanket Padawe99ef1e32016-05-18 16:12:33 -070058import android.telephony.TelephonyHistogram;
Ta-wei Yenb6929602016-05-24 15:48:27 -070059import android.telephony.TelephonyManager;
60import android.telephony.VisualVoicemailSmsFilterSettings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070061import android.text.TextUtils;
Jeff Sharkey85190e62014-12-05 09:40:12 -080062import android.util.ArraySet;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070063import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -080064import android.util.Pair;
Jeff Sharkey85190e62014-12-05 09:40:12 -080065import android.util.Slog;
Andrew Lee312e8172014-10-23 17:01:36 -070066import com.android.ims.ImsManager;
Brad Ebinger76681002017-01-23 13:50:20 -080067import com.android.ims.internal.IImsServiceController;
68import com.android.ims.internal.IImsServiceFeatureListener;
Shishir Agrawal566b7612013-10-28 14:41:00 -070069import com.android.internal.telephony.CallManager;
Shishir Agrawal302c8692015-06-19 13:49:39 -070070import com.android.internal.telephony.CellNetworkScanResult;
Shishir Agrawal566b7612013-10-28 14:41:00 -070071import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070072import com.android.internal.telephony.DefaultPhoneNotifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070073import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -080074import com.android.internal.telephony.IccCard;
Narayan Kamath1c496c22015-04-16 14:40:19 +010075import com.android.internal.telephony.MccTable;
Shishir Agrawal302c8692015-06-19 13:49:39 -070076import com.android.internal.telephony.OperatorInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070077import com.android.internal.telephony.Phone;
Ta-wei Yen87c49842016-05-13 21:19:52 -070078import com.android.internal.telephony.PhoneConstants;
Wink Saville36469e72014-06-11 15:17:00 -070079import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -070080import com.android.internal.telephony.ProxyController;
Sanket Padawe99ef1e32016-05-18 16:12:33 -070081import com.android.internal.telephony.RIL;
Svet Ganovb320e182015-04-16 12:30:10 -070082import com.android.internal.telephony.RILConstants;
Wink Savilleac1bdfd2014-11-20 23:04:44 -080083import com.android.internal.telephony.SubscriptionController;
Shishir Agrawal566b7612013-10-28 14:41:00 -070084import com.android.internal.telephony.uicc.IccIoResult;
85import com.android.internal.telephony.uicc.IccUtils;
Nathan Haroldb3014052017-01-25 15:57:32 -080086import com.android.internal.telephony.uicc.SIMRecords;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -070087import com.android.internal.telephony.uicc.UiccCard;
Nathan Haroldb3014052017-01-25 15:57:32 -080088import com.android.internal.telephony.uicc.UiccCardApplication;
Shishir Agrawal566b7612013-10-28 14:41:00 -070089import com.android.internal.telephony.uicc.UiccController;
Jake Hambye994d462014-02-03 13:10:13 -080090import com.android.internal.util.HexDump;
Ta-wei Yenb0f695b2016-08-08 17:33:11 -070091import com.android.phone.settings.VisualVoicemailSettingsUtil;
Nancy Chen31f9ba12016-01-06 11:42:12 -080092import com.android.phone.settings.VoicemailNotificationSettingsUtil;
Ta-wei Yenc236d6b2016-06-21 13:33:12 -070093import java.io.FileDescriptor;
94import java.io.PrintWriter;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070095import java.util.ArrayList;
Jeff Sharkey85190e62014-12-05 09:40:12 -080096import java.util.Arrays;
Jake Hambye994d462014-02-03 13:10:13 -080097import java.util.List;
Narayan Kamath1c496c22015-04-16 14:40:19 +010098import java.util.Locale;
Jeff Sharkey85190e62014-12-05 09:40:12 -080099import java.util.Map;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700100
101/**
102 * Implementation of the ITelephony interface.
103 */
Santos Cordon117fee72014-05-16 17:56:12 -0700104public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700105 private static final String LOG_TAG = "PhoneInterfaceManager";
106 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
107 private static final boolean DBG_LOC = false;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800108 private static final boolean DBG_MERGE = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700109
110 // Message codes used with mMainThreadHandler
111 private static final int CMD_HANDLE_PIN_MMI = 1;
112 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
113 private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
114 private static final int CMD_ANSWER_RINGING_CALL = 4;
115 private static final int CMD_END_CALL = 5; // not used yet
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700116 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
117 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700118 private static final int CMD_OPEN_CHANNEL = 9;
119 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
120 private static final int CMD_CLOSE_CHANNEL = 11;
121 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800122 private static final int CMD_NV_READ_ITEM = 13;
123 private static final int EVENT_NV_READ_ITEM_DONE = 14;
124 private static final int CMD_NV_WRITE_ITEM = 15;
125 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
126 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
127 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
128 private static final int CMD_NV_RESET_CONFIG = 19;
129 private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800130 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
131 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
132 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
133 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800134 private static final int CMD_SEND_ENVELOPE = 25;
135 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Derek Tan6b088ee2014-09-05 14:15:18 -0700136 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
137 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
138 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
139 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
140 private static final int CMD_EXCHANGE_SIM_IO = 31;
141 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800142 private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
143 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
Stuart Scott54788802015-03-30 13:18:01 -0700144 private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
145 private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700146 private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
147 private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700148 private static final int CMD_PERFORM_NETWORK_SCAN = 39;
149 private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
150 private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
151 private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
Meng Wang1a7c35a2016-05-05 20:56:15 -0700152 private static final int CMD_SET_ALLOWED_CARRIERS = 43;
153 private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
154 private static final int CMD_GET_ALLOWED_CARRIERS = 45;
155 private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
Nathan Haroldb3014052017-01-25 15:57:32 -0800156 private static final int CMD_GET_FORBIDDEN_PLMNS = 48;
157 private static final int EVENT_GET_FORBIDDEN_PLMNS_DONE = 49;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700158
159 /** The singleton instance. */
160 private static PhoneInterfaceManager sInstance;
161
Wink Saville3ab207e2014-11-20 13:07:20 -0800162 private PhoneGlobals mApp;
163 private Phone mPhone;
164 private CallManager mCM;
Stuart Scott981d8582015-04-21 14:09:50 -0700165 private UserManager mUserManager;
Wink Saville3ab207e2014-11-20 13:07:20 -0800166 private AppOpsManager mAppOps;
167 private MainThreadHandler mMainThreadHandler;
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800168 private SubscriptionController mSubscriptionController;
Wink Saville3ab207e2014-11-20 13:07:20 -0800169 private SharedPreferences mTelephonySharedPreferences;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700170
Derek Tan97ebb422014-09-05 16:55:38 -0700171 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
172 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
Jeff Sharkey85190e62014-12-05 09:40:12 -0800173 private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
Derek Tan89e89d42014-07-08 17:00:10 -0700174
175 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700176 * A request object to use for transmitting data to an ICC.
177 */
178 private static final class IccAPDUArgument {
179 public int channel, cla, command, p1, p2, p3;
180 public String data;
181
182 public IccAPDUArgument(int channel, int cla, int command,
183 int p1, int p2, int p3, String data) {
184 this.channel = channel;
185 this.cla = cla;
186 this.command = command;
187 this.p1 = p1;
188 this.p2 = p2;
189 this.p3 = p3;
190 this.data = data;
191 }
192 }
193
194 /**
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700195 * A request object to use for transmitting data to an ICC.
196 */
197 private static final class ManualNetworkSelectionArgument {
198 public OperatorInfo operatorInfo;
199 public boolean persistSelection;
200
201 public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
202 this.operatorInfo = operatorInfo;
203 this.persistSelection = persistSelection;
204 }
205 }
206
207 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700208 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
209 * request after sending. The main thread will notify the request when it is complete.
210 */
211 private static final class MainThreadRequest {
212 /** The argument to use for the request */
213 public Object argument;
214 /** The result of the request that is run on the main thread */
215 public Object result;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800216 // The subscriber id that this request applies to. Defaults to
217 // SubscriptionManager.INVALID_SUBSCRIPTION_ID
218 public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700219
220 public MainThreadRequest(Object argument) {
221 this.argument = argument;
222 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800223
224 public MainThreadRequest(Object argument, Integer subId) {
225 this.argument = argument;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800226 if (subId != null) {
227 this.subId = subId;
228 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800229 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700230 }
231
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800232 private static final class IncomingThirdPartyCallArgs {
233 public final ComponentName component;
234 public final String callId;
235 public final String callerDisplayName;
236
237 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
238 String callerDisplayName) {
239 this.component = component;
240 this.callId = callId;
241 this.callerDisplayName = callerDisplayName;
242 }
243 }
244
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700245 /**
246 * A handler that processes messages on the main thread in the phone process. Since many
247 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
248 * inbound binder threads to the main thread in the phone process. The Binder thread
249 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
250 * on, which will be notified when the operation completes and will contain the result of the
251 * request.
252 *
253 * <p>If a MainThreadRequest object is provided in the msg.obj field,
254 * note that request.result must be set to something non-null for the calling thread to
255 * unblock.
256 */
257 private final class MainThreadHandler extends Handler {
258 @Override
259 public void handleMessage(Message msg) {
260 MainThreadRequest request;
261 Message onCompleted;
262 AsyncResult ar;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800263 UiccCard uiccCard;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700264 IccAPDUArgument iccArgument;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700265
266 switch (msg.what) {
Yorke Lee716f67e2015-06-17 15:39:16 -0700267 case CMD_HANDLE_PIN_MMI: {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700268 request = (MainThreadRequest) msg.obj;
Yorke Lee716f67e2015-06-17 15:39:16 -0700269 final Phone phone = getPhoneFromRequest(request);
270 request.result = phone != null ?
271 getPhoneFromRequest(request).handlePinMmi((String) request.argument)
272 : false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700273 // Wake up the requesting thread
274 synchronized (request) {
275 request.notifyAll();
276 }
277 break;
Yorke Lee716f67e2015-06-17 15:39:16 -0700278 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700279
280 case CMD_HANDLE_NEIGHBORING_CELL:
281 request = (MainThreadRequest) msg.obj;
282 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
283 request);
Sooraj Sasindran600a37a2016-07-18 11:57:25 -0700284 mPhone.getNeighboringCids(onCompleted, (WorkSource)request.argument);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700285 break;
286
287 case EVENT_NEIGHBORING_CELL_DONE:
288 ar = (AsyncResult) msg.obj;
289 request = (MainThreadRequest) ar.userObj;
290 if (ar.exception == null && ar.result != null) {
291 request.result = ar.result;
292 } else {
293 // create an empty list to notify the waiting thread
Jake Hambye994d462014-02-03 13:10:13 -0800294 request.result = new ArrayList<NeighboringCellInfo>(0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700295 }
296 // Wake up the requesting thread
297 synchronized (request) {
298 request.notifyAll();
299 }
300 break;
301
302 case CMD_ANSWER_RINGING_CALL:
Wink Saville08874612014-08-31 19:19:58 -0700303 request = (MainThreadRequest) msg.obj;
Stuart Scott584921c2015-01-15 17:10:34 -0800304 int answer_subId = request.subId;
Wink Saville08874612014-08-31 19:19:58 -0700305 answerRingingCallInternal(answer_subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700306 break;
307
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700308 case CMD_END_CALL:
309 request = (MainThreadRequest) msg.obj;
Stuart Scott584921c2015-01-15 17:10:34 -0800310 int end_subId = request.subId;
Wink Saville08874612014-08-31 19:19:58 -0700311 final boolean hungUp;
Anthony Leeae4e36d2015-05-21 07:17:46 -0700312 Phone phone = getPhone(end_subId);
313 if (phone == null) {
314 if (DBG) log("CMD_END_CALL: no phone for id: " + end_subId);
315 break;
316 }
317 int phoneType = phone.getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700318 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
319 // CDMA: If the user presses the Power button we treat it as
320 // ending the complete call session
Wink Saville08874612014-08-31 19:19:58 -0700321 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700322 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
323 // GSM: End the call as per the Phone state
324 hungUp = PhoneUtils.hangup(mCM);
325 } else {
326 throw new IllegalStateException("Unexpected phone type: " + phoneType);
327 }
328 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
329 request.result = hungUp;
330 // Wake up the requesting thread
331 synchronized (request) {
332 request.notifyAll();
333 }
334 break;
335
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700336 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700337 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700338 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800339 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700340 if (uiccCard == null) {
341 loge("iccTransmitApduLogicalChannel: No UICC");
342 request.result = new IccIoResult(0x6F, 0, (byte[])null);
343 synchronized (request) {
344 request.notifyAll();
345 }
346 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700347 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
348 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700349 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700350 iccArgument.channel, iccArgument.cla, iccArgument.command,
351 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700352 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700353 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700354 break;
355
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700356 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700357 ar = (AsyncResult) msg.obj;
358 request = (MainThreadRequest) ar.userObj;
359 if (ar.exception == null && ar.result != null) {
360 request.result = ar.result;
361 } else {
362 request.result = new IccIoResult(0x6F, 0, (byte[])null);
363 if (ar.result == null) {
364 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800365 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700366 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800367 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700368 } else {
369 loge("iccTransmitApduLogicalChannel: Unknown exception");
370 }
371 }
372 synchronized (request) {
373 request.notifyAll();
374 }
375 break;
376
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700377 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
378 request = (MainThreadRequest) msg.obj;
379 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800380 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700381 if (uiccCard == null) {
382 loge("iccTransmitApduBasicChannel: No UICC");
383 request.result = new IccIoResult(0x6F, 0, (byte[])null);
384 synchronized (request) {
385 request.notifyAll();
386 }
387 } else {
388 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
389 request);
390 uiccCard.iccTransmitApduBasicChannel(
391 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
392 iccArgument.p3, iccArgument.data, onCompleted);
393 }
394 break;
395
396 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
397 ar = (AsyncResult) msg.obj;
398 request = (MainThreadRequest) ar.userObj;
399 if (ar.exception == null && ar.result != null) {
400 request.result = ar.result;
401 } else {
402 request.result = new IccIoResult(0x6F, 0, (byte[])null);
403 if (ar.result == null) {
404 loge("iccTransmitApduBasicChannel: Empty response");
405 } else if (ar.exception instanceof CommandException) {
406 loge("iccTransmitApduBasicChannel: CommandException: " +
407 ar.exception);
408 } else {
409 loge("iccTransmitApduBasicChannel: Unknown exception");
410 }
411 }
412 synchronized (request) {
413 request.notifyAll();
414 }
415 break;
416
417 case CMD_EXCHANGE_SIM_IO:
418 request = (MainThreadRequest) msg.obj;
419 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800420 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700421 if (uiccCard == null) {
422 loge("iccExchangeSimIO: No UICC");
423 request.result = new IccIoResult(0x6F, 0, (byte[])null);
424 synchronized (request) {
425 request.notifyAll();
426 }
427 } else {
428 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
429 request);
430 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
431 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
432 iccArgument.data, onCompleted);
433 }
434 break;
435
436 case EVENT_EXCHANGE_SIM_IO_DONE:
437 ar = (AsyncResult) msg.obj;
438 request = (MainThreadRequest) ar.userObj;
439 if (ar.exception == null && ar.result != null) {
440 request.result = ar.result;
441 } else {
442 request.result = new IccIoResult(0x6f, 0, (byte[])null);
443 }
444 synchronized (request) {
445 request.notifyAll();
446 }
447 break;
448
Derek Tan4d5e5c12014-02-04 11:54:58 -0800449 case CMD_SEND_ENVELOPE:
450 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800451 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700452 if (uiccCard == null) {
453 loge("sendEnvelopeWithStatus: No UICC");
454 request.result = new IccIoResult(0x6F, 0, (byte[])null);
455 synchronized (request) {
456 request.notifyAll();
457 }
458 } else {
459 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
460 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
461 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800462 break;
463
464 case EVENT_SEND_ENVELOPE_DONE:
465 ar = (AsyncResult) msg.obj;
466 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700467 if (ar.exception == null && ar.result != null) {
468 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800469 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700470 request.result = new IccIoResult(0x6F, 0, (byte[])null);
471 if (ar.result == null) {
472 loge("sendEnvelopeWithStatus: Empty response");
473 } else if (ar.exception instanceof CommandException) {
474 loge("sendEnvelopeWithStatus: CommandException: " +
475 ar.exception);
476 } else {
477 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
478 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800479 }
480 synchronized (request) {
481 request.notifyAll();
482 }
483 break;
484
Shishir Agrawal566b7612013-10-28 14:41:00 -0700485 case CMD_OPEN_CHANNEL:
486 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800487 uiccCard = getUiccCardFromRequest(request);
Ajay Nambiabd73502015-12-03 13:50:00 -0800488 Pair<String, Integer> openChannelArgs = (Pair<String, Integer>) request.argument;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700489 if (uiccCard == null) {
490 loge("iccOpenLogicalChannel: No UICC");
Shishir Agrawalfc0492a2016-02-17 11:15:33 -0800491 request.result = new IccOpenLogicalChannelResponse(-1,
492 IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700493 synchronized (request) {
494 request.notifyAll();
495 }
496 } else {
497 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
Ajay Nambiabd73502015-12-03 13:50:00 -0800498 uiccCard.iccOpenLogicalChannel(openChannelArgs.first,
499 openChannelArgs.second, onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700500 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700501 break;
502
503 case EVENT_OPEN_CHANNEL_DONE:
504 ar = (AsyncResult) msg.obj;
505 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700506 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700507 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700508 int[] result = (int[]) ar.result;
509 int channelId = result[0];
510 byte[] selectResponse = null;
511 if (result.length > 1) {
512 selectResponse = new byte[result.length - 1];
513 for (int i = 1; i < result.length; ++i) {
514 selectResponse[i - 1] = (byte) result[i];
515 }
516 }
517 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700518 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700519 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700520 if (ar.result == null) {
521 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700522 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700523 if (ar.exception != null) {
524 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
525 }
526
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700527 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Junda Liua754ba12015-05-20 01:17:52 -0700528 if (ar.exception instanceof CommandException) {
529 CommandException.Error error =
530 ((CommandException) (ar.exception)).getCommandError();
531 if (error == CommandException.Error.MISSING_RESOURCE) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700532 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Junda Liua754ba12015-05-20 01:17:52 -0700533 } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700534 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700535 }
536 }
537 openChannelResp = new IccOpenLogicalChannelResponse(
538 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700539 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700540 request.result = openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700541 synchronized (request) {
542 request.notifyAll();
543 }
544 break;
545
546 case CMD_CLOSE_CHANNEL:
547 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800548 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700549 if (uiccCard == null) {
550 loge("iccCloseLogicalChannel: No UICC");
551 request.result = new IccIoResult(0x6F, 0, (byte[])null);
552 synchronized (request) {
553 request.notifyAll();
554 }
555 } else {
556 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
557 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
558 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700559 break;
560
561 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800562 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
563 break;
564
565 case CMD_NV_READ_ITEM:
566 request = (MainThreadRequest) msg.obj;
567 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
568 mPhone.nvReadItem((Integer) request.argument, onCompleted);
569 break;
570
571 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700572 ar = (AsyncResult) msg.obj;
573 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800574 if (ar.exception == null && ar.result != null) {
575 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700576 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800577 request.result = "";
578 if (ar.result == null) {
579 loge("nvReadItem: Empty response");
580 } else if (ar.exception instanceof CommandException) {
581 loge("nvReadItem: CommandException: " +
582 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700583 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800584 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700585 }
586 }
587 synchronized (request) {
588 request.notifyAll();
589 }
590 break;
591
Jake Hambye994d462014-02-03 13:10:13 -0800592 case CMD_NV_WRITE_ITEM:
593 request = (MainThreadRequest) msg.obj;
594 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
595 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
596 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
597 break;
598
599 case EVENT_NV_WRITE_ITEM_DONE:
600 handleNullReturnEvent(msg, "nvWriteItem");
601 break;
602
603 case CMD_NV_WRITE_CDMA_PRL:
604 request = (MainThreadRequest) msg.obj;
605 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
606 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
607 break;
608
609 case EVENT_NV_WRITE_CDMA_PRL_DONE:
610 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
611 break;
612
613 case CMD_NV_RESET_CONFIG:
614 request = (MainThreadRequest) msg.obj;
615 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
616 mPhone.nvResetConfig((Integer) request.argument, onCompleted);
617 break;
618
619 case EVENT_NV_RESET_CONFIG_DONE:
620 handleNullReturnEvent(msg, "nvResetConfig");
621 break;
622
Jake Hamby7c27be32014-03-03 13:25:59 -0800623 case CMD_GET_PREFERRED_NETWORK_TYPE:
624 request = (MainThreadRequest) msg.obj;
625 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
Stuart Scott54788802015-03-30 13:18:01 -0700626 getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -0800627 break;
628
629 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
630 ar = (AsyncResult) msg.obj;
631 request = (MainThreadRequest) ar.userObj;
632 if (ar.exception == null && ar.result != null) {
633 request.result = ar.result; // Integer
634 } else {
Sanket Padawecfc2d352016-01-05 19:52:14 -0800635 request.result = null;
Jake Hamby7c27be32014-03-03 13:25:59 -0800636 if (ar.result == null) {
637 loge("getPreferredNetworkType: Empty response");
638 } else if (ar.exception instanceof CommandException) {
639 loge("getPreferredNetworkType: CommandException: " +
640 ar.exception);
641 } else {
642 loge("getPreferredNetworkType: Unknown exception");
643 }
644 }
645 synchronized (request) {
646 request.notifyAll();
647 }
648 break;
649
650 case CMD_SET_PREFERRED_NETWORK_TYPE:
651 request = (MainThreadRequest) msg.obj;
652 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
653 int networkType = (Integer) request.argument;
Stuart Scott54788802015-03-30 13:18:01 -0700654 getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -0800655 break;
656
657 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
658 handleNullReturnEvent(msg, "setPreferredNetworkType");
659 break;
660
Steven Liu4bf01bc2014-07-17 11:05:29 -0500661 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
662 request = (MainThreadRequest)msg.obj;
663 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
664 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
665 break;
666
667 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
668 ar = (AsyncResult)msg.obj;
669 request = (MainThreadRequest)ar.userObj;
670 request.result = ar;
671 synchronized (request) {
672 request.notifyAll();
673 }
674 break;
675
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800676 case CMD_SET_VOICEMAIL_NUMBER:
677 request = (MainThreadRequest) msg.obj;
678 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
679 Pair<String, String> tagNum = (Pair<String, String>) request.argument;
Stuart Scott584921c2015-01-15 17:10:34 -0800680 getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
681 onCompleted);
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800682 break;
683
684 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
685 handleNullReturnEvent(msg, "setVoicemailNumber");
686 break;
687
Stuart Scott54788802015-03-30 13:18:01 -0700688 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
689 request = (MainThreadRequest) msg.obj;
690 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
691 request);
692 getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
693 break;
694
695 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
696 handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
697 break;
698
Shishir Agrawal302c8692015-06-19 13:49:39 -0700699 case CMD_PERFORM_NETWORK_SCAN:
700 request = (MainThreadRequest) msg.obj;
701 onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
702 getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
703 break;
704
705 case EVENT_PERFORM_NETWORK_SCAN_DONE:
706 ar = (AsyncResult) msg.obj;
707 request = (MainThreadRequest) ar.userObj;
708 CellNetworkScanResult cellScanResult;
709 if (ar.exception == null && ar.result != null) {
710 cellScanResult = new CellNetworkScanResult(
711 CellNetworkScanResult.STATUS_SUCCESS,
712 (List<OperatorInfo>) ar.result);
713 } else {
714 if (ar.result == null) {
715 loge("getCellNetworkScanResults: Empty response");
716 }
717 if (ar.exception != null) {
718 loge("getCellNetworkScanResults: Exception: " + ar.exception);
719 }
720 int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
721 if (ar.exception instanceof CommandException) {
722 CommandException.Error error =
723 ((CommandException) (ar.exception)).getCommandError();
724 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
725 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
726 } else if (error == CommandException.Error.GENERIC_FAILURE) {
727 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
728 }
729 }
730 cellScanResult = new CellNetworkScanResult(errorCode, null);
731 }
732 request.result = cellScanResult;
733 synchronized (request) {
734 request.notifyAll();
735 }
736 break;
737
738 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
739 request = (MainThreadRequest) msg.obj;
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700740 ManualNetworkSelectionArgument selArg =
741 (ManualNetworkSelectionArgument) request.argument;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700742 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
743 request);
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700744 getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
745 selArg.persistSelection, onCompleted);
Shishir Agrawal302c8692015-06-19 13:49:39 -0700746 break;
747
748 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
749 handleNullReturnEvent(msg, "setNetworkSelectionModeManual");
750 break;
751
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700752 case CMD_GET_MODEM_ACTIVITY_INFO:
753 request = (MainThreadRequest) msg.obj;
754 onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
Prerepa Viswanadham61a60ad2015-06-08 18:07:51 -0700755 mPhone.getModemActivityInfo(onCompleted);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700756 break;
757
758 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
759 ar = (AsyncResult) msg.obj;
760 request = (MainThreadRequest) ar.userObj;
761 if (ar.exception == null && ar.result != null) {
762 request.result = ar.result;
763 } else {
764 if (ar.result == null) {
765 loge("queryModemActivityInfo: Empty response");
766 } else if (ar.exception instanceof CommandException) {
767 loge("queryModemActivityInfo: CommandException: " +
768 ar.exception);
769 } else {
770 loge("queryModemActivityInfo: Unknown exception");
771 }
772 }
Amit Mahajand4766222016-01-28 15:28:28 -0800773 // Result cannot be null. Return ModemActivityInfo with all fields set to 0.
774 if (request.result == null) {
775 request.result = new ModemActivityInfo(0, 0, 0, null, 0, 0);
776 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700777 synchronized (request) {
778 request.notifyAll();
779 }
780 break;
781
Meng Wang1a7c35a2016-05-05 20:56:15 -0700782 case CMD_SET_ALLOWED_CARRIERS:
783 request = (MainThreadRequest) msg.obj;
784 onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
785 mPhone.setAllowedCarriers(
786 (List<CarrierIdentifier>) request.argument,
787 onCompleted);
788 break;
789
790 case EVENT_SET_ALLOWED_CARRIERS_DONE:
791 ar = (AsyncResult) msg.obj;
792 request = (MainThreadRequest) ar.userObj;
793 if (ar.exception == null && ar.result != null) {
794 request.result = ar.result;
795 } else {
796 if (ar.result == null) {
797 loge("setAllowedCarriers: Empty response");
798 } else if (ar.exception instanceof CommandException) {
799 loge("setAllowedCarriers: CommandException: " +
800 ar.exception);
801 } else {
802 loge("setAllowedCarriers: Unknown exception");
803 }
804 }
805 // Result cannot be null. Return -1 on error.
806 if (request.result == null) {
807 request.result = new int[]{-1};
808 }
809 synchronized (request) {
810 request.notifyAll();
811 }
812 break;
813
814 case CMD_GET_ALLOWED_CARRIERS:
815 request = (MainThreadRequest) msg.obj;
816 onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
817 mPhone.getAllowedCarriers(onCompleted);
818 break;
819
820 case EVENT_GET_ALLOWED_CARRIERS_DONE:
821 ar = (AsyncResult) msg.obj;
822 request = (MainThreadRequest) ar.userObj;
823 if (ar.exception == null && ar.result != null) {
824 request.result = ar.result;
825 } else {
826 if (ar.result == null) {
827 loge("getAllowedCarriers: Empty response");
828 } else if (ar.exception instanceof CommandException) {
829 loge("getAllowedCarriers: CommandException: " +
830 ar.exception);
831 } else {
832 loge("getAllowedCarriers: Unknown exception");
833 }
834 }
835 // Result cannot be null. Return empty list of CarrierIdentifier.
836 if (request.result == null) {
837 request.result = new ArrayList<CarrierIdentifier>(0);
838 }
839 synchronized (request) {
840 request.notifyAll();
841 }
842 break;
843
Nathan Haroldb3014052017-01-25 15:57:32 -0800844 case EVENT_GET_FORBIDDEN_PLMNS_DONE:
845 ar = (AsyncResult) msg.obj;
846 request = (MainThreadRequest) ar.userObj;
847 if (ar.exception == null && ar.result != null) {
848 request.result = ar.result;
849 } else {
850 request.result = new IllegalArgumentException(
851 "Failed to retrieve Forbidden Plmns");
852 if (ar.result == null) {
853 loge("getForbiddenPlmns: Empty response");
854 } else {
855 loge("getForbiddenPlmns: Unknown exception");
856 }
857 }
858 synchronized (request) {
859 request.notifyAll();
860 }
861 break;
862
863 case CMD_GET_FORBIDDEN_PLMNS:
864 request = (MainThreadRequest) msg.obj;
865 uiccCard = getUiccCardFromRequest(request);
866 if (uiccCard == null) {
867 loge("getForbiddenPlmns() UiccCard is null");
868 request.result = new IllegalArgumentException(
869 "getForbiddenPlmns() UiccCard is null");
870 synchronized (request) {
871 request.notifyAll();
872 }
873 break;
874 }
875 Integer appType = (Integer) request.argument;
876 UiccCardApplication uiccApp = uiccCard.getApplicationByType(appType);
877 if (uiccApp == null) {
878 loge("getForbiddenPlmns() no app with specified type -- "
879 + appType);
880 request.result = new IllegalArgumentException("Failed to get UICC App");
881 synchronized (request) {
882 request.notifyAll();
883 }
884 break;
885 } else {
886 if (DBG) logv("getForbiddenPlmns() found app " + uiccApp.getAid()
887 + " specified type -- " + appType);
888 }
889 onCompleted = obtainMessage(EVENT_GET_FORBIDDEN_PLMNS_DONE, request);
890 ((SIMRecords) uiccApp.getIccRecords()).getForbiddenPlmns(
891 onCompleted);
892 break;
893
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700894 default:
895 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
896 break;
897 }
898 }
Jake Hambye994d462014-02-03 13:10:13 -0800899
900 private void handleNullReturnEvent(Message msg, String command) {
901 AsyncResult ar = (AsyncResult) msg.obj;
902 MainThreadRequest request = (MainThreadRequest) ar.userObj;
903 if (ar.exception == null) {
904 request.result = true;
905 } else {
906 request.result = false;
907 if (ar.exception instanceof CommandException) {
908 loge(command + ": CommandException: " + ar.exception);
909 } else {
910 loge(command + ": Unknown exception");
911 }
912 }
913 synchronized (request) {
914 request.notifyAll();
915 }
916 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700917 }
918
919 /**
920 * Posts the specified command to be executed on the main thread,
921 * waits for the request to complete, and returns the result.
922 * @see #sendRequestAsync
923 */
924 private Object sendRequest(int command, Object argument) {
Sanket Padawe56e75a32016-02-08 12:18:19 -0800925 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Saville36469e72014-06-11 15:17:00 -0700926 }
927
928 /**
929 * Posts the specified command to be executed on the main thread,
930 * waits for the request to complete, and returns the result.
931 * @see #sendRequestAsync
932 */
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800933 private Object sendRequest(int command, Object argument, Integer subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700934 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
935 throw new RuntimeException("This method will deadlock if called from the main thread.");
936 }
937
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800938 MainThreadRequest request = new MainThreadRequest(argument, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700939 Message msg = mMainThreadHandler.obtainMessage(command, request);
940 msg.sendToTarget();
941
942 // Wait for the request to complete
943 synchronized (request) {
944 while (request.result == null) {
945 try {
946 request.wait();
947 } catch (InterruptedException e) {
948 // Do nothing, go back and wait until the request is complete
949 }
950 }
951 }
952 return request.result;
953 }
954
955 /**
956 * Asynchronous ("fire and forget") version of sendRequest():
957 * Posts the specified command to be executed on the main thread, and
958 * returns immediately.
959 * @see #sendRequest
960 */
961 private void sendRequestAsync(int command) {
962 mMainThreadHandler.sendEmptyMessage(command);
963 }
964
965 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -0700966 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
967 * @see {@link #sendRequest(int,Object)}
968 */
969 private void sendRequestAsync(int command, Object argument) {
970 MainThreadRequest request = new MainThreadRequest(argument);
971 Message msg = mMainThreadHandler.obtainMessage(command, request);
972 msg.sendToTarget();
973 }
974
975 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700976 * Initialize the singleton PhoneInterfaceManager instance.
977 * This is only done once, at startup, from PhoneApp.onCreate().
978 */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700979 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700980 synchronized (PhoneInterfaceManager.class) {
981 if (sInstance == null) {
Sailesh Nepal194161e2014-07-03 08:57:44 -0700982 sInstance = new PhoneInterfaceManager(app, phone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700983 } else {
984 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
985 }
986 return sInstance;
987 }
988 }
989
990 /** Private constructor; @see init() */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700991 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700992 mApp = app;
993 mPhone = phone;
994 mCM = PhoneGlobals.getInstance().mCM;
Stuart Scott981d8582015-04-21 14:09:50 -0700995 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700996 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
997 mMainThreadHandler = new MainThreadHandler();
Andrew Leedf14ead2014-10-17 14:22:52 -0700998 mTelephonySharedPreferences =
Derek Tan97ebb422014-09-05 16:55:38 -0700999 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001000 mSubscriptionController = SubscriptionController.getInstance();
Wink Saville3ab207e2014-11-20 13:07:20 -08001001
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001002 publish();
1003 }
1004
1005 private void publish() {
1006 if (DBG) log("publish: " + this);
1007
1008 ServiceManager.addService("phone", this);
1009 }
1010
Stuart Scott584921c2015-01-15 17:10:34 -08001011 private Phone getPhoneFromRequest(MainThreadRequest request) {
Sanket Padawe56e75a32016-02-08 12:18:19 -08001012 return (request.subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
1013 ? mPhone : getPhone(request.subId);
Stuart Scott584921c2015-01-15 17:10:34 -08001014 }
1015
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001016 private UiccCard getUiccCardFromRequest(MainThreadRequest request) {
1017 Phone phone = getPhoneFromRequest(request);
1018 return phone == null ? null :
1019 UiccController.getInstance().getUiccCard(phone.getPhoneId());
1020 }
1021
Wink Saville36469e72014-06-11 15:17:00 -07001022 // returns phone associated with the subId.
Wink Savilleb564aae2014-10-23 10:18:09 -07001023 private Phone getPhone(int subId) {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001024 return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -07001025 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001026 //
1027 // Implementation of the ITelephony interface.
1028 //
1029
1030 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001031 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -07001032 }
1033
Wink Savilleb564aae2014-10-23 10:18:09 -07001034 public void dialForSubscriber(int subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001035 if (DBG) log("dial: " + number);
1036 // No permission check needed here: This is just a wrapper around the
1037 // ACTION_DIAL intent, which is available to any app since it puts up
1038 // the UI before it does anything.
1039
1040 String url = createTelUrl(number);
1041 if (url == null) {
1042 return;
1043 }
1044
1045 // PENDING: should we just silently fail if phone is offhook or ringing?
Wink Saville36469e72014-06-11 15:17:00 -07001046 PhoneConstants.State state = mCM.getState(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001047 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
1048 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
1049 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1050 mApp.startActivity(intent);
1051 }
1052 }
1053
1054 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001055 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -07001056 }
1057
Wink Savilleb564aae2014-10-23 10:18:09 -07001058 public void callForSubscriber(int subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001059 if (DBG) log("call: " + number);
1060
1061 // This is just a wrapper around the ACTION_CALL intent, but we still
1062 // need to do a permission check since we're calling startActivity()
1063 // from the context of the phone app.
1064 enforceCallPermission();
1065
1066 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
1067 != AppOpsManager.MODE_ALLOWED) {
1068 return;
1069 }
1070
1071 String url = createTelUrl(number);
1072 if (url == null) {
1073 return;
1074 }
1075
Wink Saville08874612014-08-31 19:19:58 -07001076 boolean isValid = false;
Narayan Kamath1c496c22015-04-16 14:40:19 +01001077 final List<SubscriptionInfo> slist = getActiveSubscriptionInfoList();
Wink Saville3ab207e2014-11-20 13:07:20 -08001078 if (slist != null) {
1079 for (SubscriptionInfo subInfoRecord : slist) {
1080 if (subInfoRecord.getSubscriptionId() == subId) {
1081 isValid = true;
1082 break;
1083 }
Wink Saville08874612014-08-31 19:19:58 -07001084 }
1085 }
1086 if (isValid == false) {
1087 return;
1088 }
1089
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001090 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
Wink Saville36469e72014-06-11 15:17:00 -07001091 intent.putExtra(SUBSCRIPTION_KEY, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001092 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1093 mApp.startActivity(intent);
1094 }
1095
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001096 /**
1097 * End a call based on call state
1098 * @return true is a call was ended
1099 */
1100 public boolean endCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001101 return endCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001102 }
1103
1104 /**
1105 * End a call based on the call state of the subId
1106 * @return true is a call was ended
1107 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001108 public boolean endCallForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001109 enforceCallPermission();
Stuart Scott584921c2015-01-15 17:10:34 -08001110 return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001111 }
1112
1113 public void answerRingingCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001114 answerRingingCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001115 }
1116
Wink Savilleb564aae2014-10-23 10:18:09 -07001117 public void answerRingingCallForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001118 if (DBG) log("answerRingingCall...");
1119 // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
1120 // but that can probably wait till the big TelephonyManager API overhaul.
1121 // For now, protect this call with the MODIFY_PHONE_STATE permission.
1122 enforceModifyPermission();
Stuart Scott584921c2015-01-15 17:10:34 -08001123 sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001124 }
1125
1126 /**
1127 * Make the actual telephony calls to implement answerRingingCall().
1128 * This should only be called from the main thread of the Phone app.
1129 * @see #answerRingingCall
1130 *
1131 * TODO: it would be nice to return true if we answered the call, or
1132 * false if there wasn't actually a ringing incoming call, or some
1133 * other error occurred. (In other words, pass back the return value
1134 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
1135 * But that would require calling this method via sendRequest() rather
1136 * than sendRequestAsync(), and right now we don't actually *need* that
1137 * return value, so let's just return void for now.
1138 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001139 private void answerRingingCallInternal(int subId) {
Wink Saville08874612014-08-31 19:19:58 -07001140 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001141 if (hasRingingCall) {
Wink Saville08874612014-08-31 19:19:58 -07001142 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
1143 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001144 if (hasActiveCall && hasHoldingCall) {
1145 // Both lines are in use!
1146 // TODO: provide a flag to let the caller specify what
1147 // policy to use if both lines are in use. (The current
1148 // behavior is hardwired to "answer incoming, end ongoing",
1149 // which is how the CALL button is specced to behave.)
1150 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
1151 return;
1152 } else {
1153 // answerCall() will automatically hold the current active
1154 // call, if there is one.
1155 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
1156 return;
1157 }
1158 } else {
1159 // No call was ringing.
1160 return;
1161 }
1162 }
1163
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001164 /**
Santos Cordon5422a8d2014-09-12 04:20:56 -07001165 * This method is no longer used and can be removed once TelephonyManager stops referring to it.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001166 */
Santos Cordon5422a8d2014-09-12 04:20:56 -07001167 public void silenceRinger() {
1168 Log.e(LOG_TAG, "silenseRinger not supported");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001169 }
1170
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001171 @Override
1172 public boolean isOffhook(String callingPackage) {
1173 return isOffhookForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001174 }
1175
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001176 @Override
1177 public boolean isOffhookForSubscriber(int subId, String callingPackage) {
1178 if (!canReadPhoneState(callingPackage, "isOffhookForSubscriber")) {
1179 return false;
1180 }
1181
Sanket Padawe356d7632015-06-22 14:03:32 -07001182 final Phone phone = getPhone(subId);
1183 if (phone != null) {
1184 return (phone.getState() == PhoneConstants.State.OFFHOOK);
1185 } else {
1186 return false;
1187 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001188 }
1189
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001190 @Override
1191 public boolean isRinging(String callingPackage) {
1192 return (isRingingForSubscriber(getDefaultSubscription(), callingPackage));
Wink Saville36469e72014-06-11 15:17:00 -07001193 }
1194
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001195 @Override
1196 public boolean isRingingForSubscriber(int subId, String callingPackage) {
1197 if (!canReadPhoneState(callingPackage, "isRingingForSubscriber")) {
1198 return false;
1199 }
1200
Sanket Padawe356d7632015-06-22 14:03:32 -07001201 final Phone phone = getPhone(subId);
1202 if (phone != null) {
1203 return (phone.getState() == PhoneConstants.State.RINGING);
1204 } else {
1205 return false;
1206 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001207 }
1208
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001209 @Override
1210 public boolean isIdle(String callingPackage) {
1211 return isIdleForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001212 }
1213
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001214 @Override
1215 public boolean isIdleForSubscriber(int subId, String callingPackage) {
1216 if (!canReadPhoneState(callingPackage, "isIdleForSubscriber")) {
1217 return false;
1218 }
1219
Sanket Padawe356d7632015-06-22 14:03:32 -07001220 final Phone phone = getPhone(subId);
1221 if (phone != null) {
1222 return (phone.getState() == PhoneConstants.State.IDLE);
1223 } else {
1224 return false;
1225 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001226 }
1227
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001228 public boolean supplyPin(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001229 return supplyPinForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -07001230 }
1231
Wink Savilleb564aae2014-10-23 10:18:09 -07001232 public boolean supplyPinForSubscriber(int subId, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001233 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07001234 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1235 }
1236
1237 public boolean supplyPuk(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001238 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -07001239 }
1240
Wink Savilleb564aae2014-10-23 10:18:09 -07001241 public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001242 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07001243 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1244 }
1245
1246 /** {@hide} */
1247 public int[] supplyPinReportResult(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001248 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -07001249 }
1250
Wink Savilleb564aae2014-10-23 10:18:09 -07001251 public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001252 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001253 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001254 checkSimPin.start();
1255 return checkSimPin.unlockSim(null, pin);
1256 }
1257
Wink Saville9de0f752013-10-22 19:04:03 -07001258 /** {@hide} */
1259 public int[] supplyPukReportResult(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001260 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -07001261 }
1262
Wink Savilleb564aae2014-10-23 10:18:09 -07001263 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001264 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001265 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001266 checkSimPuk.start();
1267 return checkSimPuk.unlockSim(puk, pin);
1268 }
1269
1270 /**
Wink Saville9de0f752013-10-22 19:04:03 -07001271 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001272 * a synchronous one.
1273 */
1274 private static class UnlockSim extends Thread {
1275
1276 private final IccCard mSimCard;
1277
1278 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -07001279 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1280 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001281
1282 // For replies from SimCard interface
1283 private Handler mHandler;
1284
1285 // For async handler to identify request type
1286 private static final int SUPPLY_PIN_COMPLETE = 100;
1287
1288 public UnlockSim(IccCard simCard) {
1289 mSimCard = simCard;
1290 }
1291
1292 @Override
1293 public void run() {
1294 Looper.prepare();
1295 synchronized (UnlockSim.this) {
1296 mHandler = new Handler() {
1297 @Override
1298 public void handleMessage(Message msg) {
1299 AsyncResult ar = (AsyncResult) msg.obj;
1300 switch (msg.what) {
1301 case SUPPLY_PIN_COMPLETE:
1302 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
1303 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -07001304 mRetryCount = msg.arg1;
1305 if (ar.exception != null) {
1306 if (ar.exception instanceof CommandException &&
1307 ((CommandException)(ar.exception)).getCommandError()
1308 == CommandException.Error.PASSWORD_INCORRECT) {
1309 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1310 } else {
1311 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1312 }
1313 } else {
1314 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1315 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001316 mDone = true;
1317 UnlockSim.this.notifyAll();
1318 }
1319 break;
1320 }
1321 }
1322 };
1323 UnlockSim.this.notifyAll();
1324 }
1325 Looper.loop();
1326 }
1327
1328 /*
1329 * Use PIN or PUK to unlock SIM card
1330 *
1331 * If PUK is null, unlock SIM card with PIN
1332 *
1333 * If PUK is not null, unlock SIM card with PUK and set PIN code
1334 */
Wink Saville9de0f752013-10-22 19:04:03 -07001335 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001336
1337 while (mHandler == null) {
1338 try {
1339 wait();
1340 } catch (InterruptedException e) {
1341 Thread.currentThread().interrupt();
1342 }
1343 }
1344 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1345
1346 if (puk == null) {
1347 mSimCard.supplyPin(pin, callback);
1348 } else {
1349 mSimCard.supplyPuk(puk, pin, callback);
1350 }
1351
1352 while (!mDone) {
1353 try {
1354 Log.d(LOG_TAG, "wait for done");
1355 wait();
1356 } catch (InterruptedException e) {
1357 // Restore the interrupted status
1358 Thread.currentThread().interrupt();
1359 }
1360 }
1361 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001362 int[] resultArray = new int[2];
1363 resultArray[0] = mResult;
1364 resultArray[1] = mRetryCount;
1365 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001366 }
1367 }
1368
1369 public void updateServiceLocation() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001370 updateServiceLocationForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001371
1372 }
1373
Wink Savilleb564aae2014-10-23 10:18:09 -07001374 public void updateServiceLocationForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001375 // No permission check needed here: this call is harmless, and it's
1376 // needed for the ServiceState.requestStateUpdate() call (which is
1377 // already intentionally exposed to 3rd parties.)
Sanket Padawe356d7632015-06-22 14:03:32 -07001378 final Phone phone = getPhone(subId);
1379 if (phone != null) {
1380 phone.updateServiceLocation();
1381 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001382 }
1383
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001384 @Override
1385 public boolean isRadioOn(String callingPackage) {
1386 return isRadioOnForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001387 }
1388
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001389 @Override
1390 public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
1391 if (!canReadPhoneState(callingPackage, "isRadioOnForSubscriber")) {
1392 return false;
1393 }
1394 return isRadioOnForSubscriber(subId);
1395 }
1396
1397 private boolean isRadioOnForSubscriber(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07001398 final Phone phone = getPhone(subId);
1399 if (phone != null) {
1400 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1401 } else {
1402 return false;
1403 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001404 }
1405
1406 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001407 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001408
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001409 }
Wink Saville36469e72014-06-11 15:17:00 -07001410
Wink Savilleb564aae2014-10-23 10:18:09 -07001411 public void toggleRadioOnOffForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001412 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001413 final Phone phone = getPhone(subId);
1414 if (phone != null) {
1415 phone.setRadioPower(!isRadioOnForSubscriber(subId));
1416 }
Wink Saville36469e72014-06-11 15:17:00 -07001417 }
1418
1419 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001420 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001421 }
1422
Wink Savilleb564aae2014-10-23 10:18:09 -07001423 public boolean setRadioForSubscriber(int subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001424 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001425 final Phone phone = getPhone(subId);
1426 if (phone == null) {
1427 return false;
1428 }
1429 if ((phone.getServiceState().getState() !=
Wink Saville36469e72014-06-11 15:17:00 -07001430 ServiceState.STATE_POWER_OFF) != turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001431 toggleRadioOnOffForSubscriber(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001432 }
1433 return true;
1434 }
Wink Saville36469e72014-06-11 15:17:00 -07001435
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001436 public boolean needMobileRadioShutdown() {
1437 /*
1438 * If any of the Radios are available, it will need to be
1439 * shutdown. So return true if any Radio is available.
1440 */
1441 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1442 Phone phone = PhoneFactory.getPhone(i);
1443 if (phone != null && phone.isRadioAvailable()) return true;
1444 }
1445 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1446 return false;
1447 }
1448
1449 public void shutdownMobileRadios() {
1450 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1451 logv("Shutting down Phone " + i);
1452 shutdownRadioUsingPhoneId(i);
1453 }
1454 }
1455
1456 private void shutdownRadioUsingPhoneId(int phoneId) {
1457 enforceModifyPermission();
1458 Phone phone = PhoneFactory.getPhone(phoneId);
1459 if (phone != null && phone.isRadioAvailable()) {
1460 phone.shutdownRadio();
1461 }
1462 }
1463
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001464 public boolean setRadioPower(boolean turnOn) {
Wei Liu9ae2a062016-08-08 11:09:34 -07001465 final Phone defaultPhone = PhoneFactory.getDefaultPhone();
1466 if (defaultPhone != null) {
1467 defaultPhone.setRadioPower(turnOn);
1468 return true;
1469 } else {
1470 loge("There's no default phone.");
1471 return false;
1472 }
Wink Saville36469e72014-06-11 15:17:00 -07001473 }
1474
Wink Savilleb564aae2014-10-23 10:18:09 -07001475 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001476 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001477 final Phone phone = getPhone(subId);
1478 if (phone != null) {
1479 phone.setRadioPower(turnOn);
1480 return true;
1481 } else {
1482 return false;
1483 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001484 }
1485
Wink Saville36469e72014-06-11 15:17:00 -07001486 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001487 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001488 public boolean enableDataConnectivity() {
1489 enforceModifyPermission();
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001490 int subId = mSubscriptionController.getDefaultDataSubId();
Sanket Padawe356d7632015-06-22 14:03:32 -07001491 final Phone phone = getPhone(subId);
1492 if (phone != null) {
1493 phone.setDataEnabled(true);
1494 return true;
1495 } else {
1496 return false;
1497 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001498 }
1499
Wink Saville36469e72014-06-11 15:17:00 -07001500 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001501 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001502 public boolean disableDataConnectivity() {
1503 enforceModifyPermission();
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001504 int subId = mSubscriptionController.getDefaultDataSubId();
Sanket Padawe356d7632015-06-22 14:03:32 -07001505 final Phone phone = getPhone(subId);
1506 if (phone != null) {
1507 phone.setDataEnabled(false);
1508 return true;
1509 } else {
1510 return false;
1511 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001512 }
1513
Wink Saville36469e72014-06-11 15:17:00 -07001514 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001515 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001516 public boolean isDataConnectivityPossible() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001517 int subId = mSubscriptionController.getDefaultDataSubId();
Sanket Padawe356d7632015-06-22 14:03:32 -07001518 final Phone phone = getPhone(subId);
1519 if (phone != null) {
1520 return phone.isDataConnectivityPossible();
1521 } else {
1522 return false;
1523 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001524 }
1525
1526 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001527 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07001528 }
1529
Wink Savilleb564aae2014-10-23 10:18:09 -07001530 public boolean handlePinMmiForSubscriber(int subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001531 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001532 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1533 return false;
1534 }
Wink Saville36469e72014-06-11 15:17:00 -07001535 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001536 }
1537
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001538 public int getCallState() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001539 return getCallStateForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001540 }
1541
Shishir Agrawala9f32182016-04-12 12:00:16 -07001542 public int getCallStateForSlot(int slotId) {
1543 Phone phone = PhoneFactory.getPhone(slotId);
1544 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
1545 DefaultPhoneNotifier.convertCallState(phone.getState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001546 }
1547
Sanket Padawe356d7632015-06-22 14:03:32 -07001548 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001549 public int getDataState() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001550 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
Sanket Padawe356d7632015-06-22 14:03:32 -07001551 if (phone != null) {
1552 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
1553 } else {
1554 return DefaultPhoneNotifier.convertDataState(PhoneConstants.DataState.DISCONNECTED);
1555 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001556 }
1557
Sanket Padawe356d7632015-06-22 14:03:32 -07001558 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001559 public int getDataActivity() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001560 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
Sanket Padawe356d7632015-06-22 14:03:32 -07001561 if (phone != null) {
1562 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
1563 } else {
1564 return TelephonyManager.DATA_ACTIVITY_NONE;
1565 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001566 }
1567
1568 @Override
Svetoslav64fad262015-04-14 14:35:21 -07001569 public Bundle getCellLocation(String callingPackage) {
1570 enforceFineOrCoarseLocationPermission("getCellLocation");
1571
1572 // OP_COARSE_LOCATION controls both fine and coarse location.
1573 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1574 callingPackage) != AppOpsManager.MODE_ALLOWED) {
Amit Mahajan9acc70d2015-06-02 13:17:33 -07001575 log("getCellLocation: returning null; mode != allowed");
Svetoslav64fad262015-04-14 14:35:21 -07001576 return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001577 }
1578
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001579 if (checkIfCallerIsSelfOrForegroundUser() ||
1580 checkCallerInteractAcrossUsersFull()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001581 if (DBG_LOC) log("getCellLocation: is active user");
1582 Bundle data = new Bundle();
Legler Wu2c01cdf2014-12-08 19:00:59 +08001583 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
Sanket Padawe356d7632015-06-22 14:03:32 -07001584 if (phone == null) {
1585 return null;
1586 }
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07001587
1588 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
1589 phone.getCellLocation(workSource).fillInNotifierBundle(data);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001590 return data;
1591 } else {
Amit Mahajan9acc70d2015-06-02 13:17:33 -07001592 log("getCellLocation: suppress non-active user");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001593 return null;
1594 }
1595 }
1596
Svetoslav64fad262015-04-14 14:35:21 -07001597 private void enforceFineOrCoarseLocationPermission(String message) {
1598 try {
1599 mApp.enforceCallingOrSelfPermission(
1600 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1601 } catch (SecurityException e) {
1602 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1603 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1604 // is the weaker precondition
1605 mApp.enforceCallingOrSelfPermission(
1606 android.Manifest.permission.ACCESS_COARSE_LOCATION, message);
1607 }
1608 }
1609
1610
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001611 @Override
1612 public void enableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001613 enableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001614 }
1615
Sanket Padawe356d7632015-06-22 14:03:32 -07001616 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001617 public void enableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001618 mApp.enforceCallingOrSelfPermission(
1619 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Sanket Padawe356d7632015-06-22 14:03:32 -07001620 final Phone phone = getPhone(subId);
1621 if (phone != null) {
1622 phone.enableLocationUpdates();
1623 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001624 }
1625
1626 @Override
1627 public void disableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001628 disableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001629 }
1630
Sanket Padawe356d7632015-06-22 14:03:32 -07001631 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001632 public void disableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001633 mApp.enforceCallingOrSelfPermission(
1634 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Sanket Padawe356d7632015-06-22 14:03:32 -07001635 final Phone phone = getPhone(subId);
1636 if (phone != null) {
1637 phone.disableLocationUpdates();
1638 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001639 }
1640
1641 @Override
1642 @SuppressWarnings("unchecked")
1643 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
Svetoslav64fad262015-04-14 14:35:21 -07001644 enforceFineOrCoarseLocationPermission("getNeighboringCellInfo");
1645
1646 // OP_COARSE_LOCATION controls both fine and coarse location.
1647 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1648 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1649 return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001650 }
1651
1652 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1653 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1654 return null;
1655 }
Svetoslav64fad262015-04-14 14:35:21 -07001656
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001657 if (checkIfCallerIsSelfOrForegroundUser() ||
1658 checkCallerInteractAcrossUsersFull()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001659 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1660
1661 ArrayList<NeighboringCellInfo> cells = null;
1662
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07001663 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001664 try {
1665 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07001666 CMD_HANDLE_NEIGHBORING_CELL, workSource,
Sanket Padawe56e75a32016-02-08 12:18:19 -08001667 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001668 } catch (RuntimeException e) {
Wink Saville36469e72014-06-11 15:17:00 -07001669 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001670 }
1671 return cells;
1672 } else {
1673 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1674 return null;
1675 }
1676 }
1677
1678
1679 @Override
Svetoslav64fad262015-04-14 14:35:21 -07001680 public List<CellInfo> getAllCellInfo(String callingPackage) {
1681 enforceFineOrCoarseLocationPermission("getAllCellInfo");
1682
1683 // OP_COARSE_LOCATION controls both fine and coarse location.
1684 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1685 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1686 return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001687 }
1688
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001689 if (checkIfCallerIsSelfOrForegroundUser() ||
1690 checkCallerInteractAcrossUsersFull()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001691 if (DBG_LOC) log("getAllCellInfo: is active user");
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07001692 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
Legler Wu2c01cdf2014-12-08 19:00:59 +08001693 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
1694 for (Phone phone : PhoneFactory.getPhones()) {
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07001695 final List<CellInfo> info = phone.getAllCellInfo(workSource);
1696 if (info != null) cellInfos.addAll(info);
Legler Wu2c01cdf2014-12-08 19:00:59 +08001697 }
1698 return cellInfos;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001699 } else {
1700 if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1701 return null;
1702 }
1703 }
1704
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001705 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001706 public void setCellInfoListRate(int rateInMillis) {
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07001707 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
1708 mPhone.setCellInfoListRate(rateInMillis, workSource);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001709 }
1710
Shishir Agrawala9f32182016-04-12 12:00:16 -07001711 @Override
1712 public String getImeiForSlot(int slotId, String callingPackage) {
1713 if (!canReadPhoneState(callingPackage, "getImeiForSlot")) {
1714 return null;
1715 }
1716 Phone phone = PhoneFactory.getPhone(slotId);
1717 return phone == null ? null : phone.getImei();
1718 }
1719
1720 @Override
1721 public String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage) {
1722 if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) {
1723 return null;
1724 }
1725 Phone phone = PhoneFactory.getPhone(slotId);
1726 return phone == null ? null : phone.getDeviceSvn();
1727 }
1728
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001729 //
1730 // Internal helper methods.
1731 //
1732
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001733 /**
1734 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL.
1735 */
1736 private boolean checkCallerInteractAcrossUsersFull() {
1737 return mPhone.getContext().checkCallingOrSelfPermission(
1738 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1739 == PackageManager.PERMISSION_GRANTED;
1740 }
1741
Jake Hambye994d462014-02-03 13:10:13 -08001742 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001743 boolean ok;
1744
1745 boolean self = Binder.getCallingUid() == Process.myUid();
1746 if (!self) {
1747 // Get the caller's user id then clear the calling identity
1748 // which will be restored in the finally clause.
1749 int callingUser = UserHandle.getCallingUserId();
1750 long ident = Binder.clearCallingIdentity();
1751
1752 try {
1753 // With calling identity cleared the current user is the foreground user.
1754 int foregroundUser = ActivityManager.getCurrentUser();
1755 ok = (foregroundUser == callingUser);
1756 if (DBG_LOC) {
1757 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1758 + " callingUser=" + callingUser + " ok=" + ok);
1759 }
1760 } catch (Exception ex) {
1761 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1762 ok = false;
1763 } finally {
1764 Binder.restoreCallingIdentity(ident);
1765 }
1766 } else {
1767 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1768 ok = true;
1769 }
1770 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1771 return ok;
1772 }
1773
1774 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001775 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1776 *
1777 * @throws SecurityException if the caller does not have the required permission
1778 */
1779 private void enforceModifyPermission() {
1780 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1781 }
1782
1783 /**
Junda Liua2e36012014-07-09 18:30:01 -07001784 * Make sure either system app or the caller has carrier privilege.
1785 *
1786 * @throws SecurityException if the caller does not have the required permission/privilege
1787 */
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001788 private void enforceModifyPermissionOrCarrierPrivilege(int subId) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001789 int permission = mApp.checkCallingOrSelfPermission(
1790 android.Manifest.permission.MODIFY_PHONE_STATE);
1791 if (permission == PackageManager.PERMISSION_GRANTED) {
1792 return;
1793 }
1794
1795 log("No modify permission, check carrier privilege next.");
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001796 enforceCarrierPrivilege(subId);
Junda Liua2e36012014-07-09 18:30:01 -07001797 }
1798
1799 /**
1800 * Make sure the caller has carrier privilege.
1801 *
1802 * @throws SecurityException if the caller does not have the required permission
1803 */
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001804 private void enforceCarrierPrivilege(int subId) {
1805 if (getCarrierPrivilegeStatus(subId) !=
1806 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001807 loge("No Carrier Privilege.");
1808 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001809 }
1810 }
1811
1812 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001813 * Make sure the caller has the CALL_PHONE permission.
1814 *
1815 * @throws SecurityException if the caller does not have the required permission
1816 */
1817 private void enforceCallPermission() {
1818 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1819 }
1820
Stuart Scott8eef64f2015-04-08 15:13:54 -07001821 private void enforceConnectivityInternalPermission() {
1822 mApp.enforceCallingOrSelfPermission(
1823 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1824 "ConnectivityService");
1825 }
1826
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001827 private String createTelUrl(String number) {
1828 if (TextUtils.isEmpty(number)) {
1829 return null;
1830 }
1831
Jake Hambye994d462014-02-03 13:10:13 -08001832 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001833 }
1834
Ihab Awadf9e92732013-12-05 18:02:52 -08001835 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001836 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1837 }
1838
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001839 private static void logv(String msg) {
1840 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1841 }
1842
Ihab Awadf9e92732013-12-05 18:02:52 -08001843 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001844 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1845 }
1846
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001847 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001848 public int getActivePhoneType() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001849 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001850 }
1851
Sanket Padawe356d7632015-06-22 14:03:32 -07001852 @Override
Shishir Agrawala9f32182016-04-12 12:00:16 -07001853 public int getActivePhoneTypeForSlot(int slotId) {
1854 final Phone phone = PhoneFactory.getPhone(slotId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001855 if (phone == null) {
1856 return PhoneConstants.PHONE_TYPE_NONE;
1857 } else {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001858 return phone.getPhoneType();
Sanket Padawe356d7632015-06-22 14:03:32 -07001859 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001860 }
1861
1862 /**
1863 * Returns the CDMA ERI icon index to display
1864 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001865 @Override
1866 public int getCdmaEriIconIndex(String callingPackage) {
1867 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001868 }
1869
Sanket Padawe356d7632015-06-22 14:03:32 -07001870 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001871 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
1872 if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
1873 return -1;
1874 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001875 final Phone phone = getPhone(subId);
1876 if (phone != null) {
1877 return phone.getCdmaEriIconIndex();
1878 } else {
1879 return -1;
1880 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001881 }
1882
1883 /**
1884 * Returns the CDMA ERI icon mode,
1885 * 0 - ON
1886 * 1 - FLASHING
1887 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001888 @Override
1889 public int getCdmaEriIconMode(String callingPackage) {
1890 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001891 }
1892
Sanket Padawe356d7632015-06-22 14:03:32 -07001893 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001894 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
1895 if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
1896 return -1;
1897 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001898 final Phone phone = getPhone(subId);
1899 if (phone != null) {
1900 return phone.getCdmaEriIconMode();
1901 } else {
1902 return -1;
1903 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001904 }
1905
1906 /**
1907 * Returns the CDMA ERI text,
1908 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001909 @Override
1910 public String getCdmaEriText(String callingPackage) {
1911 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001912 }
1913
Sanket Padawe356d7632015-06-22 14:03:32 -07001914 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001915 public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
1916 if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
1917 return null;
1918 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001919 final Phone phone = getPhone(subId);
1920 if (phone != null) {
1921 return phone.getCdmaEriText();
1922 } else {
1923 return null;
1924 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001925 }
1926
1927 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001928 * Returns the CDMA MDN.
1929 */
Sanket Padawe356d7632015-06-22 14:03:32 -07001930 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001931 public String getCdmaMdn(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001932 enforceModifyPermissionOrCarrierPrivilege(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001933 final Phone phone = getPhone(subId);
1934 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
1935 return phone.getLine1Number();
Junda Liuca05d5d2014-08-14 22:36:34 -07001936 } else {
1937 return null;
1938 }
1939 }
1940
1941 /**
1942 * Returns the CDMA MIN.
1943 */
Sanket Padawe356d7632015-06-22 14:03:32 -07001944 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001945 public String getCdmaMin(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001946 enforceModifyPermissionOrCarrierPrivilege(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001947 final Phone phone = getPhone(subId);
1948 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1949 return phone.getCdmaMin();
Junda Liuca05d5d2014-08-14 22:36:34 -07001950 } else {
1951 return null;
1952 }
1953 }
1954
1955 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001956 * Returns true if CDMA provisioning needs to run.
1957 */
1958 public boolean needsOtaServiceProvisioning() {
1959 return mPhone.needsOtaServiceProvisioning();
1960 }
1961
1962 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001963 * Sets the voice mail number of a given subId.
1964 */
1965 @Override
1966 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001967 enforceCarrierPrivilege(subId);
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001968 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
1969 new Pair<String, String>(alphaTag, number), new Integer(subId));
1970 return success;
1971 }
1972
Ta-wei Yen87c49842016-05-13 21:19:52 -07001973 @Override
Ta-wei Yenb0f695b2016-08-08 17:33:11 -07001974 public void setVisualVoicemailEnabled(String callingPackage,
1975 PhoneAccountHandle phoneAccountHandle, boolean enabled) {
1976 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1977 if (!TextUtils.equals(callingPackage,
1978 TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
1979 enforceModifyPermissionOrCarrierPrivilege(
1980 PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
1981 }
1982 VisualVoicemailSettingsUtil.setEnabled(mPhone.getContext(), phoneAccountHandle, enabled);
1983 }
1984
1985 @Override
1986 public boolean isVisualVoicemailEnabled(String callingPackage,
1987 PhoneAccountHandle phoneAccountHandle) {
1988 if (!canReadPhoneState(callingPackage, "isVisualVoicemailEnabled")) {
1989 return false;
1990 }
1991 return VisualVoicemailSettingsUtil.isEnabled(mPhone.getContext(), phoneAccountHandle);
1992 }
1993
1994 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07001995 public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
1996 VisualVoicemailSmsFilterSettings settings) {
1997 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001998 VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07001999 .enableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId,
2000 settings);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002001 }
2002
2003 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002004 public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
2005 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002006 VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002007 .disableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002008 }
2009
2010 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002011 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
2012 String callingPackage, int subId) {
2013 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002014 return VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002015 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), callingPackage, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002016 }
2017
2018 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002019 public VisualVoicemailSmsFilterSettings getSystemVisualVoicemailSmsFilterSettings(
2020 String packageName, int subId) {
2021 enforceReadPrivilegedPermission();
Ta-wei Yen87c49842016-05-13 21:19:52 -07002022 return VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002023 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), packageName, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002024 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002025 /**
fionaxuef039d42016-11-14 13:36:14 -08002026 * Sets the voice activation state of a given subId.
2027 */
2028 @Override
2029 public void setVoiceActivationState(int subId, int activationState) {
2030 enforceModifyPermissionOrCarrierPrivilege(subId);
2031 final Phone phone = getPhone(subId);
2032 if (phone != null) {
2033 phone.setVoiceActivationState(activationState);
2034 } else {
2035 loge("setVoiceActivationState fails with invalid subId: " + subId);
2036 }
2037 }
2038
2039 /**
2040 * Sets the data activation state of a given subId.
2041 */
2042 @Override
2043 public void setDataActivationState(int subId, int activationState) {
2044 enforceModifyPermissionOrCarrierPrivilege(subId);
2045 final Phone phone = getPhone(subId);
2046 if (phone != null) {
2047 phone.setDataActivationState(activationState);
2048 } else {
2049 loge("setVoiceActivationState fails with invalid subId: " + subId);
2050 }
2051 }
2052
2053 /**
2054 * Returns the voice activation state of a given subId.
2055 */
2056 @Override
2057 public int getVoiceActivationState(int subId, String callingPackage) {
2058 if (!canReadPhoneState(callingPackage, "getVoiceActivationStateForSubscriber")) {
2059 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2060 }
2061 final Phone phone = getPhone(subId);
2062 if (phone != null) {
2063 return phone.getVoiceActivationState();
2064 } else {
2065 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2066 }
2067 }
2068
2069 /**
2070 * Returns the data activation state of a given subId.
2071 */
2072 @Override
2073 public int getDataActivationState(int subId, String callingPackage) {
2074 if (!canReadPhoneState(callingPackage, "getDataActivationStateForSubscriber")) {
2075 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2076 }
2077 final Phone phone = getPhone(subId);
2078 if (phone != null) {
2079 return phone.getDataActivationState();
2080 } else {
2081 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2082 }
2083 }
2084
2085 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002086 * Returns the unread count of voicemails
2087 */
2088 public int getVoiceMessageCount() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07002089 return getVoiceMessageCountForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07002090 }
2091
2092 /**
2093 * Returns the unread count of voicemails for a subId
2094 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002095 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002096 public int getVoiceMessageCountForSubscriber( int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002097 final Phone phone = getPhone(subId);
2098 if (phone != null) {
2099 return phone.getVoiceMessageCount();
2100 } else {
2101 return 0;
2102 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002103 }
2104
2105 /**
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002106 * Returns the data network type.
2107 * Legacy call, permission-free.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002108 *
2109 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
2110 */
2111 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002112 public int getNetworkType() {
2113 final Phone phone = getPhone(getDefaultSubscription());
2114 if (phone != null) {
2115 return phone.getServiceState().getDataNetworkType();
2116 } else {
2117 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2118 }
Wink Saville36469e72014-06-11 15:17:00 -07002119 }
2120
2121 /**
2122 * Returns the network type for a subId
2123 */
2124 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002125 public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
2126 if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
2127 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2128 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002129
Sanket Padawe356d7632015-06-22 14:03:32 -07002130 final Phone phone = getPhone(subId);
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002131 if (phone != null) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002132 return phone.getServiceState().getDataNetworkType();
2133 } else {
2134 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2135 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002136 }
2137
2138 /**
2139 * Returns the data network type
2140 */
2141 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002142 public int getDataNetworkType(String callingPackage) {
2143 return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002144 }
2145
2146 /**
2147 * Returns the data network type for a subId
2148 */
2149 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002150 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
2151 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2152 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2153 }
2154
Sanket Padawe356d7632015-06-22 14:03:32 -07002155 final Phone phone = getPhone(subId);
2156 if (phone != null) {
2157 return phone.getServiceState().getDataNetworkType();
2158 } else {
2159 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2160 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002161 }
2162
2163 /**
Wink Saville36469e72014-06-11 15:17:00 -07002164 * Returns the Voice network type for a subId
2165 */
2166 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002167 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
2168 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2169 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2170 }
2171
Sanket Padawe356d7632015-06-22 14:03:32 -07002172 final Phone phone = getPhone(subId);
2173 if (phone != null) {
2174 return phone.getServiceState().getVoiceNetworkType();
2175 } else {
2176 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2177 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002178 }
2179
2180 /**
2181 * @return true if a ICC card is present
2182 */
2183 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07002184 // FIXME Make changes to pass defaultSimId of type int
Amit Mahajana6fc2a82015-01-06 11:53:51 -08002185 return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -07002186 }
2187
2188 /**
2189 * @return true if a ICC card is present for a slotId
2190 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002191 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002192 public boolean hasIccCardUsingSlotId(int slotId) {
Amit Mahajana6fc2a82015-01-06 11:53:51 -08002193 int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId);
Sanket Padawe356d7632015-06-22 14:03:32 -07002194 final Phone phone = getPhone(subId[0]);
2195 if (subId != null && phone != null) {
2196 return phone.getIccCard().hasIccCard();
Amit Mahajana6fc2a82015-01-06 11:53:51 -08002197 } else {
2198 return false;
2199 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002200 }
2201
2202 /**
2203 * Return if the current radio is LTE on CDMA. This
2204 * is a tri-state return value as for a period of time
2205 * the mode may be unknown.
2206 *
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002207 * @param callingPackage the name of the package making the call.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002208 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08002209 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002210 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002211 @Override
2212 public int getLteOnCdmaMode(String callingPackage) {
2213 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002214 }
2215
Sanket Padawe356d7632015-06-22 14:03:32 -07002216 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002217 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
2218 if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
2219 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2220 }
2221
Sanket Padawe356d7632015-06-22 14:03:32 -07002222 final Phone phone = getPhone(subId);
2223 if (phone == null) {
2224 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2225 } else {
2226 return phone.getLteOnCdmaMode();
2227 }
Wink Saville36469e72014-06-11 15:17:00 -07002228 }
2229
2230 public void setPhone(Phone phone) {
2231 mPhone = phone;
2232 }
2233
2234 /**
2235 * {@hide}
2236 * Returns Default subId, 0 in the case of single standby.
2237 */
Wink Savilleb564aae2014-10-23 10:18:09 -07002238 private int getDefaultSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08002239 return mSubscriptionController.getDefaultSubId();
Wink Saville36469e72014-06-11 15:17:00 -07002240 }
2241
Shishir Agrawala9f32182016-04-12 12:00:16 -07002242 private int getSlotForDefaultSubscription() {
2243 return mSubscriptionController.getPhoneId(getDefaultSubscription());
2244 }
2245
Wink Savilleb564aae2014-10-23 10:18:09 -07002246 private int getPreferredVoiceSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08002247 return mSubscriptionController.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002248 }
Ihab Awadf2177b72013-11-25 13:33:23 -08002249
2250 /**
2251 * @see android.telephony.TelephonyManager.WifiCallingChoices
2252 */
2253 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08002254 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
2255 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08002256 }
2257
2258 /**
2259 * @see android.telephony.TelephonyManager.WifiCallingChoices
2260 */
2261 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08002262 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
2263 Settings.System.putInt(mPhone.getContext().getContentResolver(),
2264 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08002265 }
2266
Sailesh Nepald1e68152013-12-12 19:08:02 -08002267 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07002268 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08002269 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08002270 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08002271
Shishir Agrawal566b7612013-10-28 14:41:00 -07002272 @Override
Ajay Nambiabd73502015-12-03 13:50:00 -08002273 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002274 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002275
Ajay Nambiabd73502015-12-03 13:50:00 -08002276 if (DBG) log("iccOpenLogicalChannel: subId=" + subId + " aid=" + AID + " p2=" + p2);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002277 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
Ajay Nambiabd73502015-12-03 13:50:00 -08002278 CMD_OPEN_CHANNEL, new Pair<String, Integer>(AID, p2), subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002279 if (DBG) log("iccOpenLogicalChannel: " + response);
2280 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07002281 }
2282
2283 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002284 public boolean iccCloseLogicalChannel(int subId, int channel) {
2285 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002286
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002287 if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002288 if (channel < 0) {
2289 return false;
2290 }
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002291 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel, subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002292 if (DBG) log("iccCloseLogicalChannel: " + success);
2293 return success;
2294 }
2295
2296 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002297 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
Shishir Agrawal566b7612013-10-28 14:41:00 -07002298 int command, int p1, int p2, int p3, String data) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002299 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002300
2301 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002302 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel +
2303 " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
Shishir Agrawal566b7612013-10-28 14:41:00 -07002304 " data=" + data);
2305 }
2306
2307 if (channel < 0) {
2308 return "";
2309 }
2310
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002311 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002312 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002313 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
2314
Shishir Agrawal566b7612013-10-28 14:41:00 -07002315 // Append the returned status code to the end of the response payload.
2316 String s = Integer.toHexString(
2317 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07002318 if (response.payload != null) {
2319 s = IccUtils.bytesToHexString(response.payload) + s;
2320 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07002321 return s;
2322 }
Jake Hambye994d462014-02-03 13:10:13 -08002323
Evan Charltonc66da362014-05-16 14:06:40 -07002324 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002325 public String iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002326 int p3, String data) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002327 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002328
2329 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002330 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd=" + command
2331 + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002332 }
2333
2334 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002335 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002336 if (DBG) log("iccTransmitApduBasicChannel: " + response);
2337
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002338 // Append the returned status code to the end of the response payload.
2339 String s = Integer.toHexString(
2340 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07002341 if (response.payload != null) {
2342 s = IccUtils.bytesToHexString(response.payload) + s;
2343 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002344 return s;
2345 }
2346
2347 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002348 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002349 String filePath) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002350 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002351
2352 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002353 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " +
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002354 p1 + " " + p2 + " " + p3 + ":" + filePath);
2355 }
2356
2357 IccIoResult response =
2358 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002359 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
2360 subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002361
2362 if (DBG) {
2363 log("Exchange SIM_IO [R]" + response);
2364 }
2365
2366 byte[] result = null;
2367 int length = 2;
2368 if (response.payload != null) {
2369 length = 2 + response.payload.length;
2370 result = new byte[length];
2371 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
2372 } else {
2373 result = new byte[length];
2374 }
2375
2376 result[length - 1] = (byte) response.sw2;
2377 result[length - 2] = (byte) response.sw1;
2378 return result;
2379 }
2380
Nathan Haroldb3014052017-01-25 15:57:32 -08002381 /**
2382 * Get the forbidden PLMN List from the given app type (ex APPTYPE_USIM)
2383 * on a particular subscription
2384 */
2385 public String[] getForbiddenPlmns(int subId, int appType) {
2386 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
2387 "Requires READ_PRIVILEGED_PHONE_STATE");
2388 if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
2389 loge("getForbiddenPlmnList(): App Type must be USIM or SIM");
2390 return null;
2391 }
2392 Object response = sendRequest(
2393 CMD_GET_FORBIDDEN_PLMNS, new Integer(appType), subId);
2394 if (response instanceof String[]) {
2395 return (String[]) response;
2396 }
2397 // Response is an Exception of some kind, which is signalled to the user as a NULL retval
2398 return null;
2399 }
2400
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002401 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002402 public String sendEnvelopeWithStatus(int subId, String content) {
2403 enforceModifyPermissionOrCarrierPrivilege(subId);
Evan Charltonc66da362014-05-16 14:06:40 -07002404
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002405 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId);
Evan Charltonc66da362014-05-16 14:06:40 -07002406 if (response.payload == null) {
2407 return "";
2408 }
2409
2410 // Append the returned status code to the end of the response payload.
2411 String s = Integer.toHexString(
2412 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2413 s = IccUtils.bytesToHexString(response.payload) + s;
2414 return s;
2415 }
2416
Jake Hambye994d462014-02-03 13:10:13 -08002417 /**
2418 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2419 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2420 *
2421 * @param itemID the ID of the item to read
2422 * @return the NV item as a String, or null on error.
2423 */
2424 @Override
2425 public String nvReadItem(int itemID) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002426 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002427 if (DBG) log("nvReadItem: item " + itemID);
2428 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
2429 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
2430 return value;
2431 }
2432
2433 /**
2434 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2435 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2436 *
2437 * @param itemID the ID of the item to read
2438 * @param itemValue the value to write, as a String
2439 * @return true on success; false on any failure
2440 */
2441 @Override
2442 public boolean nvWriteItem(int itemID, String itemValue) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002443 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002444 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
2445 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
2446 new Pair<Integer, String>(itemID, itemValue));
2447 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
2448 return success;
2449 }
2450
2451 /**
2452 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
2453 * Used for device configuration by some CDMA operators.
2454 *
2455 * @param preferredRoamingList byte array containing the new PRL
2456 * @return true on success; false on any failure
2457 */
2458 @Override
2459 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002460 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002461 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
2462 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
2463 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
2464 return success;
2465 }
2466
2467 /**
2468 * Perform the specified type of NV config reset.
2469 * Used for device configuration by some CDMA operators.
2470 *
2471 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
2472 * @return true on success; false on any failure
2473 */
2474 @Override
2475 public boolean nvResetConfig(int resetType) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002476 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002477 if (DBG) log("nvResetConfig: type " + resetType);
2478 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
2479 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
2480 return success;
2481 }
Jake Hamby7c27be32014-03-03 13:25:59 -08002482
2483 /**
Wink Saville36469e72014-06-11 15:17:00 -07002484 * {@hide}
2485 * Returns Default sim, 0 in the case of single standby.
2486 */
2487 public int getDefaultSim() {
2488 //TODO Need to get it from Telephony Devcontroller
2489 return 0;
2490 }
2491
Svet Ganovb320e182015-04-16 12:30:10 -07002492 public String[] getPcscfAddress(String apnType, String callingPackage) {
2493 if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
2494 return new String[0];
2495 }
2496
2497
ram87fca6f2014-07-18 18:58:44 +05302498 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07002499 }
2500
Brad Ebinger76681002017-01-23 13:50:20 -08002501 /**
2502 * Returns the {@link IImsServiceController} that corresponds to the given slot Id and IMS
2503 * feature or {@link null} if the service is not available. If an ImsServiceController is
2504 * available, the {@link IImsServiceFeatureListener} callback is registered as a listener for
2505 * feature updates.
2506 */
2507 public IImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
2508 IImsServiceFeatureListener callback) {
2509 enforceModifyPermission();
2510 return PhoneFactory.getImsResolver().getImsServiceControllerAndListen(slotId, feature,
2511 callback);
2512 }
2513
Wink Saville36469e72014-06-11 15:17:00 -07002514 public void setImsRegistrationState(boolean registered) {
2515 enforceModifyPermission();
2516 mPhone.setImsRegistrationState(registered);
2517 }
2518
2519 /**
Stuart Scott54788802015-03-30 13:18:01 -07002520 * Set the network selection mode to automatic.
2521 *
2522 */
2523 @Override
2524 public void setNetworkSelectionModeAutomatic(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002525 enforceModifyPermissionOrCarrierPrivilege(subId);
Stuart Scott54788802015-03-30 13:18:01 -07002526 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
2527 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
2528 }
2529
2530 /**
Shishir Agrawal302c8692015-06-19 13:49:39 -07002531 * Set the network selection mode to manual with the selected carrier.
2532 */
2533 @Override
Shishir Agrawal77ba3172015-09-10 14:50:19 -07002534 public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
2535 boolean persistSelection) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002536 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002537 if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
Shishir Agrawal77ba3172015-09-10 14:50:19 -07002538 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
2539 persistSelection);
2540 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002541 }
2542
2543 /**
2544 * Scans for available networks.
2545 */
2546 @Override
2547 public CellNetworkScanResult getCellNetworkScanResults(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002548 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002549 if (DBG) log("getCellNetworkScanResults: subId " + subId);
2550 CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
2551 CMD_PERFORM_NETWORK_SCAN, null, subId);
2552 return result;
2553 }
2554
2555 /**
Junda Liu84d15a22014-07-02 11:21:04 -07002556 * Get the calculated preferred network type.
2557 * Used for debugging incorrect network type.
2558 *
2559 * @return the preferred network type, defined in RILConstants.java.
2560 */
2561 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002562 public int getCalculatedPreferredNetworkType(String callingPackage) {
2563 if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
2564 return RILConstants.PREFERRED_NETWORK_MODE;
2565 }
2566
Amit Mahajan43330e02014-11-18 11:54:45 -08002567 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07002568 }
2569
2570 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08002571 * Get the preferred network type.
2572 * Used for device configuration by some CDMA operators.
2573 *
2574 * @return the preferred network type, defined in RILConstants.java.
2575 */
2576 @Override
Stuart Scott54788802015-03-30 13:18:01 -07002577 public int getPreferredNetworkType(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002578 enforceModifyPermissionOrCarrierPrivilege(subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002579 if (DBG) log("getPreferredNetworkType");
Stuart Scott54788802015-03-30 13:18:01 -07002580 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002581 int networkType = (result != null ? result[0] : -1);
2582 if (DBG) log("getPreferredNetworkType: " + networkType);
2583 return networkType;
2584 }
2585
2586 /**
2587 * Set the preferred network type.
2588 * Used for device configuration by some CDMA operators.
2589 *
2590 * @param networkType the preferred network type, defined in RILConstants.java.
2591 * @return true on success; false on any failure.
2592 */
2593 @Override
Stuart Scott54788802015-03-30 13:18:01 -07002594 public boolean setPreferredNetworkType(int subId, int networkType) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002595 enforceModifyPermissionOrCarrierPrivilege(subId);
Stuart Scott54788802015-03-30 13:18:01 -07002596 if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
2597 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002598 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07002599 if (success) {
2600 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
Stuart Scott54788802015-03-30 13:18:01 -07002601 Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
Junda Liu80bc0d12014-07-14 16:36:44 -07002602 }
Jake Hamby7c27be32014-03-03 13:25:59 -08002603 return success;
2604 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002605
2606 /**
Junda Liu475951f2014-11-07 16:45:03 -08002607 * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
2608 * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
2609 * tethering.
2610 *
2611 * @return 0: Not required. 1: required. 2: Not set.
2612 * @hide
2613 */
2614 @Override
2615 public int getTetherApnRequired() {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002616 enforceModifyPermission();
Junda Liu475951f2014-11-07 16:45:03 -08002617 int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2618 Settings.Global.TETHER_DUN_REQUIRED, 2);
2619 // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2620 // config_tether_apndata.
2621 if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2622 dunRequired = 1;
2623 }
2624 return dunRequired;
2625 }
2626
2627 /**
Robert Greenwalted86e582014-05-21 20:03:20 -07002628 * Set mobile data enabled
2629 * Used by the user through settings etc to turn on/off mobile data
2630 *
2631 * @param enable {@code true} turn turn data on, else {@code false}
2632 */
2633 @Override
Wink Savillee7353bb2014-12-05 14:21:41 -08002634 public void setDataEnabled(int subId, boolean enable) {
Jeff Davidsonf7eecf02016-11-18 17:05:56 -08002635 enforceModifyPermissionOrCarrierPrivilege(subId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002636 int phoneId = mSubscriptionController.getPhoneId(subId);
Joe Onoratoa601dd22016-02-23 13:03:53 -08002637 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002638 Phone phone = PhoneFactory.getPhone(phoneId);
2639 if (phone != null) {
Joe Onoratoa601dd22016-02-23 13:03:53 -08002640 if (DBG) log("setDataEnabled: subId=" + subId + " enable=" + enable);
Wink Savillee7353bb2014-12-05 14:21:41 -08002641 phone.setDataEnabled(enable);
2642 } else {
2643 loge("setDataEnabled: no phone for subId=" + subId);
2644 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002645 }
2646
2647 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07002648 * Get whether mobile data is enabled.
2649 *
Jeff Davidsonf7eecf02016-11-18 17:05:56 -08002650 * Accepts either ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE or carrier privileges.
Robert Greenwalted86e582014-05-21 20:03:20 -07002651 *
2652 * @return {@code true} if data is enabled else {@code false}
2653 */
2654 @Override
Wink Savillee7353bb2014-12-05 14:21:41 -08002655 public boolean getDataEnabled(int subId) {
Robert Greenwalt646120a2014-05-23 11:54:03 -07002656 try {
2657 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2658 null);
2659 } catch (Exception e) {
Jeff Davidsonf7eecf02016-11-18 17:05:56 -08002660 enforceModifyPermissionOrCarrierPrivilege(subId);
Robert Greenwalt646120a2014-05-23 11:54:03 -07002661 }
Wink Savillee7353bb2014-12-05 14:21:41 -08002662 int phoneId = mSubscriptionController.getPhoneId(subId);
Joe Onoratoa601dd22016-02-23 13:03:53 -08002663 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002664 Phone phone = PhoneFactory.getPhone(phoneId);
2665 if (phone != null) {
2666 boolean retVal = phone.getDataEnabled();
Joe Onoratoa601dd22016-02-23 13:03:53 -08002667 if (DBG) log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
Wink Savillee7353bb2014-12-05 14:21:41 -08002668 return retVal;
2669 } else {
Joe Onoratoa601dd22016-02-23 13:03:53 -08002670 if (DBG) loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
Wink Savillee7353bb2014-12-05 14:21:41 -08002671 return false;
2672 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002673 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07002674
2675 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002676 public int getCarrierPrivilegeStatus(int subId) {
2677 final Phone phone = getPhone(subId);
2678 if (phone == null) {
2679 loge("getCarrierPrivilegeStatus: Invalid subId");
2680 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2681 }
2682 UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002683 if (card == null) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08002684 loge("getCarrierPrivilegeStatus: No UICC");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002685 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2686 }
2687 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002688 phone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07002689 }
Junda Liu29340342014-07-10 15:23:27 -07002690
2691 @Override
Zach Johnson50ecba32015-05-19 00:24:21 -07002692 public int checkCarrierPrivilegesForPackage(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08002693 if (TextUtils.isEmpty(pkgName))
2694 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Shishir Agrawal21409252015-01-15 23:33:50 -08002695 UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002696 if (card == null) {
2697 loge("checkCarrierPrivilegesForPackage: No UICC");
2698 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2699 }
Zach Johnson50ecba32015-05-19 00:24:21 -07002700 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
2701 }
2702
2703 @Override
2704 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08002705 if (TextUtils.isEmpty(pkgName))
2706 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Zach Johnson50ecba32015-05-19 00:24:21 -07002707 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2708 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2709 UiccCard card = UiccController.getInstance().getUiccCard(i);
2710 if (card == null) {
Jonathan Basseri7d320df2015-06-16 12:17:08 -07002711 // No UICC in that slot.
Zach Johnson50ecba32015-05-19 00:24:21 -07002712 continue;
2713 }
2714
2715 result = card.getCarrierPrivilegeStatus(
2716 mPhone.getContext().getPackageManager(), pkgName);
2717 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2718 break;
2719 }
2720 }
2721
2722 return result;
Junda Liu29340342014-07-10 15:23:27 -07002723 }
Derek Tan89e89d42014-07-08 17:00:10 -07002724
2725 @Override
Junda Liue64de782015-04-16 17:19:16 -07002726 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2727 if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2728 loge("phoneId " + phoneId + " is not valid.");
2729 return null;
2730 }
2731 UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002732 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07002733 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002734 return null ;
2735 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07002736 return card.getCarrierPackageNamesForIntent(
Svetoslav483aff72015-04-21 14:16:07 -07002737 mPhone.getContext().getPackageManager(), intent);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002738 }
2739
Amith Yamasani6e118872016-02-19 12:53:51 -08002740 @Override
2741 public List<String> getPackagesWithCarrierPrivileges() {
2742 PackageManager pm = mPhone.getContext().getPackageManager();
2743 List<String> privilegedPackages = new ArrayList<>();
2744 List<PackageInfo> packages = null;
2745 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2746 UiccCard card = UiccController.getInstance().getUiccCard(i);
2747 if (card == null) {
2748 // No UICC in that slot.
2749 continue;
2750 }
2751 if (card.hasCarrierPrivilegeRules()) {
2752 if (packages == null) {
2753 // Only check packages in user 0 for now
2754 packages = pm.getInstalledPackagesAsUser(
2755 PackageManager.MATCH_DISABLED_COMPONENTS
2756 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
2757 | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
2758 }
2759 for (int p = packages.size() - 1; p >= 0; p--) {
2760 PackageInfo pkgInfo = packages.get(p);
2761 if (pkgInfo != null && pkgInfo.packageName != null
2762 && card.getCarrierPrivilegeStatus(pkgInfo)
2763 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2764 privilegedPackages.add(pkgInfo.packageName);
2765 }
2766 }
2767 }
2768 }
2769 return privilegedPackages;
2770 }
2771
Wink Savilleb564aae2014-10-23 10:18:09 -07002772 private String getIccId(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002773 final Phone phone = getPhone(subId);
2774 UiccCard card = phone == null ? null : phone.getUiccCard();
Derek Tan97ebb422014-09-05 16:55:38 -07002775 if (card == null) {
2776 loge("getIccId: No UICC");
2777 return null;
2778 }
2779 String iccId = card.getIccId();
2780 if (TextUtils.isEmpty(iccId)) {
2781 loge("getIccId: ICC ID is null or empty.");
2782 return null;
2783 }
2784 return iccId;
2785 }
2786
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002787 @Override
Jeff Sharkey85190e62014-12-05 09:40:12 -08002788 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
2789 String number) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002790 enforceCarrierPrivilege(subId);
Derek Tan97ebb422014-09-05 16:55:38 -07002791
Jeff Sharkey85190e62014-12-05 09:40:12 -08002792 final String iccId = getIccId(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07002793 final Phone phone = getPhone(subId);
2794 if (phone == null) {
2795 return false;
2796 }
2797 final String subscriberId = phone.getSubscriberId();
Jeff Sharkey85190e62014-12-05 09:40:12 -08002798
2799 if (DBG_MERGE) {
2800 Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
2801 + subscriberId + " to " + number);
2802 }
2803
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002804 if (TextUtils.isEmpty(iccId)) {
2805 return false;
Derek Tan97ebb422014-09-05 16:55:38 -07002806 }
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002807
Jeff Sharkey85190e62014-12-05 09:40:12 -08002808 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2809
2810 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002811 if (alphaTag == null) {
2812 editor.remove(alphaTagPrefKey);
2813 } else {
2814 editor.putString(alphaTagPrefKey, alphaTag);
2815 }
2816
Jeff Sharkey85190e62014-12-05 09:40:12 -08002817 // Record both the line number and IMSI for this ICCID, since we need to
2818 // track all merged IMSIs based on line number
2819 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2820 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002821 if (number == null) {
2822 editor.remove(numberPrefKey);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002823 editor.remove(subscriberPrefKey);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002824 } else {
2825 editor.putString(numberPrefKey, number);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002826 editor.putString(subscriberPrefKey, subscriberId);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002827 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08002828
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002829 editor.commit();
2830 return true;
Derek Tan7226c842014-07-02 17:42:23 -07002831 }
2832
2833 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002834 public String getLine1NumberForDisplay(int subId, String callingPackage) {
Makoto Onukifee69342015-06-29 14:44:50 -07002835 // This is open to apps with WRITE_SMS.
2836 if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
Amit Mahajan9cf11512015-11-09 11:40:48 -08002837 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
Svet Ganovb320e182015-04-16 12:30:10 -07002838 return null;
2839 }
Derek Tan97ebb422014-09-05 16:55:38 -07002840
2841 String iccId = getIccId(subId);
2842 if (iccId != null) {
2843 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
Amit Mahajan9cf11512015-11-09 11:40:48 -08002844 if (DBG_MERGE) {
2845 log("getLine1NumberForDisplay returning " +
2846 mTelephonySharedPreferences.getString(numberPrefKey, null));
2847 }
Andrew Leedf14ead2014-10-17 14:22:52 -07002848 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002849 }
Amit Mahajan9cf11512015-11-09 11:40:48 -08002850 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
Derek Tan97ebb422014-09-05 16:55:38 -07002851 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002852 }
2853
2854 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002855 public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2856 if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2857 return null;
2858 }
Derek Tan97ebb422014-09-05 16:55:38 -07002859
2860 String iccId = getIccId(subId);
2861 if (iccId != null) {
2862 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002863 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002864 }
Derek Tan97ebb422014-09-05 16:55:38 -07002865 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002866 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002867
2868 @Override
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07002869 public String[] getMergedSubscriberIds(String callingPackage) {
2870 if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
2871 return null;
2872 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08002873 final Context context = mPhone.getContext();
2874 final TelephonyManager tele = TelephonyManager.from(context);
2875 final SubscriptionManager sub = SubscriptionManager.from(context);
2876
2877 // Figure out what subscribers are currently active
2878 final ArraySet<String> activeSubscriberIds = new ArraySet<>();
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07002879 // Clear calling identity, when calling TelephonyManager, because callerUid must be
2880 // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail.
2881 final long identity = Binder.clearCallingIdentity();
2882 try {
2883 final int[] subIds = sub.getActiveSubscriptionIdList();
2884 for (int subId : subIds) {
2885 activeSubscriberIds.add(tele.getSubscriberId(subId));
2886 }
2887 } finally {
2888 Binder.restoreCallingIdentity(identity);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002889 }
2890
2891 // First pass, find a number override for an active subscriber
2892 String mergeNumber = null;
2893 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
2894 for (String key : prefs.keySet()) {
2895 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
2896 final String subscriberId = (String) prefs.get(key);
2897 if (activeSubscriberIds.contains(subscriberId)) {
2898 final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
2899 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2900 mergeNumber = (String) prefs.get(numberKey);
2901 if (DBG_MERGE) {
2902 Slog.d(LOG_TAG, "Found line number " + mergeNumber
2903 + " for active subscriber " + subscriberId);
2904 }
2905 if (!TextUtils.isEmpty(mergeNumber)) {
2906 break;
2907 }
2908 }
2909 }
2910 }
2911
2912 // Shortcut when no active merged subscribers
2913 if (TextUtils.isEmpty(mergeNumber)) {
2914 return null;
2915 }
2916
2917 // Second pass, find all subscribers under that line override
2918 final ArraySet<String> result = new ArraySet<>();
2919 for (String key : prefs.keySet()) {
2920 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
2921 final String number = (String) prefs.get(key);
2922 if (mergeNumber.equals(number)) {
2923 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
2924 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2925 final String subscriberId = (String) prefs.get(subscriberKey);
2926 if (!TextUtils.isEmpty(subscriberId)) {
2927 result.add(subscriberId);
2928 }
2929 }
2930 }
2931 }
2932
2933 final String[] resultArray = result.toArray(new String[result.size()]);
2934 Arrays.sort(resultArray);
2935 if (DBG_MERGE) {
2936 Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
2937 }
2938 return resultArray;
2939 }
2940
2941 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002942 public boolean setOperatorBrandOverride(int subId, String brand) {
2943 enforceCarrierPrivilege(subId);
2944 final Phone phone = getPhone(subId);
2945 return phone == null ? false : phone.setOperatorBrandOverride(brand);
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002946 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002947
2948 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002949 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08002950 List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2951 List<String> cdmaNonRoamingList) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002952 enforceCarrierPrivilege(subId);
2953 final Phone phone = getPhone(subId);
2954 if (phone == null) {
2955 return false;
2956 }
2957 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08002958 cdmaNonRoamingList);
2959 }
2960
2961 @Override
Amit Mahajanf43fe462017-02-23 12:08:31 -08002962 @Deprecated
Steven Liu4bf01bc2014-07-17 11:05:29 -05002963 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2964 enforceModifyPermission();
2965
2966 int returnValue = 0;
2967 try {
2968 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2969 if(result.exception == null) {
2970 if (result.result != null) {
2971 byte[] responseData = (byte[])(result.result);
2972 if(responseData.length > oemResp.length) {
2973 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2974 responseData.length + "bytes. Buffer Size is " +
2975 oemResp.length + "bytes.");
2976 }
2977 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2978 returnValue = responseData.length;
2979 }
2980 } else {
2981 CommandException ex = (CommandException) result.exception;
2982 returnValue = ex.getCommandError().ordinal();
2983 if(returnValue > 0) returnValue *= -1;
2984 }
2985 } catch (RuntimeException e) {
2986 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2987 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2988 if(returnValue > 0) returnValue *= -1;
2989 }
2990
2991 return returnValue;
2992 }
Wink Saville5d475dd2014-10-17 15:00:58 -07002993
2994 @Override
2995 public void setRadioCapability(RadioAccessFamily[] rafs) {
2996 try {
2997 ProxyController.getInstance().setRadioCapability(rafs);
2998 } catch (RuntimeException e) {
2999 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
3000 }
3001 }
3002
3003 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003004 public int getRadioAccessFamily(int phoneId, String callingPackage) {
3005 if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
3006 return RadioAccessFamily.RAF_UNKNOWN;
3007 }
3008
Wink Saville5d475dd2014-10-17 15:00:58 -07003009 return ProxyController.getInstance().getRadioAccessFamily(phoneId);
3010 }
Andrew Leedf14ead2014-10-17 14:22:52 -07003011
3012 @Override
3013 public void enableVideoCalling(boolean enable) {
3014 enforceModifyPermission();
Tyler Gunnfdd69de2015-12-04 21:24:38 -08003015 ImsManager.setVtSetting(mPhone.getContext(), enable);
Andrew Leedf14ead2014-10-17 14:22:52 -07003016 }
3017
3018 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07003019 public boolean isVideoCallingEnabled(String callingPackage) {
3020 if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
3021 return false;
3022 }
3023
Andrew Lee77527ac2014-10-21 16:57:39 -07003024 // Check the user preference and the system-level IMS setting. Even if the user has
3025 // enabled video calling, if IMS is disabled we aren't able to support video calling.
3026 // In the long run, we may instead need to check if there exists a connection service
3027 // which can support video calling.
Andrew Lee312e8172014-10-23 17:01:36 -07003028 return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
3029 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
Tyler Gunnfdd69de2015-12-04 21:24:38 -08003030 && ImsManager.isVtEnabledByUser(mPhone.getContext());
Andrew Leedf14ead2014-10-17 14:22:52 -07003031 }
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06003032
Andrew Leea1239f22015-03-02 17:44:07 -08003033 @Override
3034 public boolean canChangeDtmfToneLength() {
Jonathan Basseri9504c6b2015-06-04 14:23:32 -07003035 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
Andrew Leea1239f22015-03-02 17:44:07 -08003036 }
3037
3038 @Override
3039 public boolean isWorldPhone() {
Jonathan Basseri9504c6b2015-06-04 14:23:32 -07003040 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
Andrew Leea1239f22015-03-02 17:44:07 -08003041 }
3042
Andrew Lee9431b832015-03-09 18:46:45 -07003043 @Override
3044 public boolean isTtyModeSupported() {
3045 TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
3046 TelephonyManager telephonyManager =
3047 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
Wooki Wu1f82f7a2016-02-15 15:59:58 +08003048 return telecomManager.isTtySupported();
Andrew Lee9431b832015-03-09 18:46:45 -07003049 }
3050
3051 @Override
3052 public boolean isHearingAidCompatibilitySupported() {
3053 return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
3054 }
3055
Sanket Padawe7310cc72015-01-14 09:53:20 -08003056 /**
3057 * Returns the unique device ID of phone, for example, the IMEI for
3058 * GSM and the MEID for CDMA phones. Return null if device ID is not available.
3059 *
3060 * <p>Requires Permission:
3061 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
3062 */
3063 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07003064 public String getDeviceId(String callingPackage) {
3065 if (!canReadPhoneState(callingPackage, "getDeviceId")) {
3066 return null;
3067 }
3068
Sanket Padawe7310cc72015-01-14 09:53:20 -08003069 final Phone phone = PhoneFactory.getPhone(0);
3070 if (phone != null) {
3071 return phone.getDeviceId();
3072 } else {
3073 return null;
3074 }
3075 }
3076
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06003077 /*
3078 * {@hide}
3079 * Returns the IMS Registration Status
3080 */
Santos Cordon7a1885b2015-02-03 11:15:19 -08003081 @Override
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06003082 public boolean isImsRegistered() {
3083 return mPhone.isImsRegistered();
3084 }
Santos Cordon7a1885b2015-02-03 11:15:19 -08003085
3086 @Override
3087 public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
3088 return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
3089 }
Nathan Harolddcfc7932015-03-18 10:01:20 -07003090
Nathan Haroldc55097a2015-03-11 18:14:50 -07003091 /*
3092 * {@hide}
3093 * Returns the IMS Registration Status
3094 */
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003095 public boolean isWifiCallingAvailable() {
Nathan Haroldc55097a2015-03-11 18:14:50 -07003096 return mPhone.isWifiCallingEnabled();
3097 }
3098
3099 /*
3100 * {@hide}
3101 * Returns the IMS Registration Status
3102 */
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003103 public boolean isVolteAvailable() {
Nathan Haroldc55097a2015-03-11 18:14:50 -07003104 return mPhone.isVolteEnabled();
3105 }
Svet Ganovb320e182015-04-16 12:30:10 -07003106
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003107 /*
3108 * {@hide} Returns the IMS Registration Status
3109 */
3110 public boolean isVideoTelephonyAvailable() {
3111 return mPhone.isVideoEnabled();
3112 }
3113
Svet Ganovb320e182015-04-16 12:30:10 -07003114 private boolean canReadPhoneState(String callingPackage, String message) {
Etan Cohen921655c2015-06-24 13:54:50 -07003115 try {
Amit Mahajan83ea23b2015-07-30 16:05:11 -07003116 mApp.enforceCallingOrSelfPermission(
Etan Cohen921655c2015-06-24 13:54:50 -07003117 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
3118
Amit Mahajan83ea23b2015-07-30 16:05:11 -07003119 // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
Etan Cohen921655c2015-06-24 13:54:50 -07003120 return true;
Amit Mahajan785783f2015-06-29 10:36:50 -07003121 } catch (SecurityException e) {
3122 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
3123 message);
Etan Cohen921655c2015-06-24 13:54:50 -07003124 }
Svet Ganovb320e182015-04-16 12:30:10 -07003125
3126 if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
3127 callingPackage) != AppOpsManager.MODE_ALLOWED) {
3128 return false;
3129 }
3130
3131 return true;
3132 }
Stuart Scott8eef64f2015-04-08 15:13:54 -07003133
Makoto Onukifee69342015-06-29 14:44:50 -07003134 /**
Amit Mahajanb9b49782015-09-15 18:16:32 -07003135 * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
Makoto Onukifee69342015-06-29 14:44:50 -07003136 */
3137 private boolean canReadPhoneNumber(String callingPackage, String message) {
Makoto Onukie4072d12015-08-03 15:12:23 -07003138 // Default SMS app can always read it.
3139 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
3140 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
3141 return true;
3142 }
3143 try {
3144 return canReadPhoneState(callingPackage, message);
Amit Mahajanb9b49782015-09-15 18:16:32 -07003145 } catch (SecurityException readPhoneStateSecurityException) {
3146 try {
3147 // Can be read with READ_SMS too.
3148 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
3149 return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
3150 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
3151 } catch (SecurityException readSmsSecurityException) {
3152 // Throw exception with message including both READ_PHONE_STATE and READ_SMS
3153 // permissions
3154 throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
3155 " nor current process has " + android.Manifest.permission.READ_PHONE_STATE +
3156 " or " + android.Manifest.permission.READ_SMS + ".");
3157 }
Makoto Onukie4072d12015-08-03 15:12:23 -07003158 }
Makoto Onukifee69342015-06-29 14:44:50 -07003159 }
3160
Stuart Scott8eef64f2015-04-08 15:13:54 -07003161 @Override
3162 public void factoryReset(int subId) {
3163 enforceConnectivityInternalPermission();
Stuart Scott981d8582015-04-21 14:09:50 -07003164 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
3165 return;
3166 }
3167
Svet Ganovcc087f82015-05-12 20:35:54 -07003168 final long identity = Binder.clearCallingIdentity();
3169 try {
Stuart Scott981d8582015-04-21 14:09:50 -07003170 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
3171 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Svet Ganovcc087f82015-05-12 20:35:54 -07003172 // Enable data
3173 setDataEnabled(subId, true);
3174 // Set network selection mode to automatic
3175 setNetworkSelectionModeAutomatic(subId);
3176 // Set preferred mobile network type to the best available
3177 setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
3178 // Turn off roaming
3179 SubscriptionManager.from(mApp).setDataRoaming(0, subId);
3180 }
3181 } finally {
3182 Binder.restoreCallingIdentity(identity);
Stuart Scott8eef64f2015-04-08 15:13:54 -07003183 }
3184 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01003185
3186 @Override
3187 public String getLocaleFromDefaultSim() {
3188 // We query all subscriptions instead of just the active ones, because
3189 // this might be called early on in the provisioning flow when the
3190 // subscriptions potentially aren't active yet.
3191 final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
3192 if (slist == null || slist.isEmpty()) {
3193 return null;
3194 }
3195
3196 // This function may be called very early, say, from the setup wizard, at
3197 // which point we won't have a default subscription set. If that's the case
3198 // we just choose the first, which will be valid in "most cases".
3199 final int defaultSubId = getDefaultSubscription();
3200 SubscriptionInfo info = null;
3201 if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
3202 info = slist.get(0);
3203 } else {
3204 for (SubscriptionInfo item : slist) {
3205 if (item.getSubscriptionId() == defaultSubId) {
3206 info = item;
3207 break;
3208 }
3209 }
3210
3211 if (info == null) {
3212 return null;
3213 }
3214 }
3215
3216 // Try and fetch the locale from the carrier properties or from the SIM language
3217 // preferences (EF-PL and EF-LI)...
Tony Hill183b2de2015-06-24 14:53:58 +01003218 final int mcc = info.getMcc();
Narayan Kamath1c496c22015-04-16 14:40:19 +01003219 final Phone defaultPhone = getPhone(info.getSubscriptionId());
Narayan Kamath011676f2015-07-29 12:04:08 +01003220 String simLanguage = null;
Narayan Kamath1c496c22015-04-16 14:40:19 +01003221 if (defaultPhone != null) {
3222 final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
3223 if (localeFromDefaultSim != null) {
Narayan Kamath011676f2015-07-29 12:04:08 +01003224 if (!localeFromDefaultSim.getCountry().isEmpty()) {
Tony Hill183b2de2015-06-24 14:53:58 +01003225 if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim);
3226 return localeFromDefaultSim.toLanguageTag();
Narayan Kamath011676f2015-07-29 12:04:08 +01003227 } else {
3228 simLanguage = localeFromDefaultSim.getLanguage();
Tony Hill183b2de2015-06-24 14:53:58 +01003229 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01003230 }
3231 }
3232
Narayan Kamath011676f2015-07-29 12:04:08 +01003233 // The SIM language preferences only store a language (e.g. fr = French), not an
3234 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
3235 // the SIM and carrier preferences does not include a country we add the country
3236 // determined from the SIM MCC to provide an exact locale.
3237 final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage);
Tony Hill183b2de2015-06-24 14:53:58 +01003238 if (mccLocale != null) {
3239 if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale);
3240 return mccLocale.toLanguageTag();
Narayan Kamath1c496c22015-04-16 14:40:19 +01003241 }
3242
Tony Hill183b2de2015-06-24 14:53:58 +01003243 if (DBG) log("No locale found - returning null");
Narayan Kamath1c496c22015-04-16 14:40:19 +01003244 return null;
3245 }
3246
3247 private List<SubscriptionInfo> getAllSubscriptionInfoList() {
3248 final long identity = Binder.clearCallingIdentity();
3249 try {
3250 return mSubscriptionController.getAllSubInfoList(
3251 mPhone.getContext().getOpPackageName());
3252 } finally {
3253 Binder.restoreCallingIdentity(identity);
3254 }
3255 }
3256
3257 private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
3258 final long identity = Binder.clearCallingIdentity();
3259 try {
3260 return mSubscriptionController.getActiveSubscriptionInfoList(
3261 mPhone.getContext().getOpPackageName());
3262 } finally {
3263 Binder.restoreCallingIdentity(identity);
3264 }
3265 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003266
3267 /**
Adam Lesinski903a54c2016-04-11 14:49:52 -07003268 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
3269 * representing the state of the modem.
3270 *
3271 * NOTE: This clears the modem state, so there should only every be one caller.
3272 * @hide
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003273 */
3274 @Override
Adam Lesinski903a54c2016-04-11 14:49:52 -07003275 public void requestModemActivityInfo(ResultReceiver result) {
3276 enforceModifyPermission();
3277
3278 ModemActivityInfo info = (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
3279 Bundle bundle = new Bundle();
3280 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, info);
3281 result.send(0, bundle);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003282 }
Jack Yu85bd38a2015-11-09 11:34:32 -08003283
3284 /**
3285 * {@hide}
3286 * Returns the service state information on specified subscription.
3287 */
3288 @Override
3289 public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
3290
3291 if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
3292 return null;
3293 }
3294
3295 final Phone phone = getPhone(subId);
3296 if (phone == null) {
3297 return null;
3298 }
3299
3300 return phone.getServiceState();
3301 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08003302
3303 /**
3304 * Returns the URI for the per-account voicemail ringtone set in Phone settings.
3305 *
3306 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3307 * voicemail ringtone.
3308 * @return The URI for the ringtone to play when receiving a voicemail from a specific
3309 * PhoneAccount.
3310 */
3311 @Override
3312 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
3313 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3314 if (phone == null) {
3315 return null;
3316 }
3317
3318 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
3319 }
3320
3321 /**
3322 * Returns whether vibration is set for voicemail notification in Phone settings.
3323 *
3324 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3325 * voicemail vibration setting.
3326 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
3327 */
3328 @Override
3329 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
3330 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3331 if (phone == null) {
3332 return false;
3333 }
3334
3335 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone);
3336 }
3337
Youhan Wange64578a2016-05-02 15:32:42 -07003338 /**
3339 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
3340 *
3341 * @throws SecurityException if the caller does not have the required permission
3342 */
3343 private void enforceReadPrivilegedPermission() {
3344 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3345 null);
3346 }
3347
3348 /**
3349 * Return the application ID for the app type.
3350 *
3351 * @param subId the subscription ID that this request applies to.
3352 * @param appType the uicc app type.
3353 * @return Application ID for specificied app type, or null if no uicc.
3354 */
3355 @Override
3356 public String getAidForAppType(int subId, int appType) {
3357 enforceReadPrivilegedPermission();
3358 Phone phone = getPhone(subId);
3359 if (phone == null) {
3360 return null;
3361 }
3362 String aid = null;
3363 try {
3364 aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
3365 .getApplicationByType(appType).getAid();
3366 } catch (Exception e) {
3367 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
3368 }
3369 return aid;
3370 }
3371
Youhan Wang4001d252016-05-11 10:29:41 -07003372 /**
3373 * Return the Electronic Serial Number.
3374 *
3375 * @param subId the subscription ID that this request applies to.
3376 * @return ESN or null if error.
3377 */
3378 @Override
3379 public String getEsn(int subId) {
3380 enforceReadPrivilegedPermission();
3381 Phone phone = getPhone(subId);
3382 if (phone == null) {
3383 return null;
3384 }
3385 String esn = null;
3386 try {
3387 esn = phone.getEsn();
3388 } catch (Exception e) {
3389 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
3390 }
3391 return esn;
3392 }
3393
Sanket Padawe99ef1e32016-05-18 16:12:33 -07003394 /**
Youhan Wang66ad5d72016-07-18 17:56:58 -07003395 * Return the Preferred Roaming List Version.
3396 *
3397 * @param subId the subscription ID that this request applies to.
3398 * @return PRLVersion or null if error.
3399 */
3400 @Override
3401 public String getCdmaPrlVersion(int subId) {
3402 enforceReadPrivilegedPermission();
3403 Phone phone = getPhone(subId);
3404 if (phone == null) {
3405 return null;
3406 }
3407 String cdmaPrlVersion = null;
3408 try {
3409 cdmaPrlVersion = phone.getCdmaPrlVersion();
3410 } catch (Exception e) {
3411 Log.e(LOG_TAG, "Not getting PRLVersion", e);
3412 }
3413 return cdmaPrlVersion;
3414 }
3415
3416 /**
Sanket Padawe99ef1e32016-05-18 16:12:33 -07003417 * Get snapshot of Telephony histograms
3418 * @return List of Telephony histograms
3419 * @hide
3420 */
3421 @Override
3422 public List<TelephonyHistogram> getTelephonyHistograms() {
3423 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
3424 return RIL.getTelephonyRILTimingHistograms();
3425 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07003426
3427 /**
3428 * {@hide}
3429 * Set the allowed carrier list for slotId
3430 * Require system privileges. In the future we may add this to carrier APIs.
3431 *
3432 * @return The number of carriers set successfully, should match length of carriers
3433 */
3434 @Override
3435 public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
3436 enforceModifyPermission();
3437 int subId = SubscriptionManager.getSubId(slotId)[0];
3438 int[] retVal = (int[]) sendRequest(CMD_SET_ALLOWED_CARRIERS, carriers, subId);
3439 return retVal[0];
3440 }
3441
3442 /**
3443 * {@hide}
3444 * Get the allowed carrier list for slotId.
3445 * Require system privileges. In the future we may add this to carrier APIs.
3446 *
3447 * @return List of {@link android.service.telephony.CarrierIdentifier}; empty list
3448 * means all carriers are allowed.
3449 */
3450 @Override
3451 public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
3452 enforceReadPrivilegedPermission();
3453 int subId = SubscriptionManager.getSubId(slotId)[0];
3454 return (List<CarrierIdentifier>) sendRequest(CMD_GET_ALLOWED_CARRIERS, null, subId);
3455 }
3456
fionaxu59545b42016-05-25 15:53:37 -07003457 /**
3458 * Action set from carrier signalling broadcast receivers to enable/disable metered apns
3459 * @param subId the subscription ID that this action applies to.
3460 * @param enabled control enable or disable metered apns.
3461 * {@hide}
3462 */
3463 @Override
3464 public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
3465 enforceModifyPermission();
3466 final Phone phone = getPhone(subId);
3467 if (phone == null) {
3468 loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
3469 return;
3470 }
3471 try {
3472 phone.carrierActionSetMeteredApnsEnabled(enabled);
3473 } catch (Exception e) {
3474 Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
3475 }
3476 }
3477
3478 /**
3479 * Action set from carrier signalling broadcast receivers to enable/disable radio
3480 * @param subId the subscription ID that this action applies to.
3481 * @param enabled control enable or disable radio.
3482 * {@hide}
3483 */
3484 @Override
3485 public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
3486 enforceModifyPermission();
3487 final Phone phone = getPhone(subId);
3488 if (phone == null) {
3489 loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
3490 return;
3491 }
3492 try {
3493 phone.carrierActionSetRadioEnabled(enabled);
3494 } catch (Exception e) {
3495 Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
3496 }
3497 }
3498
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07003499 /**
3500 * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
3501 * bug report is being generated.
3502 */
3503 @Override
Ta-wei Yen99282e02016-06-21 18:19:35 -07003504 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
dcashman22b950d2016-06-27 11:39:02 -07003505 if (mPhone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
3506 != PackageManager.PERMISSION_GRANTED) {
3507 writer.println("Permission Denial: can't dump Phone from pid="
3508 + Binder.getCallingPid()
3509 + ", uid=" + Binder.getCallingUid()
3510 + "without permission "
3511 + android.Manifest.permission.DUMP);
3512 return;
3513 }
Ta-wei Yen99282e02016-06-21 18:19:35 -07003514 DumpsysHandler.dump(mPhone.getContext(), fd, writer, args);
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07003515 }
Jack Yueb89b242016-06-22 13:27:47 -07003516
3517 /**
3518 * Get aggregated video call data usage from all subscriptions since boot.
3519 * @return total data usage in bytes
3520 * {@hide}
3521 */
3522 @Override
3523 public long getVtDataUsage() {
3524 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
3525 null);
3526
3527 // NetworkStatsService keeps tracking the active network interface and identity. It will
3528 // record the delta with the corresponding network identity. What we need to do here is
3529 // returning total video call data usage from all subscriptions since boot.
3530
3531 // TODO: Add sub id support in the future. We'll need it when we support DSDA and
3532 // simultaneous VT calls.
3533 final Phone[] phones = PhoneFactory.getPhones();
3534 long total = 0;
3535 for (Phone phone : phones) {
3536 total += phone.getVtDataUsage();
3537 }
3538 return total;
3539 }
Jack Yu75ab2952016-07-08 14:29:33 -07003540
3541 /**
3542 * Policy control of data connection. Usually used when data limit is passed.
3543 * @param enabled True if enabling the data, otherwise disabling.
3544 * @param subId Subscription index
3545 * {@hide}
3546 */
3547 @Override
3548 public void setPolicyDataEnabled(boolean enabled, int subId) {
3549 enforceModifyPermission();
3550 Phone phone = getPhone(subId);
3551 if (phone != null) {
3552 phone.setPolicyDataEnabled(enabled);
3553 }
3554 }
Sooraj Sasindran600a37a2016-07-18 11:57:25 -07003555
3556 /**
3557 * Get Client request stats
3558 * @return List of Client Request Stats
3559 * @hide
3560 */
3561 @Override
3562 public List<ClientRequestStats> getClientRequestStats(String callingPackage, int subId) {
3563 if (!canReadPhoneState(callingPackage, "getClientRequestStats")) {
3564 return null;
3565 }
3566
3567 Phone phone = getPhone(subId);
3568 if (phone != null) {
3569 return phone.getClientRequestStats();
3570 }
3571
3572 return null;
3573 }
3574
3575 private WorkSource getWorkSource(WorkSource workSource, int uid) {
3576 if (workSource != null) {
3577 return workSource;
3578 }
3579
3580 String packageName = mPhone.getContext().getPackageManager().getNameForUid(uid);
3581 workSource = new WorkSource(uid, packageName);
3582 return workSource;
3583 }
Jack Yu346de222017-02-16 15:32:43 -08003584
3585 /**
3586 * Set SIM card power state. Request is equivalent to inserting or removing the card.
3587 *
3588 * @param slotId SIM slot id.
3589 * @param powerUp True if powering up the SIM, otherwise powering down
3590 *
3591 **/
3592 @Override
3593 public void setSimPowerStateForSlot(int slotId, boolean powerUp) {
3594 enforceModifyPermission();
3595 int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId);
3596 if (subId == null || subId.length == 0) {
3597 return;
3598 }
3599
3600 final Phone phone = getPhone(subId[0]);
3601 if (phone != null) {
3602 phone.setSimPowerState(powerUp);
3603 }
3604 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003605}