blob: 8e487e1f035cf042872bf2c91107b1265b3d9e28 [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
19import android.app.ActivityManager;
20import android.app.AppOpsManager;
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -070021import android.content.ComponentName;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070022import android.content.Context;
23import android.content.Intent;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070024import android.content.pm.PackageInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.Signature;
Wink Saville36469e72014-06-11 15:17:00 -070027import android.net.ConnectivityManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070028import android.net.Uri;
29import android.os.AsyncResult;
30import android.os.Binder;
31import android.os.Bundle;
32import android.os.Handler;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070033import android.os.IBinder;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070034import android.os.Looper;
35import android.os.Message;
36import android.os.Process;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070037import android.os.RemoteException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070038import android.os.ServiceManager;
Wink Saville08874612014-08-31 19:19:58 -070039import android.os.SystemProperties;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070040import android.os.UserHandle;
Ihab Awadf2177b72013-11-25 13:33:23 -080041import android.provider.Settings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070042import android.telephony.CellInfo;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070043import android.telephony.IccOpenLogicalChannelResponse;
Jake Hambye994d462014-02-03 13:10:13 -080044import android.telephony.NeighboringCellInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070045import android.telephony.ServiceState;
Wink Saville36469e72014-06-11 15:17:00 -070046import android.telephony.SubscriptionManager;
Wink Saville08874612014-08-31 19:19:58 -070047import android.telephony.SubInfoRecord;
Ihab Awadf2177b72013-11-25 13:33:23 -080048import android.telephony.TelephonyManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070049import android.text.TextUtils;
50import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -080051import android.util.Pair;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070052
Shishir Agrawal566b7612013-10-28 14:41:00 -070053import com.android.internal.telephony.CallManager;
54import com.android.internal.telephony.CommandException;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070055import com.android.internal.telephony.Connection;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070056import com.android.internal.telephony.DefaultPhoneNotifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070057import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -080058import com.android.internal.telephony.IccCard;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070059import com.android.internal.telephony.Phone;
Wink Saville36469e72014-06-11 15:17:00 -070060import com.android.internal.telephony.PhoneFactory;
61import com.android.internal.telephony.CallManager;
62import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070063import com.android.internal.telephony.PhoneConstants;
Wink Saville08874612014-08-31 19:19:58 -070064import com.android.internal.telephony.TelephonyIntents;
Wink Saville36469e72014-06-11 15:17:00 -070065import com.android.internal.telephony.dataconnection.DctController;
Derek Tan7226c842014-07-02 17:42:23 -070066import com.android.internal.telephony.uicc.AdnRecord;
Shishir Agrawal566b7612013-10-28 14:41:00 -070067import com.android.internal.telephony.uicc.IccIoResult;
68import com.android.internal.telephony.uicc.IccUtils;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -070069import com.android.internal.telephony.uicc.UiccCard;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070070import com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
Shishir Agrawal566b7612013-10-28 14:41:00 -070071import com.android.internal.telephony.uicc.UiccController;
Jake Hambye994d462014-02-03 13:10:13 -080072import com.android.internal.util.HexDump;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070073
Wink Saville36469e72014-06-11 15:17:00 -070074import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
75
Santos Cordon7d4ddf62013-07-10 11:58:08 -070076import java.util.ArrayList;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070077import java.util.HashMap;
Derek Tan89e89d42014-07-08 17:00:10 -070078import java.util.HashSet;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070079import java.util.Iterator;
Jake Hambye994d462014-02-03 13:10:13 -080080import java.util.List;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070081import java.util.Map;
Derek Tan89e89d42014-07-08 17:00:10 -070082import java.util.Set;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070083
84/**
85 * Implementation of the ITelephony interface.
86 */
Santos Cordon117fee72014-05-16 17:56:12 -070087public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070088 private static final String LOG_TAG = "PhoneInterfaceManager";
89 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
90 private static final boolean DBG_LOC = false;
91
92 // Message codes used with mMainThreadHandler
93 private static final int CMD_HANDLE_PIN_MMI = 1;
94 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
95 private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
96 private static final int CMD_ANSWER_RINGING_CALL = 4;
97 private static final int CMD_END_CALL = 5; // not used yet
98 private static final int CMD_SILENCE_RINGER = 6;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070099 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
100 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700101 private static final int CMD_OPEN_CHANNEL = 9;
102 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
103 private static final int CMD_CLOSE_CHANNEL = 11;
104 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800105 private static final int CMD_NV_READ_ITEM = 13;
106 private static final int EVENT_NV_READ_ITEM_DONE = 14;
107 private static final int CMD_NV_WRITE_ITEM = 15;
108 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
109 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
110 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
111 private static final int CMD_NV_RESET_CONFIG = 19;
112 private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800113 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
114 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
115 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
116 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800117 private static final int CMD_SEND_ENVELOPE = 25;
118 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Junda Liu787bc7e2014-06-30 13:38:02 -0700119 private static final int CMD_SET_CDMA_SUBSCRIPTION = 27;
120 private static final int EVENT_SET_CDMA_SUBSCRIPTION_DONE = 28;
Steven Liu4bf01bc2014-07-17 11:05:29 -0500121 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 29;
122 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 30;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700123 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 31;
124 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 32;
125 private static final int CMD_EXCHANGE_SIM_IO = 33;
126 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 34;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700127
128 /** The singleton instance. */
129 private static PhoneInterfaceManager sInstance;
130
131 PhoneGlobals mApp;
132 Phone mPhone;
133 CallManager mCM;
134 AppOpsManager mAppOps;
135 MainThreadHandler mMainThreadHandler;
136
137 /**
Derek Tan89e89d42014-07-08 17:00:10 -0700138 * Indicates if Android should display a simplified Mobile Network Settings UI in a specific
139 * subscription.
140 */
141 Set<Long> mSimplifiedNetworkSettings;
Derek Tan7226c842014-07-02 17:42:23 -0700142 Map<Long, AdnRecord> mAdnRecordsForDisplay;
Derek Tan89e89d42014-07-08 17:00:10 -0700143
144 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700145 * A request object to use for transmitting data to an ICC.
146 */
147 private static final class IccAPDUArgument {
148 public int channel, cla, command, p1, p2, p3;
149 public String data;
150
151 public IccAPDUArgument(int channel, int cla, int command,
152 int p1, int p2, int p3, String data) {
153 this.channel = channel;
154 this.cla = cla;
155 this.command = command;
156 this.p1 = p1;
157 this.p2 = p2;
158 this.p3 = p3;
159 this.data = data;
160 }
161 }
162
163 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700164 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
165 * request after sending. The main thread will notify the request when it is complete.
166 */
167 private static final class MainThreadRequest {
168 /** The argument to use for the request */
169 public Object argument;
170 /** The result of the request that is run on the main thread */
171 public Object result;
172
173 public MainThreadRequest(Object argument) {
174 this.argument = argument;
175 }
176 }
177
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800178 private static final class IncomingThirdPartyCallArgs {
179 public final ComponentName component;
180 public final String callId;
181 public final String callerDisplayName;
182
183 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
184 String callerDisplayName) {
185 this.component = component;
186 this.callId = callId;
187 this.callerDisplayName = callerDisplayName;
188 }
189 }
190
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700191 /**
192 * A handler that processes messages on the main thread in the phone process. Since many
193 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
194 * inbound binder threads to the main thread in the phone process. The Binder thread
195 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
196 * on, which will be notified when the operation completes and will contain the result of the
197 * request.
198 *
199 * <p>If a MainThreadRequest object is provided in the msg.obj field,
200 * note that request.result must be set to something non-null for the calling thread to
201 * unblock.
202 */
203 private final class MainThreadHandler extends Handler {
204 @Override
205 public void handleMessage(Message msg) {
206 MainThreadRequest request;
207 Message onCompleted;
208 AsyncResult ar;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700209 UiccCard uiccCard = UiccController.getInstance().getUiccCard();
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700210 IccAPDUArgument iccArgument;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700211
212 switch (msg.what) {
213 case CMD_HANDLE_PIN_MMI:
214 request = (MainThreadRequest) msg.obj;
Jake Hambye994d462014-02-03 13:10:13 -0800215 request.result = mPhone.handlePinMmi((String) request.argument);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700216 // Wake up the requesting thread
217 synchronized (request) {
218 request.notifyAll();
219 }
220 break;
221
222 case CMD_HANDLE_NEIGHBORING_CELL:
223 request = (MainThreadRequest) msg.obj;
224 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
225 request);
226 mPhone.getNeighboringCids(onCompleted);
227 break;
228
229 case EVENT_NEIGHBORING_CELL_DONE:
230 ar = (AsyncResult) msg.obj;
231 request = (MainThreadRequest) ar.userObj;
232 if (ar.exception == null && ar.result != null) {
233 request.result = ar.result;
234 } else {
235 // create an empty list to notify the waiting thread
Jake Hambye994d462014-02-03 13:10:13 -0800236 request.result = new ArrayList<NeighboringCellInfo>(0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700237 }
238 // Wake up the requesting thread
239 synchronized (request) {
240 request.notifyAll();
241 }
242 break;
243
244 case CMD_ANSWER_RINGING_CALL:
Wink Saville08874612014-08-31 19:19:58 -0700245 request = (MainThreadRequest) msg.obj;
246 long answer_subId = ((Long)request.argument).longValue();
247 answerRingingCallInternal(answer_subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700248 break;
249
250 case CMD_SILENCE_RINGER:
251 silenceRingerInternal();
252 break;
253
254 case CMD_END_CALL:
255 request = (MainThreadRequest) msg.obj;
Wink Saville08874612014-08-31 19:19:58 -0700256 long end_subId = ((Long)request.argument).longValue();
257 final boolean hungUp;
258 int phoneType = getPhone(end_subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700259 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
260 // CDMA: If the user presses the Power button we treat it as
261 // ending the complete call session
Wink Saville08874612014-08-31 19:19:58 -0700262 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700263 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
264 // GSM: End the call as per the Phone state
265 hungUp = PhoneUtils.hangup(mCM);
266 } else {
267 throw new IllegalStateException("Unexpected phone type: " + phoneType);
268 }
269 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
270 request.result = hungUp;
271 // Wake up the requesting thread
272 synchronized (request) {
273 request.notifyAll();
274 }
275 break;
276
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700277 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700278 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700279 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700280 if (uiccCard == null) {
281 loge("iccTransmitApduLogicalChannel: No UICC");
282 request.result = new IccIoResult(0x6F, 0, (byte[])null);
283 synchronized (request) {
284 request.notifyAll();
285 }
286 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700287 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
288 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700289 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700290 iccArgument.channel, iccArgument.cla, iccArgument.command,
291 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700292 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700293 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700294 break;
295
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700296 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700297 ar = (AsyncResult) msg.obj;
298 request = (MainThreadRequest) ar.userObj;
299 if (ar.exception == null && ar.result != null) {
300 request.result = ar.result;
301 } else {
302 request.result = new IccIoResult(0x6F, 0, (byte[])null);
303 if (ar.result == null) {
304 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800305 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700306 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800307 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700308 } else {
309 loge("iccTransmitApduLogicalChannel: Unknown exception");
310 }
311 }
312 synchronized (request) {
313 request.notifyAll();
314 }
315 break;
316
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700317 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
318 request = (MainThreadRequest) msg.obj;
319 iccArgument = (IccAPDUArgument) request.argument;
320 if (uiccCard == null) {
321 loge("iccTransmitApduBasicChannel: No UICC");
322 request.result = new IccIoResult(0x6F, 0, (byte[])null);
323 synchronized (request) {
324 request.notifyAll();
325 }
326 } else {
327 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
328 request);
329 uiccCard.iccTransmitApduBasicChannel(
330 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
331 iccArgument.p3, iccArgument.data, onCompleted);
332 }
333 break;
334
335 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
336 ar = (AsyncResult) msg.obj;
337 request = (MainThreadRequest) ar.userObj;
338 if (ar.exception == null && ar.result != null) {
339 request.result = ar.result;
340 } else {
341 request.result = new IccIoResult(0x6F, 0, (byte[])null);
342 if (ar.result == null) {
343 loge("iccTransmitApduBasicChannel: Empty response");
344 } else if (ar.exception instanceof CommandException) {
345 loge("iccTransmitApduBasicChannel: CommandException: " +
346 ar.exception);
347 } else {
348 loge("iccTransmitApduBasicChannel: Unknown exception");
349 }
350 }
351 synchronized (request) {
352 request.notifyAll();
353 }
354 break;
355
356 case CMD_EXCHANGE_SIM_IO:
357 request = (MainThreadRequest) msg.obj;
358 iccArgument = (IccAPDUArgument) request.argument;
359 if (uiccCard == null) {
360 loge("iccExchangeSimIO: No UICC");
361 request.result = new IccIoResult(0x6F, 0, (byte[])null);
362 synchronized (request) {
363 request.notifyAll();
364 }
365 } else {
366 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
367 request);
368 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
369 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
370 iccArgument.data, onCompleted);
371 }
372 break;
373
374 case EVENT_EXCHANGE_SIM_IO_DONE:
375 ar = (AsyncResult) msg.obj;
376 request = (MainThreadRequest) ar.userObj;
377 if (ar.exception == null && ar.result != null) {
378 request.result = ar.result;
379 } else {
380 request.result = new IccIoResult(0x6f, 0, (byte[])null);
381 }
382 synchronized (request) {
383 request.notifyAll();
384 }
385 break;
386
Derek Tan4d5e5c12014-02-04 11:54:58 -0800387 case CMD_SEND_ENVELOPE:
388 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700389 if (uiccCard == null) {
390 loge("sendEnvelopeWithStatus: No UICC");
391 request.result = new IccIoResult(0x6F, 0, (byte[])null);
392 synchronized (request) {
393 request.notifyAll();
394 }
395 } else {
396 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
397 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
398 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800399 break;
400
401 case EVENT_SEND_ENVELOPE_DONE:
402 ar = (AsyncResult) msg.obj;
403 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700404 if (ar.exception == null && ar.result != null) {
405 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800406 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700407 request.result = new IccIoResult(0x6F, 0, (byte[])null);
408 if (ar.result == null) {
409 loge("sendEnvelopeWithStatus: Empty response");
410 } else if (ar.exception instanceof CommandException) {
411 loge("sendEnvelopeWithStatus: CommandException: " +
412 ar.exception);
413 } else {
414 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
415 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800416 }
417 synchronized (request) {
418 request.notifyAll();
419 }
420 break;
421
Shishir Agrawal566b7612013-10-28 14:41:00 -0700422 case CMD_OPEN_CHANNEL:
423 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700424 if (uiccCard == null) {
425 loge("iccOpenLogicalChannel: No UICC");
426 request.result = new IccIoResult(0x6F, 0, (byte[])null);
427 synchronized (request) {
428 request.notifyAll();
429 }
430 } else {
431 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
432 uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
433 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700434 break;
435
436 case EVENT_OPEN_CHANNEL_DONE:
437 ar = (AsyncResult) msg.obj;
438 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700439 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700440 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700441 int[] result = (int[]) ar.result;
442 int channelId = result[0];
443 byte[] selectResponse = null;
444 if (result.length > 1) {
445 selectResponse = new byte[result.length - 1];
446 for (int i = 1; i < result.length; ++i) {
447 selectResponse[i - 1] = (byte) result[i];
448 }
449 }
450 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700451 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700452 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700453 if (ar.result == null) {
454 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700455 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700456 if (ar.exception != null) {
457 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
458 }
459
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700460 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700461 if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
462 if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700463 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700464 } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700465 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700466 }
467 }
468 openChannelResp = new IccOpenLogicalChannelResponse(
469 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700470 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700471 request.result = openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700472 synchronized (request) {
473 request.notifyAll();
474 }
475 break;
476
477 case CMD_CLOSE_CHANNEL:
478 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700479 if (uiccCard == null) {
480 loge("iccCloseLogicalChannel: No UICC");
481 request.result = new IccIoResult(0x6F, 0, (byte[])null);
482 synchronized (request) {
483 request.notifyAll();
484 }
485 } else {
486 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
487 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
488 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700489 break;
490
491 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800492 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
493 break;
494
495 case CMD_NV_READ_ITEM:
496 request = (MainThreadRequest) msg.obj;
497 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
498 mPhone.nvReadItem((Integer) request.argument, onCompleted);
499 break;
500
501 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700502 ar = (AsyncResult) msg.obj;
503 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800504 if (ar.exception == null && ar.result != null) {
505 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700506 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800507 request.result = "";
508 if (ar.result == null) {
509 loge("nvReadItem: Empty response");
510 } else if (ar.exception instanceof CommandException) {
511 loge("nvReadItem: CommandException: " +
512 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700513 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800514 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700515 }
516 }
517 synchronized (request) {
518 request.notifyAll();
519 }
520 break;
521
Jake Hambye994d462014-02-03 13:10:13 -0800522 case CMD_NV_WRITE_ITEM:
523 request = (MainThreadRequest) msg.obj;
524 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
525 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
526 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
527 break;
528
529 case EVENT_NV_WRITE_ITEM_DONE:
530 handleNullReturnEvent(msg, "nvWriteItem");
531 break;
532
533 case CMD_NV_WRITE_CDMA_PRL:
534 request = (MainThreadRequest) msg.obj;
535 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
536 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
537 break;
538
539 case EVENT_NV_WRITE_CDMA_PRL_DONE:
540 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
541 break;
542
543 case CMD_NV_RESET_CONFIG:
544 request = (MainThreadRequest) msg.obj;
545 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
546 mPhone.nvResetConfig((Integer) request.argument, onCompleted);
547 break;
548
549 case EVENT_NV_RESET_CONFIG_DONE:
550 handleNullReturnEvent(msg, "nvResetConfig");
551 break;
552
Jake Hamby7c27be32014-03-03 13:25:59 -0800553 case CMD_GET_PREFERRED_NETWORK_TYPE:
554 request = (MainThreadRequest) msg.obj;
555 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
556 mPhone.getPreferredNetworkType(onCompleted);
557 break;
558
559 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
560 ar = (AsyncResult) msg.obj;
561 request = (MainThreadRequest) ar.userObj;
562 if (ar.exception == null && ar.result != null) {
563 request.result = ar.result; // Integer
564 } else {
565 request.result = -1;
566 if (ar.result == null) {
567 loge("getPreferredNetworkType: Empty response");
568 } else if (ar.exception instanceof CommandException) {
569 loge("getPreferredNetworkType: CommandException: " +
570 ar.exception);
571 } else {
572 loge("getPreferredNetworkType: Unknown exception");
573 }
574 }
575 synchronized (request) {
576 request.notifyAll();
577 }
578 break;
579
580 case CMD_SET_PREFERRED_NETWORK_TYPE:
581 request = (MainThreadRequest) msg.obj;
582 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
583 int networkType = (Integer) request.argument;
584 mPhone.setPreferredNetworkType(networkType, onCompleted);
585 break;
586
587 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
588 handleNullReturnEvent(msg, "setPreferredNetworkType");
589 break;
590
Junda Liu787bc7e2014-06-30 13:38:02 -0700591 case CMD_SET_CDMA_SUBSCRIPTION:
592 request = (MainThreadRequest) msg.obj;
593 onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_DONE, request);
594 int subscriptionType = (Integer) request.argument;
595 mPhone.setCdmaSubscription(subscriptionType, onCompleted);
596 break;
597
598 case EVENT_SET_CDMA_SUBSCRIPTION_DONE:
599 handleNullReturnEvent(msg, "setCdmaSubscription");
600 break;
601
Steven Liu4bf01bc2014-07-17 11:05:29 -0500602 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
603 request = (MainThreadRequest)msg.obj;
604 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
605 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
606 break;
607
608 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
609 ar = (AsyncResult)msg.obj;
610 request = (MainThreadRequest)ar.userObj;
611 request.result = ar;
612 synchronized (request) {
613 request.notifyAll();
614 }
615 break;
616
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700617 default:
618 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
619 break;
620 }
621 }
Jake Hambye994d462014-02-03 13:10:13 -0800622
623 private void handleNullReturnEvent(Message msg, String command) {
624 AsyncResult ar = (AsyncResult) msg.obj;
625 MainThreadRequest request = (MainThreadRequest) ar.userObj;
626 if (ar.exception == null) {
627 request.result = true;
628 } else {
629 request.result = false;
630 if (ar.exception instanceof CommandException) {
631 loge(command + ": CommandException: " + ar.exception);
632 } else {
633 loge(command + ": Unknown exception");
634 }
635 }
636 synchronized (request) {
637 request.notifyAll();
638 }
639 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700640 }
641
642 /**
643 * Posts the specified command to be executed on the main thread,
644 * waits for the request to complete, and returns the result.
645 * @see #sendRequestAsync
646 */
647 private Object sendRequest(int command, Object argument) {
Santos Cordon500b0e02014-06-17 10:33:33 -0700648 return sendRequest(command, argument, null);
Wink Saville36469e72014-06-11 15:17:00 -0700649 }
650
651 /**
652 * Posts the specified command to be executed on the main thread,
653 * waits for the request to complete, and returns the result.
654 * @see #sendRequestAsync
655 */
656 private Object sendRequest(int command, Object argument, Object argument2) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700657 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
658 throw new RuntimeException("This method will deadlock if called from the main thread.");
659 }
660
661 MainThreadRequest request = new MainThreadRequest(argument);
662 Message msg = mMainThreadHandler.obtainMessage(command, request);
663 msg.sendToTarget();
664
665 // Wait for the request to complete
666 synchronized (request) {
667 while (request.result == null) {
668 try {
669 request.wait();
670 } catch (InterruptedException e) {
671 // Do nothing, go back and wait until the request is complete
672 }
673 }
674 }
675 return request.result;
676 }
677
678 /**
679 * Asynchronous ("fire and forget") version of sendRequest():
680 * Posts the specified command to be executed on the main thread, and
681 * returns immediately.
682 * @see #sendRequest
683 */
684 private void sendRequestAsync(int command) {
685 mMainThreadHandler.sendEmptyMessage(command);
686 }
687
688 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -0700689 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
690 * @see {@link #sendRequest(int,Object)}
691 */
692 private void sendRequestAsync(int command, Object argument) {
693 MainThreadRequest request = new MainThreadRequest(argument);
694 Message msg = mMainThreadHandler.obtainMessage(command, request);
695 msg.sendToTarget();
696 }
697
698 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700699 * Initialize the singleton PhoneInterfaceManager instance.
700 * This is only done once, at startup, from PhoneApp.onCreate().
701 */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700702 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700703 synchronized (PhoneInterfaceManager.class) {
704 if (sInstance == null) {
Sailesh Nepal194161e2014-07-03 08:57:44 -0700705 sInstance = new PhoneInterfaceManager(app, phone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700706 } else {
707 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
708 }
709 return sInstance;
710 }
711 }
712
713 /** Private constructor; @see init() */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700714 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700715 mApp = app;
716 mPhone = phone;
717 mCM = PhoneGlobals.getInstance().mCM;
Derek Tan89e89d42014-07-08 17:00:10 -0700718 mSimplifiedNetworkSettings = new HashSet<Long>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700719 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
720 mMainThreadHandler = new MainThreadHandler();
Derek Tan7226c842014-07-02 17:42:23 -0700721 mAdnRecordsForDisplay = new HashMap<Long, AdnRecord>();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700722 publish();
723 }
724
725 private void publish() {
726 if (DBG) log("publish: " + this);
727
728 ServiceManager.addService("phone", this);
729 }
730
Wink Saville36469e72014-06-11 15:17:00 -0700731 // returns phone associated with the subId.
732 // getPhone(0) returns default phone in single SIM mode.
733 private Phone getPhone(long subId) {
734 // FIXME: hack for the moment
735 return mPhone;
736 // return PhoneUtils.getPhoneUsingSubId(subId);
737 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700738 //
739 // Implementation of the ITelephony interface.
740 //
741
742 public void dial(String number) {
Wink Saville36469e72014-06-11 15:17:00 -0700743 dialUsingSubId(getPreferredVoiceSubscription(), number);
744 }
745
746 public void dialUsingSubId(long subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700747 if (DBG) log("dial: " + number);
748 // No permission check needed here: This is just a wrapper around the
749 // ACTION_DIAL intent, which is available to any app since it puts up
750 // the UI before it does anything.
751
752 String url = createTelUrl(number);
753 if (url == null) {
754 return;
755 }
756
757 // PENDING: should we just silently fail if phone is offhook or ringing?
Wink Saville36469e72014-06-11 15:17:00 -0700758 PhoneConstants.State state = mCM.getState(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700759 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
760 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
761 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
762 mApp.startActivity(intent);
763 }
764 }
765
766 public void call(String callingPackage, String number) {
Wink Saville36469e72014-06-11 15:17:00 -0700767 callUsingSubId(getPreferredVoiceSubscription(), callingPackage, number);
768 }
769
770 public void callUsingSubId(long subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700771 if (DBG) log("call: " + number);
772
773 // This is just a wrapper around the ACTION_CALL intent, but we still
774 // need to do a permission check since we're calling startActivity()
775 // from the context of the phone app.
776 enforceCallPermission();
777
778 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
779 != AppOpsManager.MODE_ALLOWED) {
780 return;
781 }
782
783 String url = createTelUrl(number);
784 if (url == null) {
785 return;
786 }
787
Wink Saville08874612014-08-31 19:19:58 -0700788 boolean isValid = false;
Wink Saville10aa2e92014-09-04 10:46:34 -0700789 List<SubInfoRecord> slist = SubscriptionManager.getActiveSubInfoList();
Wink Saville08874612014-08-31 19:19:58 -0700790 for (SubInfoRecord subInfoRecord : slist) {
Wink Savilleb30c9a22014-09-04 22:42:02 -0700791 if (subInfoRecord.subId == subId) {
Wink Saville08874612014-08-31 19:19:58 -0700792 isValid = true;
793 break;
794 }
795 }
796 if (isValid == false) {
797 return;
798 }
799
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700800 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
Wink Saville36469e72014-06-11 15:17:00 -0700801 intent.putExtra(SUBSCRIPTION_KEY, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700802 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
803 mApp.startActivity(intent);
804 }
805
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700806 /**
807 * End a call based on call state
808 * @return true is a call was ended
809 */
810 public boolean endCall() {
Wink Saville36469e72014-06-11 15:17:00 -0700811 return endCallUsingSubId(getDefaultSubscription());
812 }
813
814 /**
815 * End a call based on the call state of the subId
816 * @return true is a call was ended
817 */
818 public boolean endCallUsingSubId(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700819 enforceCallPermission();
Wink Saville08874612014-08-31 19:19:58 -0700820 return (Boolean) sendRequest(CMD_END_CALL, new Long(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700821 }
822
823 public void answerRingingCall() {
Wink Saville36469e72014-06-11 15:17:00 -0700824 answerRingingCallUsingSubId(getDefaultSubscription());
825 }
826
827 public void answerRingingCallUsingSubId(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700828 if (DBG) log("answerRingingCall...");
829 // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
830 // but that can probably wait till the big TelephonyManager API overhaul.
831 // For now, protect this call with the MODIFY_PHONE_STATE permission.
832 enforceModifyPermission();
Wink Saville08874612014-08-31 19:19:58 -0700833 sendRequest(CMD_ANSWER_RINGING_CALL, new Long(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700834 }
835
836 /**
837 * Make the actual telephony calls to implement answerRingingCall().
838 * This should only be called from the main thread of the Phone app.
839 * @see #answerRingingCall
840 *
841 * TODO: it would be nice to return true if we answered the call, or
842 * false if there wasn't actually a ringing incoming call, or some
843 * other error occurred. (In other words, pass back the return value
844 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
845 * But that would require calling this method via sendRequest() rather
846 * than sendRequestAsync(), and right now we don't actually *need* that
847 * return value, so let's just return void for now.
848 */
Wink Saville08874612014-08-31 19:19:58 -0700849 private void answerRingingCallInternal(long subId) {
850 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700851 if (hasRingingCall) {
Wink Saville08874612014-08-31 19:19:58 -0700852 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
853 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700854 if (hasActiveCall && hasHoldingCall) {
855 // Both lines are in use!
856 // TODO: provide a flag to let the caller specify what
857 // policy to use if both lines are in use. (The current
858 // behavior is hardwired to "answer incoming, end ongoing",
859 // which is how the CALL button is specced to behave.)
860 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
861 return;
862 } else {
863 // answerCall() will automatically hold the current active
864 // call, if there is one.
865 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
866 return;
867 }
868 } else {
869 // No call was ringing.
870 return;
871 }
872 }
873
874 public void silenceRinger() {
875 if (DBG) log("silenceRinger...");
876 // TODO: find a more appropriate permission to check here.
877 // (That can probably wait till the big TelephonyManager API overhaul.
878 // For now, protect this call with the MODIFY_PHONE_STATE permission.)
879 enforceModifyPermission();
880 sendRequestAsync(CMD_SILENCE_RINGER);
881 }
882
883 /**
884 * Internal implemenation of silenceRinger().
885 * This should only be called from the main thread of the Phone app.
886 * @see #silenceRinger
887 */
888 private void silenceRingerInternal() {
889 if ((mCM.getState() == PhoneConstants.State.RINGING)
890 && mApp.notifier.isRinging()) {
891 // Ringer is actually playing, so silence it.
892 if (DBG) log("silenceRingerInternal: silencing...");
893 mApp.notifier.silenceRinger();
894 }
895 }
896
897 public boolean isOffhook() {
Wink Saville36469e72014-06-11 15:17:00 -0700898 return isOffhookUsingSubId(getDefaultSubscription());
899 }
900
901 public boolean isOffhookUsingSubId(long subId) {
902 return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700903 }
904
905 public boolean isRinging() {
Wink Saville36469e72014-06-11 15:17:00 -0700906 return (isRingingUsingSubId(getDefaultSubscription()));
907 }
908
909 public boolean isRingingUsingSubId(long subId) {
910 return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700911 }
912
913 public boolean isIdle() {
Wink Saville36469e72014-06-11 15:17:00 -0700914 return isIdleUsingSubId(getDefaultSubscription());
915 }
916
917 public boolean isIdleUsingSubId(long subId) {
918 return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700919 }
920
921 public boolean isSimPinEnabled() {
922 enforceReadPermission();
923 return (PhoneGlobals.getInstance().isSimPinEnabled());
924 }
925
926 public boolean supplyPin(String pin) {
Wink Saville36469e72014-06-11 15:17:00 -0700927 return supplyPinUsingSubId(getDefaultSubscription(), pin);
928 }
929
930 public boolean supplyPinUsingSubId(long subId, String pin) {
931 int [] resultArray = supplyPinReportResultUsingSubId(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700932 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
933 }
934
935 public boolean supplyPuk(String puk, String pin) {
Wink Saville36469e72014-06-11 15:17:00 -0700936 return supplyPukUsingSubId(getDefaultSubscription(), puk, pin);
937 }
938
939 public boolean supplyPukUsingSubId(long subId, String puk, String pin) {
940 int [] resultArray = supplyPukReportResultUsingSubId(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700941 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
942 }
943
944 /** {@hide} */
945 public int[] supplyPinReportResult(String pin) {
Wink Saville36469e72014-06-11 15:17:00 -0700946 return supplyPinReportResultUsingSubId(getDefaultSubscription(), pin);
947 }
948
949 public int[] supplyPinReportResultUsingSubId(long subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700950 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700951 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700952 checkSimPin.start();
953 return checkSimPin.unlockSim(null, pin);
954 }
955
Wink Saville9de0f752013-10-22 19:04:03 -0700956 /** {@hide} */
957 public int[] supplyPukReportResult(String puk, String pin) {
Wink Saville36469e72014-06-11 15:17:00 -0700958 return supplyPukReportResultUsingSubId(getDefaultSubscription(), puk, pin);
959 }
960
961 public int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700962 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700963 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700964 checkSimPuk.start();
965 return checkSimPuk.unlockSim(puk, pin);
966 }
967
968 /**
Wink Saville9de0f752013-10-22 19:04:03 -0700969 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700970 * a synchronous one.
971 */
972 private static class UnlockSim extends Thread {
973
974 private final IccCard mSimCard;
975
976 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -0700977 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
978 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700979
980 // For replies from SimCard interface
981 private Handler mHandler;
982
983 // For async handler to identify request type
984 private static final int SUPPLY_PIN_COMPLETE = 100;
985
986 public UnlockSim(IccCard simCard) {
987 mSimCard = simCard;
988 }
989
990 @Override
991 public void run() {
992 Looper.prepare();
993 synchronized (UnlockSim.this) {
994 mHandler = new Handler() {
995 @Override
996 public void handleMessage(Message msg) {
997 AsyncResult ar = (AsyncResult) msg.obj;
998 switch (msg.what) {
999 case SUPPLY_PIN_COMPLETE:
1000 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
1001 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -07001002 mRetryCount = msg.arg1;
1003 if (ar.exception != null) {
1004 if (ar.exception instanceof CommandException &&
1005 ((CommandException)(ar.exception)).getCommandError()
1006 == CommandException.Error.PASSWORD_INCORRECT) {
1007 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1008 } else {
1009 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1010 }
1011 } else {
1012 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1013 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001014 mDone = true;
1015 UnlockSim.this.notifyAll();
1016 }
1017 break;
1018 }
1019 }
1020 };
1021 UnlockSim.this.notifyAll();
1022 }
1023 Looper.loop();
1024 }
1025
1026 /*
1027 * Use PIN or PUK to unlock SIM card
1028 *
1029 * If PUK is null, unlock SIM card with PIN
1030 *
1031 * If PUK is not null, unlock SIM card with PUK and set PIN code
1032 */
Wink Saville9de0f752013-10-22 19:04:03 -07001033 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001034
1035 while (mHandler == null) {
1036 try {
1037 wait();
1038 } catch (InterruptedException e) {
1039 Thread.currentThread().interrupt();
1040 }
1041 }
1042 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1043
1044 if (puk == null) {
1045 mSimCard.supplyPin(pin, callback);
1046 } else {
1047 mSimCard.supplyPuk(puk, pin, callback);
1048 }
1049
1050 while (!mDone) {
1051 try {
1052 Log.d(LOG_TAG, "wait for done");
1053 wait();
1054 } catch (InterruptedException e) {
1055 // Restore the interrupted status
1056 Thread.currentThread().interrupt();
1057 }
1058 }
1059 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001060 int[] resultArray = new int[2];
1061 resultArray[0] = mResult;
1062 resultArray[1] = mRetryCount;
1063 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001064 }
1065 }
1066
1067 public void updateServiceLocation() {
Wink Saville36469e72014-06-11 15:17:00 -07001068 updateServiceLocationUsingSubId(getDefaultSubscription());
1069
1070 }
1071
1072 public void updateServiceLocationUsingSubId(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001073 // No permission check needed here: this call is harmless, and it's
1074 // needed for the ServiceState.requestStateUpdate() call (which is
1075 // already intentionally exposed to 3rd parties.)
Wink Saville36469e72014-06-11 15:17:00 -07001076 getPhone(subId).updateServiceLocation();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001077 }
1078
1079 public boolean isRadioOn() {
Wink Saville36469e72014-06-11 15:17:00 -07001080 return isRadioOnUsingSubId(getDefaultSubscription());
1081 }
1082
1083 public boolean isRadioOnUsingSubId(long subId) {
1084 return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001085 }
1086
1087 public void toggleRadioOnOff() {
Wink Saville36469e72014-06-11 15:17:00 -07001088 toggleRadioOnOffUsingSubId(getDefaultSubscription());
1089
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001090 }
Wink Saville36469e72014-06-11 15:17:00 -07001091
1092 public void toggleRadioOnOffUsingSubId(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001093 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001094 getPhone(subId).setRadioPower(!isRadioOnUsingSubId(subId));
1095 }
1096
1097 public boolean setRadio(boolean turnOn) {
1098 return setRadioUsingSubId(getDefaultSubscription(), turnOn);
1099 }
1100
1101 public boolean setRadioUsingSubId(long subId, boolean turnOn) {
1102 enforceModifyPermission();
1103 if ((getPhone(subId).getServiceState().getState() !=
1104 ServiceState.STATE_POWER_OFF) != turnOn) {
1105 toggleRadioOnOffUsingSubId(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001106 }
1107 return true;
1108 }
Wink Saville36469e72014-06-11 15:17:00 -07001109
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001110 public boolean needMobileRadioShutdown() {
1111 /*
1112 * If any of the Radios are available, it will need to be
1113 * shutdown. So return true if any Radio is available.
1114 */
1115 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1116 Phone phone = PhoneFactory.getPhone(i);
1117 if (phone != null && phone.isRadioAvailable()) return true;
1118 }
1119 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1120 return false;
1121 }
1122
1123 public void shutdownMobileRadios() {
1124 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1125 logv("Shutting down Phone " + i);
1126 shutdownRadioUsingPhoneId(i);
1127 }
1128 }
1129
1130 private void shutdownRadioUsingPhoneId(int phoneId) {
1131 enforceModifyPermission();
1132 Phone phone = PhoneFactory.getPhone(phoneId);
1133 if (phone != null && phone.isRadioAvailable()) {
1134 phone.shutdownRadio();
1135 }
1136 }
1137
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001138 public boolean setRadioPower(boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001139 return setRadioPowerUsingSubId(getDefaultSubscription(), turnOn);
1140 }
1141
1142 public boolean setRadioPowerUsingSubId(long subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001143 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001144 getPhone(subId).setRadioPower(turnOn);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001145 return true;
1146 }
1147
Wink Saville36469e72014-06-11 15:17:00 -07001148 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001149 public boolean enableDataConnectivity() {
1150 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001151 long subId = SubscriptionManager.getDefaultDataSubId();
1152 getPhone(subId).setDataEnabled(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001153 return true;
1154 }
1155
Wink Saville36469e72014-06-11 15:17:00 -07001156 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001157 public boolean disableDataConnectivity() {
1158 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001159 long subId = SubscriptionManager.getDefaultDataSubId();
1160 getPhone(subId).setDataEnabled(false);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001161 return true;
1162 }
1163
Wink Saville36469e72014-06-11 15:17:00 -07001164 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001165 public boolean isDataConnectivityPossible() {
Wink Saville36469e72014-06-11 15:17:00 -07001166 long subId = SubscriptionManager.getDefaultDataSubId();
1167 return getPhone(subId).isDataConnectivityPossible();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001168 }
1169
1170 public boolean handlePinMmi(String dialString) {
Wink Saville36469e72014-06-11 15:17:00 -07001171 return handlePinMmiUsingSubId(getDefaultSubscription(), dialString);
1172 }
1173
1174 public boolean handlePinMmiUsingSubId(long subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001175 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001176 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001177 }
1178
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001179 public int getCallState() {
Wink Saville36469e72014-06-11 15:17:00 -07001180 return getCallStateUsingSubId(getDefaultSubscription());
1181 }
1182
1183 public int getCallStateUsingSubId(long subId) {
1184 return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001185 }
1186
1187 public int getDataState() {
Wink Saville36469e72014-06-11 15:17:00 -07001188 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1189 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001190 }
1191
1192 public int getDataActivity() {
Wink Saville36469e72014-06-11 15:17:00 -07001193 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1194 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001195 }
1196
1197 @Override
1198 public Bundle getCellLocation() {
1199 try {
1200 mApp.enforceCallingOrSelfPermission(
1201 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1202 } catch (SecurityException e) {
1203 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1204 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1205 // is the weaker precondition
1206 mApp.enforceCallingOrSelfPermission(
1207 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1208 }
1209
Jake Hambye994d462014-02-03 13:10:13 -08001210 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001211 if (DBG_LOC) log("getCellLocation: is active user");
1212 Bundle data = new Bundle();
1213 mPhone.getCellLocation().fillInNotifierBundle(data);
1214 return data;
1215 } else {
1216 if (DBG_LOC) log("getCellLocation: suppress non-active user");
1217 return null;
1218 }
1219 }
1220
1221 @Override
1222 public void enableLocationUpdates() {
Wink Saville36469e72014-06-11 15:17:00 -07001223 enableLocationUpdatesUsingSubId(getDefaultSubscription());
1224 }
1225
1226 public void enableLocationUpdatesUsingSubId(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001227 mApp.enforceCallingOrSelfPermission(
1228 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001229 getPhone(subId).enableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001230 }
1231
1232 @Override
1233 public void disableLocationUpdates() {
Wink Saville36469e72014-06-11 15:17:00 -07001234 disableLocationUpdatesUsingSubId(getDefaultSubscription());
1235 }
1236
1237 public void disableLocationUpdatesUsingSubId(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001238 mApp.enforceCallingOrSelfPermission(
1239 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001240 getPhone(subId).disableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001241 }
1242
1243 @Override
1244 @SuppressWarnings("unchecked")
1245 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1246 try {
1247 mApp.enforceCallingOrSelfPermission(
1248 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1249 } catch (SecurityException e) {
1250 // If we have ACCESS_FINE_LOCATION permission, skip the check
1251 // for ACCESS_COARSE_LOCATION
1252 // A failure should throw the SecurityException from
1253 // ACCESS_COARSE_LOCATION since this is the weaker precondition
1254 mApp.enforceCallingOrSelfPermission(
1255 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1256 }
1257
1258 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1259 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1260 return null;
1261 }
Jake Hambye994d462014-02-03 13:10:13 -08001262 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001263 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1264
1265 ArrayList<NeighboringCellInfo> cells = null;
1266
1267 try {
1268 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
Wink Saville36469e72014-06-11 15:17:00 -07001269 CMD_HANDLE_NEIGHBORING_CELL, null, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001270 } catch (RuntimeException e) {
Wink Saville36469e72014-06-11 15:17:00 -07001271 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001272 }
1273 return cells;
1274 } else {
1275 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1276 return null;
1277 }
1278 }
1279
1280
1281 @Override
1282 public List<CellInfo> getAllCellInfo() {
1283 try {
1284 mApp.enforceCallingOrSelfPermission(
1285 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1286 } catch (SecurityException e) {
1287 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1288 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1289 // is the weaker precondition
1290 mApp.enforceCallingOrSelfPermission(
1291 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1292 }
1293
Jake Hambye994d462014-02-03 13:10:13 -08001294 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001295 if (DBG_LOC) log("getAllCellInfo: is active user");
1296 return mPhone.getAllCellInfo();
1297 } else {
1298 if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1299 return null;
1300 }
1301 }
1302
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001303 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001304 public void setCellInfoListRate(int rateInMillis) {
1305 mPhone.setCellInfoListRate(rateInMillis);
1306 }
1307
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001308 //
1309 // Internal helper methods.
1310 //
1311
Jake Hambye994d462014-02-03 13:10:13 -08001312 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001313 boolean ok;
1314
1315 boolean self = Binder.getCallingUid() == Process.myUid();
1316 if (!self) {
1317 // Get the caller's user id then clear the calling identity
1318 // which will be restored in the finally clause.
1319 int callingUser = UserHandle.getCallingUserId();
1320 long ident = Binder.clearCallingIdentity();
1321
1322 try {
1323 // With calling identity cleared the current user is the foreground user.
1324 int foregroundUser = ActivityManager.getCurrentUser();
1325 ok = (foregroundUser == callingUser);
1326 if (DBG_LOC) {
1327 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1328 + " callingUser=" + callingUser + " ok=" + ok);
1329 }
1330 } catch (Exception ex) {
1331 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1332 ok = false;
1333 } finally {
1334 Binder.restoreCallingIdentity(ident);
1335 }
1336 } else {
1337 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1338 ok = true;
1339 }
1340 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1341 return ok;
1342 }
1343
1344 /**
1345 * Make sure the caller has the READ_PHONE_STATE permission.
1346 *
1347 * @throws SecurityException if the caller does not have the required permission
1348 */
1349 private void enforceReadPermission() {
1350 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
1351 }
1352
1353 /**
1354 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1355 *
1356 * @throws SecurityException if the caller does not have the required permission
1357 */
1358 private void enforceModifyPermission() {
1359 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1360 }
1361
1362 /**
Junda Liua2e36012014-07-09 18:30:01 -07001363 * Make sure either system app or the caller has carrier privilege.
1364 *
1365 * @throws SecurityException if the caller does not have the required permission/privilege
1366 */
1367 private void enforceModifyPermissionOrCarrierPrivilege() {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001368 int permission = mApp.checkCallingOrSelfPermission(
1369 android.Manifest.permission.MODIFY_PHONE_STATE);
1370 if (permission == PackageManager.PERMISSION_GRANTED) {
1371 return;
1372 }
1373
1374 log("No modify permission, check carrier privilege next.");
1375 if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1376 loge("No Carrier Privilege.");
1377 throw new SecurityException("No modify permission or carrier privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001378 }
1379 }
1380
1381 /**
1382 * Make sure the caller has carrier privilege.
1383 *
1384 * @throws SecurityException if the caller does not have the required permission
1385 */
1386 private void enforceCarrierPrivilege() {
1387 if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001388 loge("No Carrier Privilege.");
1389 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001390 }
1391 }
1392
1393 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001394 * Make sure the caller has the CALL_PHONE permission.
1395 *
1396 * @throws SecurityException if the caller does not have the required permission
1397 */
1398 private void enforceCallPermission() {
1399 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1400 }
1401
Shishir Agrawal566b7612013-10-28 14:41:00 -07001402 /**
Gabriel Peal36ebb0d2014-03-20 09:20:43 -07001403 * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
1404 *
1405 * @throws SecurityException if the caller does not have the required permission
1406 */
1407 private void enforcePrivilegedPhoneStatePermission() {
1408 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1409 null);
1410 }
1411
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001412 private String createTelUrl(String number) {
1413 if (TextUtils.isEmpty(number)) {
1414 return null;
1415 }
1416
Jake Hambye994d462014-02-03 13:10:13 -08001417 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001418 }
1419
Ihab Awadf9e92732013-12-05 18:02:52 -08001420 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001421 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1422 }
1423
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001424 private static void logv(String msg) {
1425 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1426 }
1427
Ihab Awadf9e92732013-12-05 18:02:52 -08001428 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001429 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1430 }
1431
1432 public int getActivePhoneType() {
Wink Saville36469e72014-06-11 15:17:00 -07001433 return getActivePhoneTypeUsingSubId(getDefaultSubscription());
1434 }
1435
1436 public int getActivePhoneTypeUsingSubId(long subId) {
1437 return getPhone(subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001438 }
1439
1440 /**
1441 * Returns the CDMA ERI icon index to display
1442 */
1443 public int getCdmaEriIconIndex() {
Wink Saville36469e72014-06-11 15:17:00 -07001444 return getCdmaEriIconIndexUsingSubId(getDefaultSubscription());
1445
1446 }
1447
1448 public int getCdmaEriIconIndexUsingSubId(long subId) {
1449 return getPhone(subId).getCdmaEriIconIndex();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001450 }
1451
1452 /**
1453 * Returns the CDMA ERI icon mode,
1454 * 0 - ON
1455 * 1 - FLASHING
1456 */
1457 public int getCdmaEriIconMode() {
Wink Saville36469e72014-06-11 15:17:00 -07001458 return getCdmaEriIconModeUsingSubId(getDefaultSubscription());
1459 }
1460
1461 public int getCdmaEriIconModeUsingSubId(long subId) {
1462 return getPhone(subId).getCdmaEriIconMode();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001463 }
1464
1465 /**
1466 * Returns the CDMA ERI text,
1467 */
1468 public String getCdmaEriText() {
Wink Saville36469e72014-06-11 15:17:00 -07001469 return getCdmaEriTextUsingSubId(getDefaultSubscription());
1470 }
1471
1472 public String getCdmaEriTextUsingSubId(long subId) {
1473 return getPhone(subId).getCdmaEriText();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001474 }
1475
1476 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001477 * Returns the CDMA MDN.
1478 */
1479 public String getCdmaMdn(long subId) {
1480 enforceModifyPermissionOrCarrierPrivilege();
1481 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1482 return getPhone(subId).getLine1Number();
1483 } else {
1484 return null;
1485 }
1486 }
1487
1488 /**
1489 * Returns the CDMA MIN.
1490 */
1491 public String getCdmaMin(long subId) {
1492 enforceModifyPermissionOrCarrierPrivilege();
1493 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1494 return getPhone(subId).getCdmaMin();
1495 } else {
1496 return null;
1497 }
1498 }
1499
1500 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001501 * Returns true if CDMA provisioning needs to run.
1502 */
1503 public boolean needsOtaServiceProvisioning() {
1504 return mPhone.needsOtaServiceProvisioning();
1505 }
1506
1507 /**
1508 * Returns the unread count of voicemails
1509 */
1510 public int getVoiceMessageCount() {
Wink Saville36469e72014-06-11 15:17:00 -07001511 return getVoiceMessageCountUsingSubId(getDefaultSubscription());
1512 }
1513
1514 /**
1515 * Returns the unread count of voicemails for a subId
1516 */
1517 public int getVoiceMessageCountUsingSubId( long subId) {
1518 return getPhone(subId).getVoiceMessageCount();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001519 }
1520
1521 /**
1522 * Returns the data network type
1523 *
1524 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
1525 */
1526 @Override
1527 public int getNetworkType() {
Wink Saville36469e72014-06-11 15:17:00 -07001528 return getNetworkTypeUsingSubId(getDefaultSubscription());
1529 }
1530
1531 /**
1532 * Returns the network type for a subId
1533 */
1534 @Override
1535 public int getNetworkTypeUsingSubId(long subId) {
1536 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001537 }
1538
1539 /**
1540 * Returns the data network type
1541 */
1542 @Override
1543 public int getDataNetworkType() {
Wink Saville36469e72014-06-11 15:17:00 -07001544 return getDataNetworkTypeUsingSubId(getDefaultSubscription());
1545 }
1546
1547 /**
1548 * Returns the data network type for a subId
1549 */
1550 @Override
1551 public int getDataNetworkTypeUsingSubId(long subId) {
1552 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001553 }
1554
1555 /**
1556 * Returns the data network type
1557 */
1558 @Override
1559 public int getVoiceNetworkType() {
Wink Saville36469e72014-06-11 15:17:00 -07001560 return getVoiceNetworkTypeUsingSubId(getDefaultSubscription());
1561 }
1562
1563 /**
1564 * Returns the Voice network type for a subId
1565 */
1566 @Override
1567 public int getVoiceNetworkTypeUsingSubId(long subId) {
1568 return getPhone(subId).getServiceState().getVoiceNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001569 }
1570
1571 /**
1572 * @return true if a ICC card is present
1573 */
1574 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07001575 // FIXME Make changes to pass defaultSimId of type int
1576 return hasIccCardUsingSlotId(getDefaultSubscription());
1577 }
1578
1579 /**
1580 * @return true if a ICC card is present for a slotId
1581 */
1582 public boolean hasIccCardUsingSlotId(long slotId) {
1583 return getPhone(slotId).getIccCard().hasIccCard();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001584 }
1585
1586 /**
1587 * Return if the current radio is LTE on CDMA. This
1588 * is a tri-state return value as for a period of time
1589 * the mode may be unknown.
1590 *
1591 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08001592 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001593 */
1594 public int getLteOnCdmaMode() {
Wink Saville36469e72014-06-11 15:17:00 -07001595 return getLteOnCdmaModeUsingSubId(getDefaultSubscription());
1596 }
1597
1598 public int getLteOnCdmaModeUsingSubId(long subId) {
1599 return getPhone(subId).getLteOnCdmaMode();
1600 }
1601
1602 public void setPhone(Phone phone) {
1603 mPhone = phone;
1604 }
1605
1606 /**
1607 * {@hide}
1608 * Returns Default subId, 0 in the case of single standby.
1609 */
1610 private long getDefaultSubscription() {
1611 return SubscriptionManager.getDefaultSubId();
1612 }
1613
1614 private long getPreferredVoiceSubscription() {
1615 return SubscriptionManager.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001616 }
Ihab Awadf2177b72013-11-25 13:33:23 -08001617
1618 /**
1619 * @see android.telephony.TelephonyManager.WifiCallingChoices
1620 */
1621 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001622 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1623 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08001624 }
1625
1626 /**
1627 * @see android.telephony.TelephonyManager.WifiCallingChoices
1628 */
1629 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001630 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1631 Settings.System.putInt(mPhone.getContext().getContentResolver(),
1632 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08001633 }
1634
Sailesh Nepald1e68152013-12-12 19:08:02 -08001635 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07001636 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08001637 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08001638 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08001639
Shishir Agrawal566b7612013-10-28 14:41:00 -07001640 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001641 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
Junda Liua2e36012014-07-09 18:30:01 -07001642 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001643
1644 if (DBG) log("iccOpenLogicalChannel: " + AID);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001645 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1646 CMD_OPEN_CHANNEL, AID);
1647 if (DBG) log("iccOpenLogicalChannel: " + response);
1648 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07001649 }
1650
1651 @Override
1652 public boolean iccCloseLogicalChannel(int channel) {
Junda Liua2e36012014-07-09 18:30:01 -07001653 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001654
1655 if (DBG) log("iccCloseLogicalChannel: " + channel);
1656 if (channel < 0) {
1657 return false;
1658 }
Jake Hambye994d462014-02-03 13:10:13 -08001659 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001660 if (DBG) log("iccCloseLogicalChannel: " + success);
1661 return success;
1662 }
1663
1664 @Override
1665 public String iccTransmitApduLogicalChannel(int channel, int cla,
1666 int command, int p1, int p2, int p3, String data) {
Junda Liua2e36012014-07-09 18:30:01 -07001667 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001668
1669 if (DBG) {
1670 log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1671 " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1672 " data=" + data);
1673 }
1674
1675 if (channel < 0) {
1676 return "";
1677 }
1678
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001679 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawal566b7612013-10-28 14:41:00 -07001680 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1681 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1682
Shishir Agrawal566b7612013-10-28 14:41:00 -07001683 // Append the returned status code to the end of the response payload.
1684 String s = Integer.toHexString(
1685 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001686 if (response.payload != null) {
1687 s = IccUtils.bytesToHexString(response.payload) + s;
1688 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001689 return s;
1690 }
Jake Hambye994d462014-02-03 13:10:13 -08001691
Evan Charltonc66da362014-05-16 14:06:40 -07001692 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001693 public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1694 int p3, String data) {
1695 enforceModifyPermissionOrCarrierPrivilege();
1696
1697 if (DBG) {
1698 log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1699 + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1700 }
1701
1702 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1703 new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1704 if (DBG) log("iccTransmitApduBasicChannel: " + response);
1705
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001706 // Append the returned status code to the end of the response payload.
1707 String s = Integer.toHexString(
1708 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001709 if (response.payload != null) {
1710 s = IccUtils.bytesToHexString(response.payload) + s;
1711 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001712 return s;
1713 }
1714
1715 @Override
1716 public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1717 String filePath) {
1718 enforceModifyPermissionOrCarrierPrivilege();
1719
1720 if (DBG) {
1721 log("Exchange SIM_IO " + fileID + ":" + command + " " +
1722 p1 + " " + p2 + " " + p3 + ":" + filePath);
1723 }
1724
1725 IccIoResult response =
1726 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
1727 new IccAPDUArgument(fileID, command, -1, p1, p2, p3, filePath));
1728
1729 if (DBG) {
1730 log("Exchange SIM_IO [R]" + response);
1731 }
1732
1733 byte[] result = null;
1734 int length = 2;
1735 if (response.payload != null) {
1736 length = 2 + response.payload.length;
1737 result = new byte[length];
1738 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1739 } else {
1740 result = new byte[length];
1741 }
1742
1743 result[length - 1] = (byte) response.sw2;
1744 result[length - 2] = (byte) response.sw1;
1745 return result;
1746 }
1747
1748 @Override
Evan Charltonc66da362014-05-16 14:06:40 -07001749 public String sendEnvelopeWithStatus(String content) {
Junda Liua2e36012014-07-09 18:30:01 -07001750 enforceModifyPermissionOrCarrierPrivilege();
Evan Charltonc66da362014-05-16 14:06:40 -07001751
1752 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1753 if (response.payload == null) {
1754 return "";
1755 }
1756
1757 // Append the returned status code to the end of the response payload.
1758 String s = Integer.toHexString(
1759 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1760 s = IccUtils.bytesToHexString(response.payload) + s;
1761 return s;
1762 }
1763
Jake Hambye994d462014-02-03 13:10:13 -08001764 /**
1765 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1766 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1767 *
1768 * @param itemID the ID of the item to read
1769 * @return the NV item as a String, or null on error.
1770 */
1771 @Override
1772 public String nvReadItem(int itemID) {
Junda Liua2e36012014-07-09 18:30:01 -07001773 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001774 if (DBG) log("nvReadItem: item " + itemID);
1775 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1776 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1777 return value;
1778 }
1779
1780 /**
1781 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1782 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1783 *
1784 * @param itemID the ID of the item to read
1785 * @param itemValue the value to write, as a String
1786 * @return true on success; false on any failure
1787 */
1788 @Override
1789 public boolean nvWriteItem(int itemID, String itemValue) {
Junda Liua2e36012014-07-09 18:30:01 -07001790 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001791 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1792 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1793 new Pair<Integer, String>(itemID, itemValue));
1794 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1795 return success;
1796 }
1797
1798 /**
1799 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1800 * Used for device configuration by some CDMA operators.
1801 *
1802 * @param preferredRoamingList byte array containing the new PRL
1803 * @return true on success; false on any failure
1804 */
1805 @Override
1806 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Junda Liua2e36012014-07-09 18:30:01 -07001807 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001808 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1809 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1810 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1811 return success;
1812 }
1813
1814 /**
1815 * Perform the specified type of NV config reset.
1816 * Used for device configuration by some CDMA operators.
1817 *
1818 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1819 * @return true on success; false on any failure
1820 */
1821 @Override
1822 public boolean nvResetConfig(int resetType) {
Junda Liua2e36012014-07-09 18:30:01 -07001823 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001824 if (DBG) log("nvResetConfig: type " + resetType);
1825 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1826 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1827 return success;
1828 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001829
1830 /**
Wink Saville36469e72014-06-11 15:17:00 -07001831 * {@hide}
1832 * Returns Default sim, 0 in the case of single standby.
1833 */
1834 public int getDefaultSim() {
1835 //TODO Need to get it from Telephony Devcontroller
1836 return 0;
1837 }
1838
ram87fca6f2014-07-18 18:58:44 +05301839 public String[] getPcscfAddress(String apnType) {
Wink Saville36469e72014-06-11 15:17:00 -07001840 enforceReadPermission();
ram87fca6f2014-07-18 18:58:44 +05301841 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07001842 }
1843
1844 public void setImsRegistrationState(boolean registered) {
1845 enforceModifyPermission();
1846 mPhone.setImsRegistrationState(registered);
1847 }
1848
1849 /**
Junda Liu84d15a22014-07-02 11:21:04 -07001850 * Get the calculated preferred network type.
1851 * Used for debugging incorrect network type.
1852 *
1853 * @return the preferred network type, defined in RILConstants.java.
1854 */
1855 @Override
1856 public int getCalculatedPreferredNetworkType() {
1857 enforceReadPermission();
Wink Saville08874612014-08-31 19:19:58 -07001858 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get PhoneId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07001859 }
1860
1861 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08001862 * Get the preferred network type.
1863 * Used for device configuration by some CDMA operators.
1864 *
1865 * @return the preferred network type, defined in RILConstants.java.
1866 */
1867 @Override
1868 public int getPreferredNetworkType() {
Junda Liua2e36012014-07-09 18:30:01 -07001869 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001870 if (DBG) log("getPreferredNetworkType");
1871 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
1872 int networkType = (result != null ? result[0] : -1);
1873 if (DBG) log("getPreferredNetworkType: " + networkType);
1874 return networkType;
1875 }
1876
1877 /**
1878 * Set the preferred network type.
1879 * Used for device configuration by some CDMA operators.
1880 *
1881 * @param networkType the preferred network type, defined in RILConstants.java.
1882 * @return true on success; false on any failure.
1883 */
1884 @Override
1885 public boolean setPreferredNetworkType(int networkType) {
Junda Liua2e36012014-07-09 18:30:01 -07001886 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001887 if (DBG) log("setPreferredNetworkType: type " + networkType);
1888 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
1889 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07001890 if (success) {
1891 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
1892 Settings.Global.PREFERRED_NETWORK_MODE, networkType);
1893 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001894 return success;
1895 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001896
1897 /**
Junda Liu787bc7e2014-06-30 13:38:02 -07001898 * Set the CDMA subscription source.
1899 * Used for device supporting both NV and RUIM for CDMA.
1900 *
1901 * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
1902 * @return true on success; false on any failure.
1903 */
1904 @Override
1905 public boolean setCdmaSubscription(int subscriptionType) {
Junda Liua2e36012014-07-09 18:30:01 -07001906 enforceModifyPermissionOrCarrierPrivilege();
Junda Liu787bc7e2014-06-30 13:38:02 -07001907 if (DBG) log("setCdmaSubscription: type " + subscriptionType);
1908 if (subscriptionType != mPhone.CDMA_SUBSCRIPTION_RUIM_SIM &&
1909 subscriptionType != mPhone.CDMA_SUBSCRIPTION_NV) {
1910 loge("setCdmaSubscription: unsupported subscriptionType.");
1911 return false;
1912 }
1913 Boolean success = (Boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION, subscriptionType);
1914 if (DBG) log("setCdmaSubscription: " + (success ? "ok" : "fail"));
1915 if (success) {
1916 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
1917 Settings.Global.CDMA_SUBSCRIPTION_MODE, subscriptionType);
1918 }
1919 return success;
1920 }
1921
1922 /**
Robert Greenwalted86e582014-05-21 20:03:20 -07001923 * Set mobile data enabled
1924 * Used by the user through settings etc to turn on/off mobile data
1925 *
1926 * @param enable {@code true} turn turn data on, else {@code false}
1927 */
1928 @Override
1929 public void setDataEnabled(boolean enable) {
1930 enforceModifyPermission();
1931 mPhone.setDataEnabled(enable);
1932 }
1933
1934 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07001935 * Get whether mobile data is enabled.
1936 *
1937 * Note that this used to be available from ConnectivityService, gated by
1938 * ACCESS_NETWORK_STATE permission, so this will accept either that or
1939 * our MODIFY_PHONE_STATE.
Robert Greenwalted86e582014-05-21 20:03:20 -07001940 *
1941 * @return {@code true} if data is enabled else {@code false}
1942 */
1943 @Override
1944 public boolean getDataEnabled() {
Robert Greenwalt646120a2014-05-23 11:54:03 -07001945 try {
1946 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1947 null);
1948 } catch (Exception e) {
1949 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1950 null);
1951 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001952 return mPhone.getDataEnabled();
1953 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001954
1955 @Override
1956 public int hasCarrierPrivileges() {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001957 UiccCard card = UiccController.getInstance().getUiccCard();
1958 if (card == null) {
1959 loge("hasCarrierPrivileges: No UICC");
1960 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1961 }
1962 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001963 mPhone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001964 }
Junda Liu29340342014-07-10 15:23:27 -07001965
1966 @Override
Shishir Agrawal6d5a2852014-07-11 16:32:57 -07001967 public int checkCarrierPrivilegesForPackage(String pkgname) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001968 UiccCard card = UiccController.getInstance().getUiccCard();
1969 if (card == null) {
1970 loge("checkCarrierPrivilegesForPackage: No UICC");
1971 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1972 }
1973 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
Junda Liu29340342014-07-10 15:23:27 -07001974 }
Derek Tan89e89d42014-07-08 17:00:10 -07001975
1976 @Override
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001977 public List<String> getCarrierPackageNamesForIntent(Intent intent) {
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001978 UiccCard card = UiccController.getInstance().getUiccCard();
1979 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001980 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001981 return null ;
1982 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001983 return card.getCarrierPackageNamesForIntent(
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001984 mPhone.getContext().getPackageManager(), intent);
1985 }
1986
1987 @Override
Derek Tan89e89d42014-07-08 17:00:10 -07001988 public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
Derek Tan352d8cd2014-07-12 12:57:11 -07001989 enforceModifyPermissionOrCarrierPrivilege();
Derek Tan89e89d42014-07-08 17:00:10 -07001990 if (enable) {
1991 mSimplifiedNetworkSettings.add(subId);
1992 } else {
1993 mSimplifiedNetworkSettings.remove(subId);
1994 }
1995 }
1996
1997 @Override
1998 public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
1999 enforceReadPermission();
2000 return mSimplifiedNetworkSettings.contains(subId);
2001 }
Derek Tan7226c842014-07-02 17:42:23 -07002002
2003 @Override
2004 public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
Derek Tan352d8cd2014-07-12 12:57:11 -07002005 enforceModifyPermissionOrCarrierPrivilege();
Derek Tan7226c842014-07-02 17:42:23 -07002006 mAdnRecordsForDisplay.put(subId, new AdnRecord(alphaTag, number));
2007 }
2008
2009 @Override
2010 public String getLine1NumberForDisplay(long subId) {
2011 enforceReadPermission();
2012 if (!mAdnRecordsForDisplay.containsKey(subId)) {
2013 return null;
2014 }
2015 AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
2016 if (adnRecord.getNumber() == null || adnRecord.getNumber().isEmpty()) {
2017 return null;
2018 }
2019 return adnRecord.getNumber();
2020 }
2021
2022 @Override
2023 public String getLine1AlphaTagForDisplay(long subId) {
2024 enforceReadPermission();
2025 if (!mAdnRecordsForDisplay.containsKey(subId)) {
2026 return null;
2027 }
2028 AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
2029 if (adnRecord.getAlphaTag() == null || adnRecord.getAlphaTag().isEmpty()) {
2030 return null;
2031 }
2032 return adnRecord.getAlphaTag();
2033 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002034
2035 @Override
2036 public boolean setOperatorBrandOverride(String iccId, String brand) {
2037 enforceModifyPermissionOrCarrierPrivilege();
2038 return mPhone.setOperatorBrandOverride(iccId, brand);
2039 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002040
2041 @Override
2042 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2043 enforceModifyPermission();
2044
2045 int returnValue = 0;
2046 try {
2047 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2048 if(result.exception == null) {
2049 if (result.result != null) {
2050 byte[] responseData = (byte[])(result.result);
2051 if(responseData.length > oemResp.length) {
2052 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2053 responseData.length + "bytes. Buffer Size is " +
2054 oemResp.length + "bytes.");
2055 }
2056 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2057 returnValue = responseData.length;
2058 }
2059 } else {
2060 CommandException ex = (CommandException) result.exception;
2061 returnValue = ex.getCommandError().ordinal();
2062 if(returnValue > 0) returnValue *= -1;
2063 }
2064 } catch (RuntimeException e) {
2065 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2066 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2067 if(returnValue > 0) returnValue *= -1;
2068 }
2069
2070 return returnValue;
2071 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002072}