blob: 38bfa50dd6b3ee7d4dd410498926a3bbfa7e07af [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 Sasindran22882212016-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 Sasindran22882212016-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 Sasindran22882212016-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
Sanket Padawe5780e442017-03-20 15:04:47 -07001542 public int getCallStateForSlot(int slotIndex) {
1543 Phone phone = PhoneFactory.getPhone(slotIndex);
Shishir Agrawala9f32182016-04-12 12:00:16 -07001544 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 Sasindran22882212016-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 Sasindran22882212016-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 Sasindran22882212016-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 Sasindran22882212016-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 Sasindran22882212016-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) {
Jack Yu3128d9e2017-01-16 10:15:34 -08001707 enforceModifyPermission();
Sooraj Sasindran22882212016-07-18 11:57:25 -07001708 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
1709 mPhone.setCellInfoListRate(rateInMillis, workSource);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001710 }
1711
Shishir Agrawala9f32182016-04-12 12:00:16 -07001712 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07001713 public String getImeiForSlot(int slotIndex, String callingPackage) {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001714 if (!canReadPhoneState(callingPackage, "getImeiForSlot")) {
1715 return null;
1716 }
Sanket Padawe5780e442017-03-20 15:04:47 -07001717 Phone phone = PhoneFactory.getPhone(slotIndex);
Shishir Agrawala9f32182016-04-12 12:00:16 -07001718 return phone == null ? null : phone.getImei();
1719 }
1720
1721 @Override
Jack Yuf7e8f152017-03-15 17:14:14 -07001722 public String getMeidForSlot(int slotIndex, String callingPackage) {
1723 if (!canReadPhoneState(callingPackage, "getMeidForSlot")) {
1724 return null;
1725 }
1726 Phone phone = PhoneFactory.getPhone(slotIndex);
1727 return phone == null ? null : phone.getMeid();
1728 }
1729
1730 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07001731 public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage) {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001732 if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) {
1733 return null;
1734 }
Sanket Padawe5780e442017-03-20 15:04:47 -07001735 Phone phone = PhoneFactory.getPhone(slotIndex);
Shishir Agrawala9f32182016-04-12 12:00:16 -07001736 return phone == null ? null : phone.getDeviceSvn();
1737 }
1738
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001739 //
1740 // Internal helper methods.
1741 //
1742
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001743 /**
1744 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL.
1745 */
1746 private boolean checkCallerInteractAcrossUsersFull() {
1747 return mPhone.getContext().checkCallingOrSelfPermission(
1748 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1749 == PackageManager.PERMISSION_GRANTED;
1750 }
1751
Jake Hambye994d462014-02-03 13:10:13 -08001752 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001753 boolean ok;
1754
1755 boolean self = Binder.getCallingUid() == Process.myUid();
1756 if (!self) {
1757 // Get the caller's user id then clear the calling identity
1758 // which will be restored in the finally clause.
1759 int callingUser = UserHandle.getCallingUserId();
1760 long ident = Binder.clearCallingIdentity();
1761
1762 try {
1763 // With calling identity cleared the current user is the foreground user.
1764 int foregroundUser = ActivityManager.getCurrentUser();
1765 ok = (foregroundUser == callingUser);
1766 if (DBG_LOC) {
1767 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1768 + " callingUser=" + callingUser + " ok=" + ok);
1769 }
1770 } catch (Exception ex) {
1771 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1772 ok = false;
1773 } finally {
1774 Binder.restoreCallingIdentity(ident);
1775 }
1776 } else {
1777 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1778 ok = true;
1779 }
1780 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1781 return ok;
1782 }
1783
1784 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001785 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1786 *
1787 * @throws SecurityException if the caller does not have the required permission
1788 */
1789 private void enforceModifyPermission() {
1790 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1791 }
1792
1793 /**
Junda Liua2e36012014-07-09 18:30:01 -07001794 * Make sure either system app or the caller has carrier privilege.
1795 *
1796 * @throws SecurityException if the caller does not have the required permission/privilege
1797 */
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001798 private void enforceModifyPermissionOrCarrierPrivilege(int subId) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001799 int permission = mApp.checkCallingOrSelfPermission(
1800 android.Manifest.permission.MODIFY_PHONE_STATE);
1801 if (permission == PackageManager.PERMISSION_GRANTED) {
1802 return;
1803 }
1804
1805 log("No modify permission, check carrier privilege next.");
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001806 enforceCarrierPrivilege(subId);
Junda Liua2e36012014-07-09 18:30:01 -07001807 }
1808
1809 /**
1810 * Make sure the caller has carrier privilege.
1811 *
1812 * @throws SecurityException if the caller does not have the required permission
1813 */
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001814 private void enforceCarrierPrivilege(int subId) {
1815 if (getCarrierPrivilegeStatus(subId) !=
1816 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001817 loge("No Carrier Privilege.");
1818 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001819 }
1820 }
1821
1822 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001823 * Make sure the caller has the CALL_PHONE permission.
1824 *
1825 * @throws SecurityException if the caller does not have the required permission
1826 */
1827 private void enforceCallPermission() {
1828 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1829 }
1830
Stuart Scott8eef64f2015-04-08 15:13:54 -07001831 private void enforceConnectivityInternalPermission() {
1832 mApp.enforceCallingOrSelfPermission(
1833 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1834 "ConnectivityService");
1835 }
1836
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001837 private String createTelUrl(String number) {
1838 if (TextUtils.isEmpty(number)) {
1839 return null;
1840 }
1841
Jake Hambye994d462014-02-03 13:10:13 -08001842 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001843 }
1844
Ihab Awadf9e92732013-12-05 18:02:52 -08001845 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001846 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1847 }
1848
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001849 private static void logv(String msg) {
1850 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1851 }
1852
Ihab Awadf9e92732013-12-05 18:02:52 -08001853 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001854 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1855 }
1856
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001857 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001858 public int getActivePhoneType() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001859 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001860 }
1861
Sanket Padawe356d7632015-06-22 14:03:32 -07001862 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07001863 public int getActivePhoneTypeForSlot(int slotIndex) {
1864 final Phone phone = PhoneFactory.getPhone(slotIndex);
Sanket Padawe356d7632015-06-22 14:03:32 -07001865 if (phone == null) {
1866 return PhoneConstants.PHONE_TYPE_NONE;
1867 } else {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001868 return phone.getPhoneType();
Sanket Padawe356d7632015-06-22 14:03:32 -07001869 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001870 }
1871
1872 /**
1873 * Returns the CDMA ERI icon index to display
1874 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001875 @Override
1876 public int getCdmaEriIconIndex(String callingPackage) {
1877 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001878 }
1879
Sanket Padawe356d7632015-06-22 14:03:32 -07001880 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001881 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
1882 if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
1883 return -1;
1884 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001885 final Phone phone = getPhone(subId);
1886 if (phone != null) {
1887 return phone.getCdmaEriIconIndex();
1888 } else {
1889 return -1;
1890 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001891 }
1892
1893 /**
1894 * Returns the CDMA ERI icon mode,
1895 * 0 - ON
1896 * 1 - FLASHING
1897 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001898 @Override
1899 public int getCdmaEriIconMode(String callingPackage) {
1900 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001901 }
1902
Sanket Padawe356d7632015-06-22 14:03:32 -07001903 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001904 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
1905 if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
1906 return -1;
1907 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001908 final Phone phone = getPhone(subId);
1909 if (phone != null) {
1910 return phone.getCdmaEriIconMode();
1911 } else {
1912 return -1;
1913 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001914 }
1915
1916 /**
1917 * Returns the CDMA ERI text,
1918 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001919 @Override
1920 public String getCdmaEriText(String callingPackage) {
1921 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001922 }
1923
Sanket Padawe356d7632015-06-22 14:03:32 -07001924 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001925 public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
1926 if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
1927 return null;
1928 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001929 final Phone phone = getPhone(subId);
1930 if (phone != null) {
1931 return phone.getCdmaEriText();
1932 } else {
1933 return null;
1934 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001935 }
1936
1937 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001938 * Returns the CDMA MDN.
1939 */
Sanket Padawe356d7632015-06-22 14:03:32 -07001940 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001941 public String getCdmaMdn(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001942 enforceModifyPermissionOrCarrierPrivilege(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001943 final Phone phone = getPhone(subId);
1944 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
1945 return phone.getLine1Number();
Junda Liuca05d5d2014-08-14 22:36:34 -07001946 } else {
1947 return null;
1948 }
1949 }
1950
1951 /**
1952 * Returns the CDMA MIN.
1953 */
Sanket Padawe356d7632015-06-22 14:03:32 -07001954 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001955 public String getCdmaMin(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001956 enforceModifyPermissionOrCarrierPrivilege(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001957 final Phone phone = getPhone(subId);
1958 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1959 return phone.getCdmaMin();
Junda Liuca05d5d2014-08-14 22:36:34 -07001960 } else {
1961 return null;
1962 }
1963 }
1964
1965 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001966 * Returns true if CDMA provisioning needs to run.
1967 */
1968 public boolean needsOtaServiceProvisioning() {
1969 return mPhone.needsOtaServiceProvisioning();
1970 }
1971
1972 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001973 * Sets the voice mail number of a given subId.
1974 */
1975 @Override
1976 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001977 enforceCarrierPrivilege(subId);
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001978 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
1979 new Pair<String, String>(alphaTag, number), new Integer(subId));
1980 return success;
1981 }
1982
Ta-wei Yen87c49842016-05-13 21:19:52 -07001983 @Override
Ta-wei Yenb0f695b2016-08-08 17:33:11 -07001984 public void setVisualVoicemailEnabled(String callingPackage,
1985 PhoneAccountHandle phoneAccountHandle, boolean enabled) {
1986 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1987 if (!TextUtils.equals(callingPackage,
1988 TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
1989 enforceModifyPermissionOrCarrierPrivilege(
1990 PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
1991 }
1992 VisualVoicemailSettingsUtil.setEnabled(mPhone.getContext(), phoneAccountHandle, enabled);
1993 }
1994
1995 @Override
1996 public boolean isVisualVoicemailEnabled(String callingPackage,
1997 PhoneAccountHandle phoneAccountHandle) {
1998 if (!canReadPhoneState(callingPackage, "isVisualVoicemailEnabled")) {
1999 return false;
2000 }
2001 return VisualVoicemailSettingsUtil.isEnabled(mPhone.getContext(), phoneAccountHandle);
2002 }
2003
2004 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002005 public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
2006 VisualVoicemailSmsFilterSettings settings) {
2007 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002008 VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002009 .enableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId,
2010 settings);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002011 }
2012
2013 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002014 public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
2015 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002016 VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002017 .disableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002018 }
2019
2020 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002021 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
2022 String callingPackage, int subId) {
2023 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002024 return VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002025 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), callingPackage, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002026 }
2027
2028 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07002029 public VisualVoicemailSmsFilterSettings getSystemVisualVoicemailSmsFilterSettings(
2030 String packageName, int subId) {
2031 enforceReadPrivilegedPermission();
Ta-wei Yen87c49842016-05-13 21:19:52 -07002032 return VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07002033 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), packageName, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07002034 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002035 /**
fionaxuef039d42016-11-14 13:36:14 -08002036 * Sets the voice activation state of a given subId.
2037 */
2038 @Override
2039 public void setVoiceActivationState(int subId, int activationState) {
2040 enforceModifyPermissionOrCarrierPrivilege(subId);
2041 final Phone phone = getPhone(subId);
2042 if (phone != null) {
2043 phone.setVoiceActivationState(activationState);
2044 } else {
2045 loge("setVoiceActivationState fails with invalid subId: " + subId);
2046 }
2047 }
2048
2049 /**
2050 * Sets the data activation state of a given subId.
2051 */
2052 @Override
2053 public void setDataActivationState(int subId, int activationState) {
2054 enforceModifyPermissionOrCarrierPrivilege(subId);
2055 final Phone phone = getPhone(subId);
2056 if (phone != null) {
2057 phone.setDataActivationState(activationState);
2058 } else {
2059 loge("setVoiceActivationState fails with invalid subId: " + subId);
2060 }
2061 }
2062
2063 /**
2064 * Returns the voice activation state of a given subId.
2065 */
2066 @Override
2067 public int getVoiceActivationState(int subId, String callingPackage) {
2068 if (!canReadPhoneState(callingPackage, "getVoiceActivationStateForSubscriber")) {
2069 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2070 }
2071 final Phone phone = getPhone(subId);
2072 if (phone != null) {
2073 return phone.getVoiceActivationState();
2074 } else {
2075 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2076 }
2077 }
2078
2079 /**
2080 * Returns the data activation state of a given subId.
2081 */
2082 @Override
2083 public int getDataActivationState(int subId, String callingPackage) {
2084 if (!canReadPhoneState(callingPackage, "getDataActivationStateForSubscriber")) {
2085 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2086 }
2087 final Phone phone = getPhone(subId);
2088 if (phone != null) {
2089 return phone.getDataActivationState();
2090 } else {
2091 return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
2092 }
2093 }
2094
2095 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002096 * Returns the unread count of voicemails
2097 */
2098 public int getVoiceMessageCount() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07002099 return getVoiceMessageCountForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07002100 }
2101
2102 /**
2103 * Returns the unread count of voicemails for a subId
2104 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002105 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002106 public int getVoiceMessageCountForSubscriber( int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002107 final Phone phone = getPhone(subId);
2108 if (phone != null) {
2109 return phone.getVoiceMessageCount();
2110 } else {
2111 return 0;
2112 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002113 }
2114
2115 /**
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002116 * Returns the data network type.
2117 * Legacy call, permission-free.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002118 *
2119 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
2120 */
2121 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002122 public int getNetworkType() {
2123 final Phone phone = getPhone(getDefaultSubscription());
2124 if (phone != null) {
2125 return phone.getServiceState().getDataNetworkType();
2126 } else {
2127 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2128 }
Wink Saville36469e72014-06-11 15:17:00 -07002129 }
2130
2131 /**
2132 * Returns the network type for a subId
2133 */
2134 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002135 public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
2136 if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
2137 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2138 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002139
Sanket Padawe356d7632015-06-22 14:03:32 -07002140 final Phone phone = getPhone(subId);
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002141 if (phone != null) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002142 return phone.getServiceState().getDataNetworkType();
2143 } else {
2144 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2145 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002146 }
2147
2148 /**
2149 * Returns the data network type
2150 */
2151 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002152 public int getDataNetworkType(String callingPackage) {
2153 return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002154 }
2155
2156 /**
2157 * Returns the data network type for a subId
2158 */
2159 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002160 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
2161 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2162 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2163 }
2164
Sanket Padawe356d7632015-06-22 14:03:32 -07002165 final Phone phone = getPhone(subId);
2166 if (phone != null) {
2167 return phone.getServiceState().getDataNetworkType();
2168 } else {
2169 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2170 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002171 }
2172
2173 /**
Wink Saville36469e72014-06-11 15:17:00 -07002174 * Returns the Voice network type for a subId
2175 */
2176 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002177 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
2178 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2179 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2180 }
2181
Sanket Padawe356d7632015-06-22 14:03:32 -07002182 final Phone phone = getPhone(subId);
2183 if (phone != null) {
2184 return phone.getServiceState().getVoiceNetworkType();
2185 } else {
2186 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2187 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002188 }
2189
2190 /**
2191 * @return true if a ICC card is present
2192 */
2193 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07002194 // FIXME Make changes to pass defaultSimId of type int
Sanket Padawe5780e442017-03-20 15:04:47 -07002195 return hasIccCardUsingSlotIndex(mSubscriptionController.getSlotIndex(
2196 getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -07002197 }
2198
2199 /**
Sanket Padawe5780e442017-03-20 15:04:47 -07002200 * @return true if a ICC card is present for a slotIndex
Wink Saville36469e72014-06-11 15:17:00 -07002201 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002202 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07002203 public boolean hasIccCardUsingSlotIndex(int slotIndex) {
2204 int subId[] = mSubscriptionController.getSubIdUsingSlotIndex(slotIndex);
Sanket Padawe356d7632015-06-22 14:03:32 -07002205 final Phone phone = getPhone(subId[0]);
2206 if (subId != null && phone != null) {
2207 return phone.getIccCard().hasIccCard();
Amit Mahajana6fc2a82015-01-06 11:53:51 -08002208 } else {
2209 return false;
2210 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002211 }
2212
2213 /**
2214 * Return if the current radio is LTE on CDMA. This
2215 * is a tri-state return value as for a period of time
2216 * the mode may be unknown.
2217 *
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002218 * @param callingPackage the name of the package making the call.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002219 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08002220 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002221 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002222 @Override
2223 public int getLteOnCdmaMode(String callingPackage) {
2224 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002225 }
2226
Sanket Padawe356d7632015-06-22 14:03:32 -07002227 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002228 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
2229 if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
2230 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2231 }
2232
Sanket Padawe356d7632015-06-22 14:03:32 -07002233 final Phone phone = getPhone(subId);
2234 if (phone == null) {
2235 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2236 } else {
2237 return phone.getLteOnCdmaMode();
2238 }
Wink Saville36469e72014-06-11 15:17:00 -07002239 }
2240
2241 public void setPhone(Phone phone) {
2242 mPhone = phone;
2243 }
2244
2245 /**
2246 * {@hide}
2247 * Returns Default subId, 0 in the case of single standby.
2248 */
Wink Savilleb564aae2014-10-23 10:18:09 -07002249 private int getDefaultSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08002250 return mSubscriptionController.getDefaultSubId();
Wink Saville36469e72014-06-11 15:17:00 -07002251 }
2252
Shishir Agrawala9f32182016-04-12 12:00:16 -07002253 private int getSlotForDefaultSubscription() {
2254 return mSubscriptionController.getPhoneId(getDefaultSubscription());
2255 }
2256
Wink Savilleb564aae2014-10-23 10:18:09 -07002257 private int getPreferredVoiceSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08002258 return mSubscriptionController.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002259 }
Ihab Awadf2177b72013-11-25 13:33:23 -08002260
2261 /**
2262 * @see android.telephony.TelephonyManager.WifiCallingChoices
2263 */
2264 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08002265 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
2266 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08002267 }
2268
2269 /**
2270 * @see android.telephony.TelephonyManager.WifiCallingChoices
2271 */
2272 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08002273 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
2274 Settings.System.putInt(mPhone.getContext().getContentResolver(),
2275 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08002276 }
2277
Sailesh Nepald1e68152013-12-12 19:08:02 -08002278 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07002279 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08002280 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08002281 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08002282
Shishir Agrawal566b7612013-10-28 14:41:00 -07002283 @Override
Ajay Nambiabd73502015-12-03 13:50:00 -08002284 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002285 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002286
Ajay Nambiabd73502015-12-03 13:50:00 -08002287 if (DBG) log("iccOpenLogicalChannel: subId=" + subId + " aid=" + AID + " p2=" + p2);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002288 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
Ajay Nambiabd73502015-12-03 13:50:00 -08002289 CMD_OPEN_CHANNEL, new Pair<String, Integer>(AID, p2), subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002290 if (DBG) log("iccOpenLogicalChannel: " + response);
2291 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07002292 }
2293
2294 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002295 public boolean iccCloseLogicalChannel(int subId, int channel) {
2296 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002297
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002298 if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002299 if (channel < 0) {
2300 return false;
2301 }
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002302 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel, subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002303 if (DBG) log("iccCloseLogicalChannel: " + success);
2304 return success;
2305 }
2306
2307 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002308 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
Shishir Agrawal566b7612013-10-28 14:41:00 -07002309 int command, int p1, int p2, int p3, String data) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002310 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002311
2312 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002313 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel +
2314 " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
Shishir Agrawal566b7612013-10-28 14:41:00 -07002315 " data=" + data);
2316 }
2317
2318 if (channel < 0) {
2319 return "";
2320 }
2321
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002322 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002323 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002324 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
2325
Shishir Agrawal566b7612013-10-28 14:41:00 -07002326 // Append the returned status code to the end of the response payload.
2327 String s = Integer.toHexString(
2328 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07002329 if (response.payload != null) {
2330 s = IccUtils.bytesToHexString(response.payload) + s;
2331 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07002332 return s;
2333 }
Jake Hambye994d462014-02-03 13:10:13 -08002334
Evan Charltonc66da362014-05-16 14:06:40 -07002335 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002336 public String iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002337 int p3, String data) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002338 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002339
2340 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002341 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd=" + command
2342 + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002343 }
2344
2345 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002346 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002347 if (DBG) log("iccTransmitApduBasicChannel: " + response);
2348
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002349 // Append the returned status code to the end of the response payload.
2350 String s = Integer.toHexString(
2351 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07002352 if (response.payload != null) {
2353 s = IccUtils.bytesToHexString(response.payload) + s;
2354 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002355 return s;
2356 }
2357
2358 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002359 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002360 String filePath) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002361 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002362
2363 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002364 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " +
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002365 p1 + " " + p2 + " " + p3 + ":" + filePath);
2366 }
2367
2368 IccIoResult response =
2369 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002370 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
2371 subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002372
2373 if (DBG) {
2374 log("Exchange SIM_IO [R]" + response);
2375 }
2376
2377 byte[] result = null;
2378 int length = 2;
2379 if (response.payload != null) {
2380 length = 2 + response.payload.length;
2381 result = new byte[length];
2382 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
2383 } else {
2384 result = new byte[length];
2385 }
2386
2387 result[length - 1] = (byte) response.sw2;
2388 result[length - 2] = (byte) response.sw1;
2389 return result;
2390 }
2391
Nathan Haroldb3014052017-01-25 15:57:32 -08002392 /**
2393 * Get the forbidden PLMN List from the given app type (ex APPTYPE_USIM)
2394 * on a particular subscription
2395 */
2396 public String[] getForbiddenPlmns(int subId, int appType) {
Nathan Harold892104e2017-04-13 18:19:05 -07002397 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
2398 "Requires READ_PHONE_STATE");
Nathan Haroldb3014052017-01-25 15:57:32 -08002399 if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
2400 loge("getForbiddenPlmnList(): App Type must be USIM or SIM");
2401 return null;
2402 }
2403 Object response = sendRequest(
2404 CMD_GET_FORBIDDEN_PLMNS, new Integer(appType), subId);
2405 if (response instanceof String[]) {
2406 return (String[]) response;
2407 }
2408 // Response is an Exception of some kind, which is signalled to the user as a NULL retval
2409 return null;
2410 }
2411
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002412 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002413 public String sendEnvelopeWithStatus(int subId, String content) {
2414 enforceModifyPermissionOrCarrierPrivilege(subId);
Evan Charltonc66da362014-05-16 14:06:40 -07002415
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002416 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId);
Evan Charltonc66da362014-05-16 14:06:40 -07002417 if (response.payload == null) {
2418 return "";
2419 }
2420
2421 // Append the returned status code to the end of the response payload.
2422 String s = Integer.toHexString(
2423 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2424 s = IccUtils.bytesToHexString(response.payload) + s;
2425 return s;
2426 }
2427
Jake Hambye994d462014-02-03 13:10:13 -08002428 /**
2429 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2430 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2431 *
2432 * @param itemID the ID of the item to read
2433 * @return the NV item as a String, or null on error.
2434 */
2435 @Override
2436 public String nvReadItem(int itemID) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002437 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002438 if (DBG) log("nvReadItem: item " + itemID);
2439 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
2440 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
2441 return value;
2442 }
2443
2444 /**
2445 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2446 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2447 *
2448 * @param itemID the ID of the item to read
2449 * @param itemValue the value to write, as a String
2450 * @return true on success; false on any failure
2451 */
2452 @Override
2453 public boolean nvWriteItem(int itemID, String itemValue) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002454 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002455 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
2456 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
2457 new Pair<Integer, String>(itemID, itemValue));
2458 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
2459 return success;
2460 }
2461
2462 /**
2463 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
2464 * Used for device configuration by some CDMA operators.
2465 *
2466 * @param preferredRoamingList byte array containing the new PRL
2467 * @return true on success; false on any failure
2468 */
2469 @Override
2470 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002471 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002472 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
2473 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
2474 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
2475 return success;
2476 }
2477
2478 /**
2479 * Perform the specified type of NV config reset.
2480 * Used for device configuration by some CDMA operators.
2481 *
2482 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
2483 * @return true on success; false on any failure
2484 */
2485 @Override
2486 public boolean nvResetConfig(int resetType) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002487 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002488 if (DBG) log("nvResetConfig: type " + resetType);
2489 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
2490 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
2491 return success;
2492 }
Jake Hamby7c27be32014-03-03 13:25:59 -08002493
2494 /**
Wink Saville36469e72014-06-11 15:17:00 -07002495 * {@hide}
2496 * Returns Default sim, 0 in the case of single standby.
2497 */
2498 public int getDefaultSim() {
2499 //TODO Need to get it from Telephony Devcontroller
2500 return 0;
2501 }
2502
Svet Ganovb320e182015-04-16 12:30:10 -07002503 public String[] getPcscfAddress(String apnType, String callingPackage) {
2504 if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
2505 return new String[0];
2506 }
2507
2508
ram87fca6f2014-07-18 18:58:44 +05302509 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07002510 }
2511
Brad Ebinger76681002017-01-23 13:50:20 -08002512 /**
2513 * Returns the {@link IImsServiceController} that corresponds to the given slot Id and IMS
2514 * feature or {@link null} if the service is not available. If an ImsServiceController is
2515 * available, the {@link IImsServiceFeatureListener} callback is registered as a listener for
2516 * feature updates.
2517 */
Sanket Padawe5780e442017-03-20 15:04:47 -07002518 public IImsServiceController getImsServiceControllerAndListen(int slotIndex, int feature,
Brad Ebinger76681002017-01-23 13:50:20 -08002519 IImsServiceFeatureListener callback) {
2520 enforceModifyPermission();
Sanket Padawe5780e442017-03-20 15:04:47 -07002521 return PhoneFactory.getImsResolver().getImsServiceControllerAndListen(slotIndex, feature,
Brad Ebinger76681002017-01-23 13:50:20 -08002522 callback);
2523 }
2524
Wink Saville36469e72014-06-11 15:17:00 -07002525 public void setImsRegistrationState(boolean registered) {
2526 enforceModifyPermission();
2527 mPhone.setImsRegistrationState(registered);
2528 }
2529
2530 /**
Stuart Scott54788802015-03-30 13:18:01 -07002531 * Set the network selection mode to automatic.
2532 *
2533 */
2534 @Override
2535 public void setNetworkSelectionModeAutomatic(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002536 enforceModifyPermissionOrCarrierPrivilege(subId);
Stuart Scott54788802015-03-30 13:18:01 -07002537 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
2538 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
2539 }
2540
2541 /**
Shishir Agrawal302c8692015-06-19 13:49:39 -07002542 * Set the network selection mode to manual with the selected carrier.
2543 */
2544 @Override
Shishir Agrawal77ba3172015-09-10 14:50:19 -07002545 public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
2546 boolean persistSelection) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002547 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002548 if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
Shishir Agrawal77ba3172015-09-10 14:50:19 -07002549 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
2550 persistSelection);
2551 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002552 }
2553
2554 /**
2555 * Scans for available networks.
2556 */
2557 @Override
2558 public CellNetworkScanResult getCellNetworkScanResults(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002559 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002560 if (DBG) log("getCellNetworkScanResults: subId " + subId);
2561 CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
2562 CMD_PERFORM_NETWORK_SCAN, null, subId);
2563 return result;
2564 }
2565
2566 /**
Junda Liu84d15a22014-07-02 11:21:04 -07002567 * Get the calculated preferred network type.
2568 * Used for debugging incorrect network type.
2569 *
2570 * @return the preferred network type, defined in RILConstants.java.
2571 */
2572 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002573 public int getCalculatedPreferredNetworkType(String callingPackage) {
2574 if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
2575 return RILConstants.PREFERRED_NETWORK_MODE;
2576 }
2577
Amit Mahajan43330e02014-11-18 11:54:45 -08002578 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07002579 }
2580
2581 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08002582 * Get the preferred network type.
2583 * Used for device configuration by some CDMA operators.
2584 *
2585 * @return the preferred network type, defined in RILConstants.java.
2586 */
2587 @Override
Stuart Scott54788802015-03-30 13:18:01 -07002588 public int getPreferredNetworkType(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002589 enforceModifyPermissionOrCarrierPrivilege(subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002590 if (DBG) log("getPreferredNetworkType");
Stuart Scott54788802015-03-30 13:18:01 -07002591 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002592 int networkType = (result != null ? result[0] : -1);
2593 if (DBG) log("getPreferredNetworkType: " + networkType);
2594 return networkType;
2595 }
2596
2597 /**
2598 * Set the preferred network type.
2599 * Used for device configuration by some CDMA operators.
2600 *
2601 * @param networkType the preferred network type, defined in RILConstants.java.
2602 * @return true on success; false on any failure.
2603 */
2604 @Override
Stuart Scott54788802015-03-30 13:18:01 -07002605 public boolean setPreferredNetworkType(int subId, int networkType) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002606 enforceModifyPermissionOrCarrierPrivilege(subId);
Stuart Scott54788802015-03-30 13:18:01 -07002607 if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
2608 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002609 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07002610 if (success) {
2611 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
Stuart Scott54788802015-03-30 13:18:01 -07002612 Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
Junda Liu80bc0d12014-07-14 16:36:44 -07002613 }
Jake Hamby7c27be32014-03-03 13:25:59 -08002614 return success;
2615 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002616
2617 /**
Junda Liu475951f2014-11-07 16:45:03 -08002618 * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
2619 * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
2620 * tethering.
2621 *
2622 * @return 0: Not required. 1: required. 2: Not set.
2623 * @hide
2624 */
2625 @Override
2626 public int getTetherApnRequired() {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002627 enforceModifyPermission();
Junda Liu475951f2014-11-07 16:45:03 -08002628 int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2629 Settings.Global.TETHER_DUN_REQUIRED, 2);
2630 // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2631 // config_tether_apndata.
2632 if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2633 dunRequired = 1;
2634 }
2635 return dunRequired;
2636 }
2637
2638 /**
Robert Greenwalted86e582014-05-21 20:03:20 -07002639 * Set mobile data enabled
2640 * Used by the user through settings etc to turn on/off mobile data
2641 *
2642 * @param enable {@code true} turn turn data on, else {@code false}
2643 */
2644 @Override
Wink Savillee7353bb2014-12-05 14:21:41 -08002645 public void setDataEnabled(int subId, boolean enable) {
Jeff Davidsonf7eecf02016-11-18 17:05:56 -08002646 enforceModifyPermissionOrCarrierPrivilege(subId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002647 int phoneId = mSubscriptionController.getPhoneId(subId);
Joe Onoratoa601dd22016-02-23 13:03:53 -08002648 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002649 Phone phone = PhoneFactory.getPhone(phoneId);
2650 if (phone != null) {
Joe Onoratoa601dd22016-02-23 13:03:53 -08002651 if (DBG) log("setDataEnabled: subId=" + subId + " enable=" + enable);
Wink Savillee7353bb2014-12-05 14:21:41 -08002652 phone.setDataEnabled(enable);
2653 } else {
2654 loge("setDataEnabled: no phone for subId=" + subId);
2655 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002656 }
2657
2658 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07002659 * Get whether mobile data is enabled.
2660 *
Jeff Davidsonf7eecf02016-11-18 17:05:56 -08002661 * Accepts either ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE or carrier privileges.
Robert Greenwalted86e582014-05-21 20:03:20 -07002662 *
2663 * @return {@code true} if data is enabled else {@code false}
2664 */
2665 @Override
Wink Savillee7353bb2014-12-05 14:21:41 -08002666 public boolean getDataEnabled(int subId) {
Robert Greenwalt646120a2014-05-23 11:54:03 -07002667 try {
2668 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2669 null);
2670 } catch (Exception e) {
Jeff Davidsonf7eecf02016-11-18 17:05:56 -08002671 enforceModifyPermissionOrCarrierPrivilege(subId);
Robert Greenwalt646120a2014-05-23 11:54:03 -07002672 }
Wink Savillee7353bb2014-12-05 14:21:41 -08002673 int phoneId = mSubscriptionController.getPhoneId(subId);
Joe Onoratoa601dd22016-02-23 13:03:53 -08002674 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002675 Phone phone = PhoneFactory.getPhone(phoneId);
2676 if (phone != null) {
2677 boolean retVal = phone.getDataEnabled();
Joe Onoratoa601dd22016-02-23 13:03:53 -08002678 if (DBG) log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
Wink Savillee7353bb2014-12-05 14:21:41 -08002679 return retVal;
2680 } else {
Joe Onoratoa601dd22016-02-23 13:03:53 -08002681 if (DBG) loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
Wink Savillee7353bb2014-12-05 14:21:41 -08002682 return false;
2683 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002684 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07002685
2686 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002687 public int getCarrierPrivilegeStatus(int subId) {
2688 final Phone phone = getPhone(subId);
2689 if (phone == null) {
2690 loge("getCarrierPrivilegeStatus: Invalid subId");
2691 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2692 }
2693 UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002694 if (card == null) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08002695 loge("getCarrierPrivilegeStatus: No UICC");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002696 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2697 }
2698 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002699 phone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07002700 }
Junda Liu29340342014-07-10 15:23:27 -07002701
2702 @Override
Zach Johnson50ecba32015-05-19 00:24:21 -07002703 public int checkCarrierPrivilegesForPackage(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08002704 if (TextUtils.isEmpty(pkgName))
2705 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Shishir Agrawal21409252015-01-15 23:33:50 -08002706 UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002707 if (card == null) {
2708 loge("checkCarrierPrivilegesForPackage: No UICC");
2709 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2710 }
Zach Johnson50ecba32015-05-19 00:24:21 -07002711 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
2712 }
2713
2714 @Override
2715 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08002716 if (TextUtils.isEmpty(pkgName))
2717 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Zach Johnson50ecba32015-05-19 00:24:21 -07002718 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2719 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2720 UiccCard card = UiccController.getInstance().getUiccCard(i);
2721 if (card == null) {
Jonathan Basseri7d320df2015-06-16 12:17:08 -07002722 // No UICC in that slot.
Zach Johnson50ecba32015-05-19 00:24:21 -07002723 continue;
2724 }
2725
2726 result = card.getCarrierPrivilegeStatus(
2727 mPhone.getContext().getPackageManager(), pkgName);
2728 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2729 break;
2730 }
2731 }
2732
2733 return result;
Junda Liu29340342014-07-10 15:23:27 -07002734 }
Derek Tan89e89d42014-07-08 17:00:10 -07002735
2736 @Override
Junda Liue64de782015-04-16 17:19:16 -07002737 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2738 if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2739 loge("phoneId " + phoneId + " is not valid.");
2740 return null;
2741 }
2742 UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002743 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07002744 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002745 return null ;
2746 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07002747 return card.getCarrierPackageNamesForIntent(
Svetoslav483aff72015-04-21 14:16:07 -07002748 mPhone.getContext().getPackageManager(), intent);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002749 }
2750
Amith Yamasani6e118872016-02-19 12:53:51 -08002751 @Override
2752 public List<String> getPackagesWithCarrierPrivileges() {
2753 PackageManager pm = mPhone.getContext().getPackageManager();
2754 List<String> privilegedPackages = new ArrayList<>();
2755 List<PackageInfo> packages = null;
2756 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2757 UiccCard card = UiccController.getInstance().getUiccCard(i);
2758 if (card == null) {
2759 // No UICC in that slot.
2760 continue;
2761 }
2762 if (card.hasCarrierPrivilegeRules()) {
2763 if (packages == null) {
2764 // Only check packages in user 0 for now
2765 packages = pm.getInstalledPackagesAsUser(
2766 PackageManager.MATCH_DISABLED_COMPONENTS
2767 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
2768 | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
2769 }
2770 for (int p = packages.size() - 1; p >= 0; p--) {
2771 PackageInfo pkgInfo = packages.get(p);
2772 if (pkgInfo != null && pkgInfo.packageName != null
2773 && card.getCarrierPrivilegeStatus(pkgInfo)
2774 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2775 privilegedPackages.add(pkgInfo.packageName);
2776 }
2777 }
2778 }
2779 }
2780 return privilegedPackages;
2781 }
2782
Wink Savilleb564aae2014-10-23 10:18:09 -07002783 private String getIccId(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002784 final Phone phone = getPhone(subId);
2785 UiccCard card = phone == null ? null : phone.getUiccCard();
Derek Tan97ebb422014-09-05 16:55:38 -07002786 if (card == null) {
2787 loge("getIccId: No UICC");
2788 return null;
2789 }
2790 String iccId = card.getIccId();
2791 if (TextUtils.isEmpty(iccId)) {
2792 loge("getIccId: ICC ID is null or empty.");
2793 return null;
2794 }
2795 return iccId;
2796 }
2797
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002798 @Override
Jeff Sharkey85190e62014-12-05 09:40:12 -08002799 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
2800 String number) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002801 enforceCarrierPrivilege(subId);
Derek Tan97ebb422014-09-05 16:55:38 -07002802
Jeff Sharkey85190e62014-12-05 09:40:12 -08002803 final String iccId = getIccId(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07002804 final Phone phone = getPhone(subId);
2805 if (phone == null) {
2806 return false;
2807 }
2808 final String subscriberId = phone.getSubscriberId();
Jeff Sharkey85190e62014-12-05 09:40:12 -08002809
2810 if (DBG_MERGE) {
2811 Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
2812 + subscriberId + " to " + number);
2813 }
2814
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002815 if (TextUtils.isEmpty(iccId)) {
2816 return false;
Derek Tan97ebb422014-09-05 16:55:38 -07002817 }
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002818
Jeff Sharkey85190e62014-12-05 09:40:12 -08002819 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2820
2821 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002822 if (alphaTag == null) {
2823 editor.remove(alphaTagPrefKey);
2824 } else {
2825 editor.putString(alphaTagPrefKey, alphaTag);
2826 }
2827
Jeff Sharkey85190e62014-12-05 09:40:12 -08002828 // Record both the line number and IMSI for this ICCID, since we need to
2829 // track all merged IMSIs based on line number
2830 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2831 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002832 if (number == null) {
2833 editor.remove(numberPrefKey);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002834 editor.remove(subscriberPrefKey);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002835 } else {
2836 editor.putString(numberPrefKey, number);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002837 editor.putString(subscriberPrefKey, subscriberId);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002838 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08002839
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002840 editor.commit();
2841 return true;
Derek Tan7226c842014-07-02 17:42:23 -07002842 }
2843
2844 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002845 public String getLine1NumberForDisplay(int subId, String callingPackage) {
Makoto Onukifee69342015-06-29 14:44:50 -07002846 // This is open to apps with WRITE_SMS.
2847 if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
Amit Mahajan9cf11512015-11-09 11:40:48 -08002848 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
Svet Ganovb320e182015-04-16 12:30:10 -07002849 return null;
2850 }
Derek Tan97ebb422014-09-05 16:55:38 -07002851
2852 String iccId = getIccId(subId);
2853 if (iccId != null) {
2854 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
Amit Mahajan9cf11512015-11-09 11:40:48 -08002855 if (DBG_MERGE) {
2856 log("getLine1NumberForDisplay returning " +
2857 mTelephonySharedPreferences.getString(numberPrefKey, null));
2858 }
Andrew Leedf14ead2014-10-17 14:22:52 -07002859 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002860 }
Amit Mahajan9cf11512015-11-09 11:40:48 -08002861 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
Derek Tan97ebb422014-09-05 16:55:38 -07002862 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002863 }
2864
2865 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002866 public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2867 if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2868 return null;
2869 }
Derek Tan97ebb422014-09-05 16:55:38 -07002870
2871 String iccId = getIccId(subId);
2872 if (iccId != null) {
2873 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002874 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002875 }
Derek Tan97ebb422014-09-05 16:55:38 -07002876 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002877 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002878
2879 @Override
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07002880 public String[] getMergedSubscriberIds(String callingPackage) {
2881 if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
2882 return null;
2883 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08002884 final Context context = mPhone.getContext();
2885 final TelephonyManager tele = TelephonyManager.from(context);
2886 final SubscriptionManager sub = SubscriptionManager.from(context);
2887
2888 // Figure out what subscribers are currently active
2889 final ArraySet<String> activeSubscriberIds = new ArraySet<>();
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07002890 // Clear calling identity, when calling TelephonyManager, because callerUid must be
2891 // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail.
2892 final long identity = Binder.clearCallingIdentity();
2893 try {
2894 final int[] subIds = sub.getActiveSubscriptionIdList();
2895 for (int subId : subIds) {
2896 activeSubscriberIds.add(tele.getSubscriberId(subId));
2897 }
2898 } finally {
2899 Binder.restoreCallingIdentity(identity);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002900 }
2901
2902 // First pass, find a number override for an active subscriber
2903 String mergeNumber = null;
2904 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
2905 for (String key : prefs.keySet()) {
2906 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
2907 final String subscriberId = (String) prefs.get(key);
2908 if (activeSubscriberIds.contains(subscriberId)) {
2909 final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
2910 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2911 mergeNumber = (String) prefs.get(numberKey);
2912 if (DBG_MERGE) {
2913 Slog.d(LOG_TAG, "Found line number " + mergeNumber
2914 + " for active subscriber " + subscriberId);
2915 }
2916 if (!TextUtils.isEmpty(mergeNumber)) {
2917 break;
2918 }
2919 }
2920 }
2921 }
2922
2923 // Shortcut when no active merged subscribers
2924 if (TextUtils.isEmpty(mergeNumber)) {
2925 return null;
2926 }
2927
2928 // Second pass, find all subscribers under that line override
2929 final ArraySet<String> result = new ArraySet<>();
2930 for (String key : prefs.keySet()) {
2931 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
2932 final String number = (String) prefs.get(key);
2933 if (mergeNumber.equals(number)) {
2934 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
2935 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2936 final String subscriberId = (String) prefs.get(subscriberKey);
2937 if (!TextUtils.isEmpty(subscriberId)) {
2938 result.add(subscriberId);
2939 }
2940 }
2941 }
2942 }
2943
2944 final String[] resultArray = result.toArray(new String[result.size()]);
2945 Arrays.sort(resultArray);
2946 if (DBG_MERGE) {
2947 Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
2948 }
2949 return resultArray;
2950 }
2951
2952 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002953 public boolean setOperatorBrandOverride(int subId, String brand) {
2954 enforceCarrierPrivilege(subId);
2955 final Phone phone = getPhone(subId);
2956 return phone == null ? false : phone.setOperatorBrandOverride(brand);
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002957 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002958
2959 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002960 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08002961 List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2962 List<String> cdmaNonRoamingList) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002963 enforceCarrierPrivilege(subId);
2964 final Phone phone = getPhone(subId);
2965 if (phone == null) {
2966 return false;
2967 }
2968 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08002969 cdmaNonRoamingList);
2970 }
2971
2972 @Override
Amit Mahajanf43fe462017-02-23 12:08:31 -08002973 @Deprecated
Steven Liu4bf01bc2014-07-17 11:05:29 -05002974 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2975 enforceModifyPermission();
2976
2977 int returnValue = 0;
2978 try {
2979 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2980 if(result.exception == null) {
2981 if (result.result != null) {
2982 byte[] responseData = (byte[])(result.result);
2983 if(responseData.length > oemResp.length) {
2984 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2985 responseData.length + "bytes. Buffer Size is " +
2986 oemResp.length + "bytes.");
2987 }
2988 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2989 returnValue = responseData.length;
2990 }
2991 } else {
2992 CommandException ex = (CommandException) result.exception;
2993 returnValue = ex.getCommandError().ordinal();
2994 if(returnValue > 0) returnValue *= -1;
2995 }
2996 } catch (RuntimeException e) {
2997 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2998 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2999 if(returnValue > 0) returnValue *= -1;
3000 }
3001
3002 return returnValue;
3003 }
Wink Saville5d475dd2014-10-17 15:00:58 -07003004
3005 @Override
3006 public void setRadioCapability(RadioAccessFamily[] rafs) {
3007 try {
3008 ProxyController.getInstance().setRadioCapability(rafs);
3009 } catch (RuntimeException e) {
3010 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
3011 }
3012 }
3013
3014 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07003015 public int getRadioAccessFamily(int phoneId, String callingPackage) {
3016 if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
3017 return RadioAccessFamily.RAF_UNKNOWN;
3018 }
3019
Wink Saville5d475dd2014-10-17 15:00:58 -07003020 return ProxyController.getInstance().getRadioAccessFamily(phoneId);
3021 }
Andrew Leedf14ead2014-10-17 14:22:52 -07003022
3023 @Override
3024 public void enableVideoCalling(boolean enable) {
3025 enforceModifyPermission();
Tyler Gunnfdd69de2015-12-04 21:24:38 -08003026 ImsManager.setVtSetting(mPhone.getContext(), enable);
Andrew Leedf14ead2014-10-17 14:22:52 -07003027 }
3028
3029 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07003030 public boolean isVideoCallingEnabled(String callingPackage) {
3031 if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
3032 return false;
3033 }
3034
Andrew Lee77527ac2014-10-21 16:57:39 -07003035 // Check the user preference and the system-level IMS setting. Even if the user has
3036 // enabled video calling, if IMS is disabled we aren't able to support video calling.
3037 // In the long run, we may instead need to check if there exists a connection service
3038 // which can support video calling.
Andrew Lee312e8172014-10-23 17:01:36 -07003039 return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
3040 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
Tyler Gunnfdd69de2015-12-04 21:24:38 -08003041 && ImsManager.isVtEnabledByUser(mPhone.getContext());
Andrew Leedf14ead2014-10-17 14:22:52 -07003042 }
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06003043
Andrew Leea1239f22015-03-02 17:44:07 -08003044 @Override
3045 public boolean canChangeDtmfToneLength() {
Jonathan Basseri9504c6b2015-06-04 14:23:32 -07003046 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
Andrew Leea1239f22015-03-02 17:44:07 -08003047 }
3048
3049 @Override
3050 public boolean isWorldPhone() {
Jonathan Basseri9504c6b2015-06-04 14:23:32 -07003051 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
Andrew Leea1239f22015-03-02 17:44:07 -08003052 }
3053
Andrew Lee9431b832015-03-09 18:46:45 -07003054 @Override
3055 public boolean isTtyModeSupported() {
3056 TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
3057 TelephonyManager telephonyManager =
3058 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
Wooki Wu1f82f7a2016-02-15 15:59:58 +08003059 return telecomManager.isTtySupported();
Andrew Lee9431b832015-03-09 18:46:45 -07003060 }
3061
3062 @Override
3063 public boolean isHearingAidCompatibilitySupported() {
3064 return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
3065 }
3066
Sanket Padawe7310cc72015-01-14 09:53:20 -08003067 /**
3068 * Returns the unique device ID of phone, for example, the IMEI for
3069 * GSM and the MEID for CDMA phones. Return null if device ID is not available.
3070 *
3071 * <p>Requires Permission:
3072 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
3073 */
3074 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07003075 public String getDeviceId(String callingPackage) {
3076 if (!canReadPhoneState(callingPackage, "getDeviceId")) {
3077 return null;
3078 }
3079
Sanket Padawe7310cc72015-01-14 09:53:20 -08003080 final Phone phone = PhoneFactory.getPhone(0);
3081 if (phone != null) {
3082 return phone.getDeviceId();
3083 } else {
3084 return null;
3085 }
3086 }
3087
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06003088 /*
3089 * {@hide}
3090 * Returns the IMS Registration Status
3091 */
Santos Cordon7a1885b2015-02-03 11:15:19 -08003092 @Override
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06003093 public boolean isImsRegistered() {
3094 return mPhone.isImsRegistered();
3095 }
Santos Cordon7a1885b2015-02-03 11:15:19 -08003096
3097 @Override
3098 public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
3099 return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
3100 }
Nathan Harolddcfc7932015-03-18 10:01:20 -07003101
Nathan Haroldc55097a2015-03-11 18:14:50 -07003102 /*
3103 * {@hide}
3104 * Returns the IMS Registration Status
3105 */
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003106 public boolean isWifiCallingAvailable() {
Nathan Haroldc55097a2015-03-11 18:14:50 -07003107 return mPhone.isWifiCallingEnabled();
3108 }
3109
3110 /*
3111 * {@hide}
3112 * Returns the IMS Registration Status
3113 */
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003114 public boolean isVolteAvailable() {
Nathan Haroldc55097a2015-03-11 18:14:50 -07003115 return mPhone.isVolteEnabled();
3116 }
Svet Ganovb320e182015-04-16 12:30:10 -07003117
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003118 /*
3119 * {@hide} Returns the IMS Registration Status
3120 */
3121 public boolean isVideoTelephonyAvailable() {
3122 return mPhone.isVideoEnabled();
3123 }
3124
Svet Ganovb320e182015-04-16 12:30:10 -07003125 private boolean canReadPhoneState(String callingPackage, String message) {
Etan Cohen921655c2015-06-24 13:54:50 -07003126 try {
Amit Mahajan83ea23b2015-07-30 16:05:11 -07003127 mApp.enforceCallingOrSelfPermission(
Etan Cohen921655c2015-06-24 13:54:50 -07003128 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
3129
Amit Mahajan83ea23b2015-07-30 16:05:11 -07003130 // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
Etan Cohen921655c2015-06-24 13:54:50 -07003131 return true;
Amit Mahajan785783f2015-06-29 10:36:50 -07003132 } catch (SecurityException e) {
3133 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
3134 message);
Etan Cohen921655c2015-06-24 13:54:50 -07003135 }
Svet Ganovb320e182015-04-16 12:30:10 -07003136
3137 if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
3138 callingPackage) != AppOpsManager.MODE_ALLOWED) {
3139 return false;
3140 }
3141
3142 return true;
3143 }
Stuart Scott8eef64f2015-04-08 15:13:54 -07003144
Makoto Onukifee69342015-06-29 14:44:50 -07003145 /**
Amit Mahajanb9b49782015-09-15 18:16:32 -07003146 * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
Makoto Onukifee69342015-06-29 14:44:50 -07003147 */
3148 private boolean canReadPhoneNumber(String callingPackage, String message) {
Makoto Onukie4072d12015-08-03 15:12:23 -07003149 // Default SMS app can always read it.
3150 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
3151 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
3152 return true;
3153 }
3154 try {
3155 return canReadPhoneState(callingPackage, message);
Amit Mahajanb9b49782015-09-15 18:16:32 -07003156 } catch (SecurityException readPhoneStateSecurityException) {
3157 try {
3158 // Can be read with READ_SMS too.
3159 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
3160 return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
3161 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
3162 } catch (SecurityException readSmsSecurityException) {
3163 // Throw exception with message including both READ_PHONE_STATE and READ_SMS
3164 // permissions
3165 throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
3166 " nor current process has " + android.Manifest.permission.READ_PHONE_STATE +
3167 " or " + android.Manifest.permission.READ_SMS + ".");
3168 }
Makoto Onukie4072d12015-08-03 15:12:23 -07003169 }
Makoto Onukifee69342015-06-29 14:44:50 -07003170 }
3171
Stuart Scott8eef64f2015-04-08 15:13:54 -07003172 @Override
3173 public void factoryReset(int subId) {
3174 enforceConnectivityInternalPermission();
Stuart Scott981d8582015-04-21 14:09:50 -07003175 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
3176 return;
3177 }
3178
Svet Ganovcc087f82015-05-12 20:35:54 -07003179 final long identity = Binder.clearCallingIdentity();
3180 try {
Stuart Scott981d8582015-04-21 14:09:50 -07003181 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
3182 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Svet Ganovcc087f82015-05-12 20:35:54 -07003183 // Enable data
3184 setDataEnabled(subId, true);
3185 // Set network selection mode to automatic
3186 setNetworkSelectionModeAutomatic(subId);
3187 // Set preferred mobile network type to the best available
3188 setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
3189 // Turn off roaming
3190 SubscriptionManager.from(mApp).setDataRoaming(0, subId);
3191 }
3192 } finally {
3193 Binder.restoreCallingIdentity(identity);
Stuart Scott8eef64f2015-04-08 15:13:54 -07003194 }
3195 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01003196
3197 @Override
3198 public String getLocaleFromDefaultSim() {
3199 // We query all subscriptions instead of just the active ones, because
3200 // this might be called early on in the provisioning flow when the
3201 // subscriptions potentially aren't active yet.
3202 final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
3203 if (slist == null || slist.isEmpty()) {
3204 return null;
3205 }
3206
3207 // This function may be called very early, say, from the setup wizard, at
3208 // which point we won't have a default subscription set. If that's the case
3209 // we just choose the first, which will be valid in "most cases".
3210 final int defaultSubId = getDefaultSubscription();
3211 SubscriptionInfo info = null;
3212 if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
3213 info = slist.get(0);
3214 } else {
3215 for (SubscriptionInfo item : slist) {
3216 if (item.getSubscriptionId() == defaultSubId) {
3217 info = item;
3218 break;
3219 }
3220 }
3221
3222 if (info == null) {
3223 return null;
3224 }
3225 }
3226
3227 // Try and fetch the locale from the carrier properties or from the SIM language
3228 // preferences (EF-PL and EF-LI)...
Tony Hill183b2de2015-06-24 14:53:58 +01003229 final int mcc = info.getMcc();
Narayan Kamath1c496c22015-04-16 14:40:19 +01003230 final Phone defaultPhone = getPhone(info.getSubscriptionId());
Narayan Kamath011676f2015-07-29 12:04:08 +01003231 String simLanguage = null;
Narayan Kamath1c496c22015-04-16 14:40:19 +01003232 if (defaultPhone != null) {
3233 final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
3234 if (localeFromDefaultSim != null) {
Narayan Kamath011676f2015-07-29 12:04:08 +01003235 if (!localeFromDefaultSim.getCountry().isEmpty()) {
Tony Hill183b2de2015-06-24 14:53:58 +01003236 if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim);
3237 return localeFromDefaultSim.toLanguageTag();
Narayan Kamath011676f2015-07-29 12:04:08 +01003238 } else {
3239 simLanguage = localeFromDefaultSim.getLanguage();
Tony Hill183b2de2015-06-24 14:53:58 +01003240 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01003241 }
3242 }
3243
Narayan Kamath011676f2015-07-29 12:04:08 +01003244 // The SIM language preferences only store a language (e.g. fr = French), not an
3245 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
3246 // the SIM and carrier preferences does not include a country we add the country
3247 // determined from the SIM MCC to provide an exact locale.
3248 final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage);
Tony Hill183b2de2015-06-24 14:53:58 +01003249 if (mccLocale != null) {
3250 if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale);
3251 return mccLocale.toLanguageTag();
Narayan Kamath1c496c22015-04-16 14:40:19 +01003252 }
3253
Tony Hill183b2de2015-06-24 14:53:58 +01003254 if (DBG) log("No locale found - returning null");
Narayan Kamath1c496c22015-04-16 14:40:19 +01003255 return null;
3256 }
3257
3258 private List<SubscriptionInfo> getAllSubscriptionInfoList() {
3259 final long identity = Binder.clearCallingIdentity();
3260 try {
3261 return mSubscriptionController.getAllSubInfoList(
3262 mPhone.getContext().getOpPackageName());
3263 } finally {
3264 Binder.restoreCallingIdentity(identity);
3265 }
3266 }
3267
3268 private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
3269 final long identity = Binder.clearCallingIdentity();
3270 try {
3271 return mSubscriptionController.getActiveSubscriptionInfoList(
3272 mPhone.getContext().getOpPackageName());
3273 } finally {
3274 Binder.restoreCallingIdentity(identity);
3275 }
3276 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003277
3278 /**
Adam Lesinski903a54c2016-04-11 14:49:52 -07003279 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
3280 * representing the state of the modem.
3281 *
3282 * NOTE: This clears the modem state, so there should only every be one caller.
3283 * @hide
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003284 */
3285 @Override
Adam Lesinski903a54c2016-04-11 14:49:52 -07003286 public void requestModemActivityInfo(ResultReceiver result) {
3287 enforceModifyPermission();
3288
3289 ModemActivityInfo info = (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
3290 Bundle bundle = new Bundle();
3291 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, info);
3292 result.send(0, bundle);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003293 }
Jack Yu85bd38a2015-11-09 11:34:32 -08003294
3295 /**
3296 * {@hide}
3297 * Returns the service state information on specified subscription.
3298 */
3299 @Override
3300 public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
3301
3302 if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
3303 return null;
3304 }
3305
3306 final Phone phone = getPhone(subId);
3307 if (phone == null) {
3308 return null;
3309 }
3310
3311 return phone.getServiceState();
3312 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08003313
3314 /**
3315 * Returns the URI for the per-account voicemail ringtone set in Phone settings.
3316 *
3317 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3318 * voicemail ringtone.
3319 * @return The URI for the ringtone to play when receiving a voicemail from a specific
3320 * PhoneAccount.
3321 */
3322 @Override
3323 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
3324 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3325 if (phone == null) {
3326 return null;
3327 }
3328
3329 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
3330 }
3331
3332 /**
3333 * Returns whether vibration is set for voicemail notification in Phone settings.
3334 *
3335 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3336 * voicemail vibration setting.
3337 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
3338 */
3339 @Override
3340 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
3341 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3342 if (phone == null) {
3343 return false;
3344 }
3345
3346 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone);
3347 }
3348
Youhan Wange64578a2016-05-02 15:32:42 -07003349 /**
3350 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
3351 *
3352 * @throws SecurityException if the caller does not have the required permission
3353 */
3354 private void enforceReadPrivilegedPermission() {
3355 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3356 null);
3357 }
3358
3359 /**
3360 * Return the application ID for the app type.
3361 *
3362 * @param subId the subscription ID that this request applies to.
3363 * @param appType the uicc app type.
3364 * @return Application ID for specificied app type, or null if no uicc.
3365 */
3366 @Override
3367 public String getAidForAppType(int subId, int appType) {
3368 enforceReadPrivilegedPermission();
3369 Phone phone = getPhone(subId);
3370 if (phone == null) {
3371 return null;
3372 }
3373 String aid = null;
3374 try {
3375 aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
3376 .getApplicationByType(appType).getAid();
3377 } catch (Exception e) {
3378 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
3379 }
3380 return aid;
3381 }
3382
Youhan Wang4001d252016-05-11 10:29:41 -07003383 /**
3384 * Return the Electronic Serial Number.
3385 *
3386 * @param subId the subscription ID that this request applies to.
3387 * @return ESN or null if error.
3388 */
3389 @Override
3390 public String getEsn(int subId) {
3391 enforceReadPrivilegedPermission();
3392 Phone phone = getPhone(subId);
3393 if (phone == null) {
3394 return null;
3395 }
3396 String esn = null;
3397 try {
3398 esn = phone.getEsn();
3399 } catch (Exception e) {
3400 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
3401 }
3402 return esn;
3403 }
3404
Sanket Padawe99ef1e32016-05-18 16:12:33 -07003405 /**
Youhan Wang66ad5d72016-07-18 17:56:58 -07003406 * Return the Preferred Roaming List Version.
3407 *
3408 * @param subId the subscription ID that this request applies to.
3409 * @return PRLVersion or null if error.
3410 */
3411 @Override
3412 public String getCdmaPrlVersion(int subId) {
3413 enforceReadPrivilegedPermission();
3414 Phone phone = getPhone(subId);
3415 if (phone == null) {
3416 return null;
3417 }
3418 String cdmaPrlVersion = null;
3419 try {
3420 cdmaPrlVersion = phone.getCdmaPrlVersion();
3421 } catch (Exception e) {
3422 Log.e(LOG_TAG, "Not getting PRLVersion", e);
3423 }
3424 return cdmaPrlVersion;
3425 }
3426
3427 /**
Sanket Padawe99ef1e32016-05-18 16:12:33 -07003428 * Get snapshot of Telephony histograms
3429 * @return List of Telephony histograms
3430 * @hide
3431 */
3432 @Override
3433 public List<TelephonyHistogram> getTelephonyHistograms() {
3434 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
3435 return RIL.getTelephonyRILTimingHistograms();
3436 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07003437
3438 /**
3439 * {@hide}
Sanket Padawe5780e442017-03-20 15:04:47 -07003440 * Set the allowed carrier list for slotIndex
Meng Wang1a7c35a2016-05-05 20:56:15 -07003441 * Require system privileges. In the future we may add this to carrier APIs.
3442 *
3443 * @return The number of carriers set successfully, should match length of carriers
3444 */
3445 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07003446 public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
Meng Wang1a7c35a2016-05-05 20:56:15 -07003447 enforceModifyPermission();
Sanket Padawe5780e442017-03-20 15:04:47 -07003448 int subId = SubscriptionManager.getSubId(slotIndex)[0];
Meng Wang1a7c35a2016-05-05 20:56:15 -07003449 int[] retVal = (int[]) sendRequest(CMD_SET_ALLOWED_CARRIERS, carriers, subId);
3450 return retVal[0];
3451 }
3452
3453 /**
3454 * {@hide}
Sanket Padawe5780e442017-03-20 15:04:47 -07003455 * Get the allowed carrier list for slotIndex.
Meng Wang1a7c35a2016-05-05 20:56:15 -07003456 * Require system privileges. In the future we may add this to carrier APIs.
3457 *
3458 * @return List of {@link android.service.telephony.CarrierIdentifier}; empty list
3459 * means all carriers are allowed.
3460 */
3461 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07003462 public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
Meng Wang1a7c35a2016-05-05 20:56:15 -07003463 enforceReadPrivilegedPermission();
Sanket Padawe5780e442017-03-20 15:04:47 -07003464 int subId = SubscriptionManager.getSubId(slotIndex)[0];
Meng Wang1a7c35a2016-05-05 20:56:15 -07003465 return (List<CarrierIdentifier>) sendRequest(CMD_GET_ALLOWED_CARRIERS, null, subId);
3466 }
3467
fionaxu59545b42016-05-25 15:53:37 -07003468 /**
3469 * Action set from carrier signalling broadcast receivers to enable/disable metered apns
3470 * @param subId the subscription ID that this action applies to.
3471 * @param enabled control enable or disable metered apns.
3472 * {@hide}
3473 */
3474 @Override
3475 public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
3476 enforceModifyPermission();
3477 final Phone phone = getPhone(subId);
3478 if (phone == null) {
3479 loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
3480 return;
3481 }
3482 try {
3483 phone.carrierActionSetMeteredApnsEnabled(enabled);
3484 } catch (Exception e) {
3485 Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
3486 }
3487 }
3488
3489 /**
3490 * Action set from carrier signalling broadcast receivers to enable/disable radio
3491 * @param subId the subscription ID that this action applies to.
3492 * @param enabled control enable or disable radio.
3493 * {@hide}
3494 */
3495 @Override
3496 public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
3497 enforceModifyPermission();
3498 final Phone phone = getPhone(subId);
3499 if (phone == null) {
3500 loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
3501 return;
3502 }
3503 try {
3504 phone.carrierActionSetRadioEnabled(enabled);
3505 } catch (Exception e) {
3506 Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
3507 }
3508 }
3509
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07003510 /**
3511 * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
3512 * bug report is being generated.
3513 */
3514 @Override
Ta-wei Yen99282e02016-06-21 18:19:35 -07003515 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
dcashman22b950d2016-06-27 11:39:02 -07003516 if (mPhone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
3517 != PackageManager.PERMISSION_GRANTED) {
3518 writer.println("Permission Denial: can't dump Phone from pid="
3519 + Binder.getCallingPid()
3520 + ", uid=" + Binder.getCallingUid()
3521 + "without permission "
3522 + android.Manifest.permission.DUMP);
3523 return;
3524 }
Ta-wei Yen99282e02016-06-21 18:19:35 -07003525 DumpsysHandler.dump(mPhone.getContext(), fd, writer, args);
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07003526 }
Jack Yueb89b242016-06-22 13:27:47 -07003527
3528 /**
3529 * Get aggregated video call data usage from all subscriptions since boot.
3530 * @return total data usage in bytes
3531 * {@hide}
3532 */
3533 @Override
3534 public long getVtDataUsage() {
3535 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
3536 null);
3537
3538 // NetworkStatsService keeps tracking the active network interface and identity. It will
3539 // record the delta with the corresponding network identity. What we need to do here is
3540 // returning total video call data usage from all subscriptions since boot.
3541
3542 // TODO: Add sub id support in the future. We'll need it when we support DSDA and
3543 // simultaneous VT calls.
3544 final Phone[] phones = PhoneFactory.getPhones();
3545 long total = 0;
3546 for (Phone phone : phones) {
3547 total += phone.getVtDataUsage();
3548 }
3549 return total;
3550 }
Jack Yu75ab2952016-07-08 14:29:33 -07003551
3552 /**
3553 * Policy control of data connection. Usually used when data limit is passed.
3554 * @param enabled True if enabling the data, otherwise disabling.
3555 * @param subId Subscription index
3556 * {@hide}
3557 */
3558 @Override
3559 public void setPolicyDataEnabled(boolean enabled, int subId) {
3560 enforceModifyPermission();
3561 Phone phone = getPhone(subId);
3562 if (phone != null) {
3563 phone.setPolicyDataEnabled(enabled);
3564 }
3565 }
Sooraj Sasindran22882212016-07-18 11:57:25 -07003566
3567 /**
3568 * Get Client request stats
3569 * @return List of Client Request Stats
3570 * @hide
3571 */
3572 @Override
3573 public List<ClientRequestStats> getClientRequestStats(String callingPackage, int subId) {
3574 if (!canReadPhoneState(callingPackage, "getClientRequestStats")) {
3575 return null;
3576 }
3577
3578 Phone phone = getPhone(subId);
3579 if (phone != null) {
3580 return phone.getClientRequestStats();
3581 }
3582
3583 return null;
3584 }
3585
3586 private WorkSource getWorkSource(WorkSource workSource, int uid) {
3587 if (workSource != null) {
3588 return workSource;
3589 }
3590
3591 String packageName = mPhone.getContext().getPackageManager().getNameForUid(uid);
3592 workSource = new WorkSource(uid, packageName);
3593 return workSource;
3594 }
Jack Yu346de222017-02-16 15:32:43 -08003595
3596 /**
3597 * Set SIM card power state. Request is equivalent to inserting or removing the card.
3598 *
Sanket Padawe5780e442017-03-20 15:04:47 -07003599 * @param slotIndex SIM slot id.
Jack Yu346de222017-02-16 15:32:43 -08003600 * @param powerUp True if powering up the SIM, otherwise powering down
3601 *
3602 **/
3603 @Override
Sanket Padawe5780e442017-03-20 15:04:47 -07003604 public void setSimPowerStateForSlot(int slotIndex, boolean powerUp) {
Jack Yu346de222017-02-16 15:32:43 -08003605 enforceModifyPermission();
Sanket Padawe5780e442017-03-20 15:04:47 -07003606 int subId[] = mSubscriptionController.getSubIdUsingSlotIndex(slotIndex);
Jack Yu346de222017-02-16 15:32:43 -08003607 if (subId == null || subId.length == 0) {
3608 return;
3609 }
3610
3611 final Phone phone = getPhone(subId[0]);
3612 if (phone != null) {
3613 phone.setSimPowerState(powerUp);
3614 }
3615 }
shuoqfef36a32017-01-10 13:02:18 -08003616
3617 /**
3618 * Check if phone is in emergency callback mode
3619 * @return true if phone is in emergency callback mode
3620 * @param subId sub id
3621 */
3622 public boolean getEmergencyCallbackMode(int subId) {
3623 final Phone phone = getPhone(subId);
3624 if (phone != null) {
3625 return phone.isInEcm();
3626 } else {
3627 return false;
3628 }
3629 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003630}