blob: ffbdebf2b26d9dd4dd781a3312d05bcfffb8c469 [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;
Derek Tan97ebb422014-09-05 16:55:38 -070024import android.content.SharedPreferences;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070025import android.content.pm.PackageInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.Signature;
Wink Saville36469e72014-06-11 15:17:00 -070028import android.net.ConnectivityManager;
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;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070034import android.os.IBinder;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070035import android.os.Looper;
36import android.os.Message;
37import android.os.Process;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070038import android.os.RemoteException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070039import android.os.ServiceManager;
Wink Saville08874612014-08-31 19:19:58 -070040import android.os.SystemProperties;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070041import android.os.UserHandle;
Derek Tan97ebb422014-09-05 16:55:38 -070042import android.preference.PreferenceManager;
Ihab Awadf2177b72013-11-25 13:33:23 -080043import android.provider.Settings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070044import android.telephony.CellInfo;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070045import android.telephony.IccOpenLogicalChannelResponse;
Jake Hambye994d462014-02-03 13:10:13 -080046import android.telephony.NeighboringCellInfo;
Wink Saville5d475dd2014-10-17 15:00:58 -070047import android.telephony.RadioAccessFamily;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070048import android.telephony.ServiceState;
Wink Saville36469e72014-06-11 15:17:00 -070049import android.telephony.SubscriptionManager;
Wink Saville08874612014-08-31 19:19:58 -070050import android.telephony.SubInfoRecord;
Ihab Awadf2177b72013-11-25 13:33:23 -080051import android.telephony.TelephonyManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070052import android.text.TextUtils;
53import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -080054import android.util.Pair;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070055
Shishir Agrawal566b7612013-10-28 14:41:00 -070056import com.android.internal.telephony.CallManager;
57import com.android.internal.telephony.CommandException;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070058import com.android.internal.telephony.Connection;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070059import com.android.internal.telephony.DefaultPhoneNotifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070060import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -080061import com.android.internal.telephony.IccCard;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070062import com.android.internal.telephony.Phone;
Wink Saville36469e72014-06-11 15:17:00 -070063import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -070064import com.android.internal.telephony.PhoneProxy;
65import com.android.internal.telephony.ProxyController;
Wink Saville36469e72014-06-11 15:17:00 -070066import com.android.internal.telephony.CallManager;
67import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070068import com.android.internal.telephony.PhoneConstants;
Wink Saville08874612014-08-31 19:19:58 -070069import com.android.internal.telephony.TelephonyIntents;
Wink Saville36469e72014-06-11 15:17:00 -070070import com.android.internal.telephony.dataconnection.DctController;
Derek Tan7226c842014-07-02 17:42:23 -070071import com.android.internal.telephony.uicc.AdnRecord;
Shishir Agrawal566b7612013-10-28 14:41:00 -070072import com.android.internal.telephony.uicc.IccIoResult;
73import com.android.internal.telephony.uicc.IccUtils;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -070074import com.android.internal.telephony.uicc.UiccCard;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070075import com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
Shishir Agrawal566b7612013-10-28 14:41:00 -070076import com.android.internal.telephony.uicc.UiccController;
Jake Hambye994d462014-02-03 13:10:13 -080077import com.android.internal.util.HexDump;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070078
Wink Saville36469e72014-06-11 15:17:00 -070079import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
80
Santos Cordon7d4ddf62013-07-10 11:58:08 -070081import java.util.ArrayList;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070082import java.util.HashMap;
Derek Tan89e89d42014-07-08 17:00:10 -070083import java.util.HashSet;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070084import java.util.Iterator;
Jake Hambye994d462014-02-03 13:10:13 -080085import java.util.List;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070086import java.util.Map;
Derek Tan89e89d42014-07-08 17:00:10 -070087import java.util.Set;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070088
89/**
90 * Implementation of the ITelephony interface.
91 */
Santos Cordon117fee72014-05-16 17:56:12 -070092public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070093 private static final String LOG_TAG = "PhoneInterfaceManager";
94 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
95 private static final boolean DBG_LOC = false;
96
97 // Message codes used with mMainThreadHandler
98 private static final int CMD_HANDLE_PIN_MMI = 1;
99 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
100 private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
101 private static final int CMD_ANSWER_RINGING_CALL = 4;
102 private static final int CMD_END_CALL = 5; // not used yet
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700103 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
104 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700105 private static final int CMD_OPEN_CHANNEL = 9;
106 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
107 private static final int CMD_CLOSE_CHANNEL = 11;
108 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800109 private static final int CMD_NV_READ_ITEM = 13;
110 private static final int EVENT_NV_READ_ITEM_DONE = 14;
111 private static final int CMD_NV_WRITE_ITEM = 15;
112 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
113 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
114 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
115 private static final int CMD_NV_RESET_CONFIG = 19;
116 private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800117 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
118 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
119 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
120 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800121 private static final int CMD_SEND_ENVELOPE = 25;
122 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Derek Tan6b088ee2014-09-05 14:15:18 -0700123 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
124 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
125 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
126 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
127 private static final int CMD_EXCHANGE_SIM_IO = 31;
128 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700129
130 /** The singleton instance. */
131 private static PhoneInterfaceManager sInstance;
132
133 PhoneGlobals mApp;
134 Phone mPhone;
135 CallManager mCM;
136 AppOpsManager mAppOps;
137 MainThreadHandler mMainThreadHandler;
138
Andrew Leedf14ead2014-10-17 14:22:52 -0700139 SharedPreferences mTelephonySharedPreferences;
Derek Tan97ebb422014-09-05 16:55:38 -0700140 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
141 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
142 private static final String PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX =
143 "carrier_simplified_network_settings_";
Andrew Leedf14ead2014-10-17 14:22:52 -0700144 private static final String PREF_ENABLE_VIDEO_CALLING = "enable_video_calling";
Derek Tan89e89d42014-07-08 17:00:10 -0700145
146 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700147 * A request object to use for transmitting data to an ICC.
148 */
149 private static final class IccAPDUArgument {
150 public int channel, cla, command, p1, p2, p3;
151 public String data;
152
153 public IccAPDUArgument(int channel, int cla, int command,
154 int p1, int p2, int p3, String data) {
155 this.channel = channel;
156 this.cla = cla;
157 this.command = command;
158 this.p1 = p1;
159 this.p2 = p2;
160 this.p3 = p3;
161 this.data = data;
162 }
163 }
164
165 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700166 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
167 * request after sending. The main thread will notify the request when it is complete.
168 */
169 private static final class MainThreadRequest {
170 /** The argument to use for the request */
171 public Object argument;
172 /** The result of the request that is run on the main thread */
173 public Object result;
174
175 public MainThreadRequest(Object argument) {
176 this.argument = argument;
177 }
178 }
179
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800180 private static final class IncomingThirdPartyCallArgs {
181 public final ComponentName component;
182 public final String callId;
183 public final String callerDisplayName;
184
185 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
186 String callerDisplayName) {
187 this.component = component;
188 this.callId = callId;
189 this.callerDisplayName = callerDisplayName;
190 }
191 }
192
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700193 /**
194 * A handler that processes messages on the main thread in the phone process. Since many
195 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
196 * inbound binder threads to the main thread in the phone process. The Binder thread
197 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
198 * on, which will be notified when the operation completes and will contain the result of the
199 * request.
200 *
201 * <p>If a MainThreadRequest object is provided in the msg.obj field,
202 * note that request.result must be set to something non-null for the calling thread to
203 * unblock.
204 */
205 private final class MainThreadHandler extends Handler {
206 @Override
207 public void handleMessage(Message msg) {
208 MainThreadRequest request;
209 Message onCompleted;
210 AsyncResult ar;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700211 UiccCard uiccCard = UiccController.getInstance().getUiccCard();
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700212 IccAPDUArgument iccArgument;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700213
214 switch (msg.what) {
215 case CMD_HANDLE_PIN_MMI:
216 request = (MainThreadRequest) msg.obj;
Jake Hambye994d462014-02-03 13:10:13 -0800217 request.result = mPhone.handlePinMmi((String) request.argument);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700218 // Wake up the requesting thread
219 synchronized (request) {
220 request.notifyAll();
221 }
222 break;
223
224 case CMD_HANDLE_NEIGHBORING_CELL:
225 request = (MainThreadRequest) msg.obj;
226 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
227 request);
228 mPhone.getNeighboringCids(onCompleted);
229 break;
230
231 case EVENT_NEIGHBORING_CELL_DONE:
232 ar = (AsyncResult) msg.obj;
233 request = (MainThreadRequest) ar.userObj;
234 if (ar.exception == null && ar.result != null) {
235 request.result = ar.result;
236 } else {
237 // create an empty list to notify the waiting thread
Jake Hambye994d462014-02-03 13:10:13 -0800238 request.result = new ArrayList<NeighboringCellInfo>(0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700239 }
240 // Wake up the requesting thread
241 synchronized (request) {
242 request.notifyAll();
243 }
244 break;
245
246 case CMD_ANSWER_RINGING_CALL:
Wink Saville08874612014-08-31 19:19:58 -0700247 request = (MainThreadRequest) msg.obj;
248 long answer_subId = ((Long)request.argument).longValue();
249 answerRingingCallInternal(answer_subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700250 break;
251
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700252 case CMD_END_CALL:
253 request = (MainThreadRequest) msg.obj;
Wink Saville08874612014-08-31 19:19:58 -0700254 long end_subId = ((Long)request.argument).longValue();
255 final boolean hungUp;
256 int phoneType = getPhone(end_subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700257 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
258 // CDMA: If the user presses the Power button we treat it as
259 // ending the complete call session
Wink Saville08874612014-08-31 19:19:58 -0700260 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700261 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
262 // GSM: End the call as per the Phone state
263 hungUp = PhoneUtils.hangup(mCM);
264 } else {
265 throw new IllegalStateException("Unexpected phone type: " + phoneType);
266 }
267 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
268 request.result = hungUp;
269 // Wake up the requesting thread
270 synchronized (request) {
271 request.notifyAll();
272 }
273 break;
274
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700275 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700276 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700277 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700278 if (uiccCard == null) {
279 loge("iccTransmitApduLogicalChannel: No UICC");
280 request.result = new IccIoResult(0x6F, 0, (byte[])null);
281 synchronized (request) {
282 request.notifyAll();
283 }
284 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700285 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
286 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700287 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700288 iccArgument.channel, iccArgument.cla, iccArgument.command,
289 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700290 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700291 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700292 break;
293
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700294 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700295 ar = (AsyncResult) msg.obj;
296 request = (MainThreadRequest) ar.userObj;
297 if (ar.exception == null && ar.result != null) {
298 request.result = ar.result;
299 } else {
300 request.result = new IccIoResult(0x6F, 0, (byte[])null);
301 if (ar.result == null) {
302 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800303 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700304 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800305 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700306 } else {
307 loge("iccTransmitApduLogicalChannel: Unknown exception");
308 }
309 }
310 synchronized (request) {
311 request.notifyAll();
312 }
313 break;
314
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700315 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
316 request = (MainThreadRequest) msg.obj;
317 iccArgument = (IccAPDUArgument) request.argument;
318 if (uiccCard == null) {
319 loge("iccTransmitApduBasicChannel: No UICC");
320 request.result = new IccIoResult(0x6F, 0, (byte[])null);
321 synchronized (request) {
322 request.notifyAll();
323 }
324 } else {
325 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
326 request);
327 uiccCard.iccTransmitApduBasicChannel(
328 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
329 iccArgument.p3, iccArgument.data, onCompleted);
330 }
331 break;
332
333 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
334 ar = (AsyncResult) msg.obj;
335 request = (MainThreadRequest) ar.userObj;
336 if (ar.exception == null && ar.result != null) {
337 request.result = ar.result;
338 } else {
339 request.result = new IccIoResult(0x6F, 0, (byte[])null);
340 if (ar.result == null) {
341 loge("iccTransmitApduBasicChannel: Empty response");
342 } else if (ar.exception instanceof CommandException) {
343 loge("iccTransmitApduBasicChannel: CommandException: " +
344 ar.exception);
345 } else {
346 loge("iccTransmitApduBasicChannel: Unknown exception");
347 }
348 }
349 synchronized (request) {
350 request.notifyAll();
351 }
352 break;
353
354 case CMD_EXCHANGE_SIM_IO:
355 request = (MainThreadRequest) msg.obj;
356 iccArgument = (IccAPDUArgument) request.argument;
357 if (uiccCard == null) {
358 loge("iccExchangeSimIO: No UICC");
359 request.result = new IccIoResult(0x6F, 0, (byte[])null);
360 synchronized (request) {
361 request.notifyAll();
362 }
363 } else {
364 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
365 request);
366 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
367 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
368 iccArgument.data, onCompleted);
369 }
370 break;
371
372 case EVENT_EXCHANGE_SIM_IO_DONE:
373 ar = (AsyncResult) msg.obj;
374 request = (MainThreadRequest) ar.userObj;
375 if (ar.exception == null && ar.result != null) {
376 request.result = ar.result;
377 } else {
378 request.result = new IccIoResult(0x6f, 0, (byte[])null);
379 }
380 synchronized (request) {
381 request.notifyAll();
382 }
383 break;
384
Derek Tan4d5e5c12014-02-04 11:54:58 -0800385 case CMD_SEND_ENVELOPE:
386 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700387 if (uiccCard == null) {
388 loge("sendEnvelopeWithStatus: No UICC");
389 request.result = new IccIoResult(0x6F, 0, (byte[])null);
390 synchronized (request) {
391 request.notifyAll();
392 }
393 } else {
394 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
395 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
396 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800397 break;
398
399 case EVENT_SEND_ENVELOPE_DONE:
400 ar = (AsyncResult) msg.obj;
401 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700402 if (ar.exception == null && ar.result != null) {
403 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800404 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700405 request.result = new IccIoResult(0x6F, 0, (byte[])null);
406 if (ar.result == null) {
407 loge("sendEnvelopeWithStatus: Empty response");
408 } else if (ar.exception instanceof CommandException) {
409 loge("sendEnvelopeWithStatus: CommandException: " +
410 ar.exception);
411 } else {
412 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
413 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800414 }
415 synchronized (request) {
416 request.notifyAll();
417 }
418 break;
419
Shishir Agrawal566b7612013-10-28 14:41:00 -0700420 case CMD_OPEN_CHANNEL:
421 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700422 if (uiccCard == null) {
423 loge("iccOpenLogicalChannel: No UICC");
424 request.result = new IccIoResult(0x6F, 0, (byte[])null);
425 synchronized (request) {
426 request.notifyAll();
427 }
428 } else {
429 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
430 uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
431 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700432 break;
433
434 case EVENT_OPEN_CHANNEL_DONE:
435 ar = (AsyncResult) msg.obj;
436 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700437 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700438 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700439 int[] result = (int[]) ar.result;
440 int channelId = result[0];
441 byte[] selectResponse = null;
442 if (result.length > 1) {
443 selectResponse = new byte[result.length - 1];
444 for (int i = 1; i < result.length; ++i) {
445 selectResponse[i - 1] = (byte) result[i];
446 }
447 }
448 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700449 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700450 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700451 if (ar.result == null) {
452 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700453 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700454 if (ar.exception != null) {
455 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
456 }
457
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700458 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700459 if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
460 if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700461 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700462 } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700463 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700464 }
465 }
466 openChannelResp = new IccOpenLogicalChannelResponse(
467 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700468 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700469 request.result = openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700470 synchronized (request) {
471 request.notifyAll();
472 }
473 break;
474
475 case CMD_CLOSE_CHANNEL:
476 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700477 if (uiccCard == null) {
478 loge("iccCloseLogicalChannel: No UICC");
479 request.result = new IccIoResult(0x6F, 0, (byte[])null);
480 synchronized (request) {
481 request.notifyAll();
482 }
483 } else {
484 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
485 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
486 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700487 break;
488
489 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800490 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
491 break;
492
493 case CMD_NV_READ_ITEM:
494 request = (MainThreadRequest) msg.obj;
495 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
496 mPhone.nvReadItem((Integer) request.argument, onCompleted);
497 break;
498
499 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700500 ar = (AsyncResult) msg.obj;
501 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800502 if (ar.exception == null && ar.result != null) {
503 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700504 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800505 request.result = "";
506 if (ar.result == null) {
507 loge("nvReadItem: Empty response");
508 } else if (ar.exception instanceof CommandException) {
509 loge("nvReadItem: CommandException: " +
510 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700511 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800512 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700513 }
514 }
515 synchronized (request) {
516 request.notifyAll();
517 }
518 break;
519
Jake Hambye994d462014-02-03 13:10:13 -0800520 case CMD_NV_WRITE_ITEM:
521 request = (MainThreadRequest) msg.obj;
522 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
523 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
524 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
525 break;
526
527 case EVENT_NV_WRITE_ITEM_DONE:
528 handleNullReturnEvent(msg, "nvWriteItem");
529 break;
530
531 case CMD_NV_WRITE_CDMA_PRL:
532 request = (MainThreadRequest) msg.obj;
533 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
534 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
535 break;
536
537 case EVENT_NV_WRITE_CDMA_PRL_DONE:
538 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
539 break;
540
541 case CMD_NV_RESET_CONFIG:
542 request = (MainThreadRequest) msg.obj;
543 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
544 mPhone.nvResetConfig((Integer) request.argument, onCompleted);
545 break;
546
547 case EVENT_NV_RESET_CONFIG_DONE:
548 handleNullReturnEvent(msg, "nvResetConfig");
549 break;
550
Jake Hamby7c27be32014-03-03 13:25:59 -0800551 case CMD_GET_PREFERRED_NETWORK_TYPE:
552 request = (MainThreadRequest) msg.obj;
553 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
554 mPhone.getPreferredNetworkType(onCompleted);
555 break;
556
557 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
558 ar = (AsyncResult) msg.obj;
559 request = (MainThreadRequest) ar.userObj;
560 if (ar.exception == null && ar.result != null) {
561 request.result = ar.result; // Integer
562 } else {
563 request.result = -1;
564 if (ar.result == null) {
565 loge("getPreferredNetworkType: Empty response");
566 } else if (ar.exception instanceof CommandException) {
567 loge("getPreferredNetworkType: CommandException: " +
568 ar.exception);
569 } else {
570 loge("getPreferredNetworkType: Unknown exception");
571 }
572 }
573 synchronized (request) {
574 request.notifyAll();
575 }
576 break;
577
578 case CMD_SET_PREFERRED_NETWORK_TYPE:
579 request = (MainThreadRequest) msg.obj;
580 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
581 int networkType = (Integer) request.argument;
582 mPhone.setPreferredNetworkType(networkType, onCompleted);
583 break;
584
585 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
586 handleNullReturnEvent(msg, "setPreferredNetworkType");
587 break;
588
Steven Liu4bf01bc2014-07-17 11:05:29 -0500589 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
590 request = (MainThreadRequest)msg.obj;
591 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
592 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
593 break;
594
595 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
596 ar = (AsyncResult)msg.obj;
597 request = (MainThreadRequest)ar.userObj;
598 request.result = ar;
599 synchronized (request) {
600 request.notifyAll();
601 }
602 break;
603
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700604 default:
605 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
606 break;
607 }
608 }
Jake Hambye994d462014-02-03 13:10:13 -0800609
610 private void handleNullReturnEvent(Message msg, String command) {
611 AsyncResult ar = (AsyncResult) msg.obj;
612 MainThreadRequest request = (MainThreadRequest) ar.userObj;
613 if (ar.exception == null) {
614 request.result = true;
615 } else {
616 request.result = false;
617 if (ar.exception instanceof CommandException) {
618 loge(command + ": CommandException: " + ar.exception);
619 } else {
620 loge(command + ": Unknown exception");
621 }
622 }
623 synchronized (request) {
624 request.notifyAll();
625 }
626 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700627 }
628
629 /**
630 * Posts the specified command to be executed on the main thread,
631 * waits for the request to complete, and returns the result.
632 * @see #sendRequestAsync
633 */
634 private Object sendRequest(int command, Object argument) {
Santos Cordon500b0e02014-06-17 10:33:33 -0700635 return sendRequest(command, argument, null);
Wink Saville36469e72014-06-11 15:17:00 -0700636 }
637
638 /**
639 * Posts the specified command to be executed on the main thread,
640 * waits for the request to complete, and returns the result.
641 * @see #sendRequestAsync
642 */
643 private Object sendRequest(int command, Object argument, Object argument2) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700644 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
645 throw new RuntimeException("This method will deadlock if called from the main thread.");
646 }
647
648 MainThreadRequest request = new MainThreadRequest(argument);
649 Message msg = mMainThreadHandler.obtainMessage(command, request);
650 msg.sendToTarget();
651
652 // Wait for the request to complete
653 synchronized (request) {
654 while (request.result == null) {
655 try {
656 request.wait();
657 } catch (InterruptedException e) {
658 // Do nothing, go back and wait until the request is complete
659 }
660 }
661 }
662 return request.result;
663 }
664
665 /**
666 * Asynchronous ("fire and forget") version of sendRequest():
667 * Posts the specified command to be executed on the main thread, and
668 * returns immediately.
669 * @see #sendRequest
670 */
671 private void sendRequestAsync(int command) {
672 mMainThreadHandler.sendEmptyMessage(command);
673 }
674
675 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -0700676 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
677 * @see {@link #sendRequest(int,Object)}
678 */
679 private void sendRequestAsync(int command, Object argument) {
680 MainThreadRequest request = new MainThreadRequest(argument);
681 Message msg = mMainThreadHandler.obtainMessage(command, request);
682 msg.sendToTarget();
683 }
684
685 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700686 * Initialize the singleton PhoneInterfaceManager instance.
687 * This is only done once, at startup, from PhoneApp.onCreate().
688 */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700689 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700690 synchronized (PhoneInterfaceManager.class) {
691 if (sInstance == null) {
Sailesh Nepal194161e2014-07-03 08:57:44 -0700692 sInstance = new PhoneInterfaceManager(app, phone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700693 } else {
694 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
695 }
696 return sInstance;
697 }
698 }
699
700 /** Private constructor; @see init() */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700701 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700702 mApp = app;
703 mPhone = phone;
704 mCM = PhoneGlobals.getInstance().mCM;
705 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
706 mMainThreadHandler = new MainThreadHandler();
Andrew Leedf14ead2014-10-17 14:22:52 -0700707 mTelephonySharedPreferences =
Derek Tan97ebb422014-09-05 16:55:38 -0700708 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700709 publish();
710 }
711
712 private void publish() {
713 if (DBG) log("publish: " + this);
714
715 ServiceManager.addService("phone", this);
716 }
717
Wink Saville36469e72014-06-11 15:17:00 -0700718 // returns phone associated with the subId.
Wink Saville36469e72014-06-11 15:17:00 -0700719 private Phone getPhone(long subId) {
Legler Wuf8733b42014-09-25 11:00:54 +0800720 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -0700721 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700722 //
723 // Implementation of the ITelephony interface.
724 //
725
726 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700727 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -0700728 }
729
Wink Savilleadd7cc52014-09-08 14:23:09 -0700730 public void dialForSubscriber(long subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700731 if (DBG) log("dial: " + number);
732 // No permission check needed here: This is just a wrapper around the
733 // ACTION_DIAL intent, which is available to any app since it puts up
734 // the UI before it does anything.
735
736 String url = createTelUrl(number);
737 if (url == null) {
738 return;
739 }
740
741 // PENDING: should we just silently fail if phone is offhook or ringing?
Wink Saville36469e72014-06-11 15:17:00 -0700742 PhoneConstants.State state = mCM.getState(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700743 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
744 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
745 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
746 mApp.startActivity(intent);
747 }
748 }
749
750 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700751 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -0700752 }
753
Wink Savilleadd7cc52014-09-08 14:23:09 -0700754 public void callForSubscriber(long subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700755 if (DBG) log("call: " + number);
756
757 // This is just a wrapper around the ACTION_CALL intent, but we still
758 // need to do a permission check since we're calling startActivity()
759 // from the context of the phone app.
760 enforceCallPermission();
761
762 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
763 != AppOpsManager.MODE_ALLOWED) {
764 return;
765 }
766
767 String url = createTelUrl(number);
768 if (url == null) {
769 return;
770 }
771
Wink Saville08874612014-08-31 19:19:58 -0700772 boolean isValid = false;
Wink Saville10aa2e92014-09-04 10:46:34 -0700773 List<SubInfoRecord> slist = SubscriptionManager.getActiveSubInfoList();
Wink Saville08874612014-08-31 19:19:58 -0700774 for (SubInfoRecord subInfoRecord : slist) {
Wink Savilleb30c9a22014-09-04 22:42:02 -0700775 if (subInfoRecord.subId == subId) {
Wink Saville08874612014-08-31 19:19:58 -0700776 isValid = true;
777 break;
778 }
779 }
780 if (isValid == false) {
781 return;
782 }
783
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700784 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
Wink Saville36469e72014-06-11 15:17:00 -0700785 intent.putExtra(SUBSCRIPTION_KEY, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700786 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
787 mApp.startActivity(intent);
788 }
789
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700790 /**
791 * End a call based on call state
792 * @return true is a call was ended
793 */
794 public boolean endCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700795 return endCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700796 }
797
798 /**
799 * End a call based on the call state of the subId
800 * @return true is a call was ended
801 */
Wink Savilleadd7cc52014-09-08 14:23:09 -0700802 public boolean endCallForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700803 enforceCallPermission();
Wink Saville08874612014-08-31 19:19:58 -0700804 return (Boolean) sendRequest(CMD_END_CALL, new Long(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700805 }
806
807 public void answerRingingCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700808 answerRingingCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700809 }
810
Wink Savilleadd7cc52014-09-08 14:23:09 -0700811 public void answerRingingCallForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700812 if (DBG) log("answerRingingCall...");
813 // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
814 // but that can probably wait till the big TelephonyManager API overhaul.
815 // For now, protect this call with the MODIFY_PHONE_STATE permission.
816 enforceModifyPermission();
Wink Saville08874612014-08-31 19:19:58 -0700817 sendRequest(CMD_ANSWER_RINGING_CALL, new Long(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700818 }
819
820 /**
821 * Make the actual telephony calls to implement answerRingingCall().
822 * This should only be called from the main thread of the Phone app.
823 * @see #answerRingingCall
824 *
825 * TODO: it would be nice to return true if we answered the call, or
826 * false if there wasn't actually a ringing incoming call, or some
827 * other error occurred. (In other words, pass back the return value
828 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
829 * But that would require calling this method via sendRequest() rather
830 * than sendRequestAsync(), and right now we don't actually *need* that
831 * return value, so let's just return void for now.
832 */
Wink Saville08874612014-08-31 19:19:58 -0700833 private void answerRingingCallInternal(long subId) {
834 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700835 if (hasRingingCall) {
Wink Saville08874612014-08-31 19:19:58 -0700836 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
837 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700838 if (hasActiveCall && hasHoldingCall) {
839 // Both lines are in use!
840 // TODO: provide a flag to let the caller specify what
841 // policy to use if both lines are in use. (The current
842 // behavior is hardwired to "answer incoming, end ongoing",
843 // which is how the CALL button is specced to behave.)
844 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
845 return;
846 } else {
847 // answerCall() will automatically hold the current active
848 // call, if there is one.
849 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
850 return;
851 }
852 } else {
853 // No call was ringing.
854 return;
855 }
856 }
857
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700858 /**
Santos Cordon5422a8d2014-09-12 04:20:56 -0700859 * This method is no longer used and can be removed once TelephonyManager stops referring to it.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700860 */
Santos Cordon5422a8d2014-09-12 04:20:56 -0700861 public void silenceRinger() {
862 Log.e(LOG_TAG, "silenseRinger not supported");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700863 }
864
865 public boolean isOffhook() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700866 return isOffhookForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700867 }
868
Wink Savilleadd7cc52014-09-08 14:23:09 -0700869 public boolean isOffhookForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700870 return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700871 }
872
873 public boolean isRinging() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700874 return (isRingingForSubscriber(getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -0700875 }
876
Wink Savilleadd7cc52014-09-08 14:23:09 -0700877 public boolean isRingingForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700878 return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700879 }
880
881 public boolean isIdle() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700882 return isIdleForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700883 }
884
Wink Savilleadd7cc52014-09-08 14:23:09 -0700885 public boolean isIdleForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700886 return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700887 }
888
889 public boolean isSimPinEnabled() {
890 enforceReadPermission();
891 return (PhoneGlobals.getInstance().isSimPinEnabled());
892 }
893
894 public boolean supplyPin(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700895 return supplyPinForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -0700896 }
897
Wink Savilleadd7cc52014-09-08 14:23:09 -0700898 public boolean supplyPinForSubscriber(long subId, String pin) {
899 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700900 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
901 }
902
903 public boolean supplyPuk(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700904 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -0700905 }
906
Wink Savilleadd7cc52014-09-08 14:23:09 -0700907 public boolean supplyPukForSubscriber(long subId, String puk, String pin) {
908 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700909 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
910 }
911
912 /** {@hide} */
913 public int[] supplyPinReportResult(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700914 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -0700915 }
916
Wink Savilleadd7cc52014-09-08 14:23:09 -0700917 public int[] supplyPinReportResultForSubscriber(long subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700918 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700919 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700920 checkSimPin.start();
921 return checkSimPin.unlockSim(null, pin);
922 }
923
Wink Saville9de0f752013-10-22 19:04:03 -0700924 /** {@hide} */
925 public int[] supplyPukReportResult(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700926 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -0700927 }
928
Wink Savilleadd7cc52014-09-08 14:23:09 -0700929 public int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700930 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700931 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700932 checkSimPuk.start();
933 return checkSimPuk.unlockSim(puk, pin);
934 }
935
936 /**
Wink Saville9de0f752013-10-22 19:04:03 -0700937 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700938 * a synchronous one.
939 */
940 private static class UnlockSim extends Thread {
941
942 private final IccCard mSimCard;
943
944 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -0700945 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
946 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700947
948 // For replies from SimCard interface
949 private Handler mHandler;
950
951 // For async handler to identify request type
952 private static final int SUPPLY_PIN_COMPLETE = 100;
953
954 public UnlockSim(IccCard simCard) {
955 mSimCard = simCard;
956 }
957
958 @Override
959 public void run() {
960 Looper.prepare();
961 synchronized (UnlockSim.this) {
962 mHandler = new Handler() {
963 @Override
964 public void handleMessage(Message msg) {
965 AsyncResult ar = (AsyncResult) msg.obj;
966 switch (msg.what) {
967 case SUPPLY_PIN_COMPLETE:
968 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
969 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -0700970 mRetryCount = msg.arg1;
971 if (ar.exception != null) {
972 if (ar.exception instanceof CommandException &&
973 ((CommandException)(ar.exception)).getCommandError()
974 == CommandException.Error.PASSWORD_INCORRECT) {
975 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
976 } else {
977 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
978 }
979 } else {
980 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
981 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700982 mDone = true;
983 UnlockSim.this.notifyAll();
984 }
985 break;
986 }
987 }
988 };
989 UnlockSim.this.notifyAll();
990 }
991 Looper.loop();
992 }
993
994 /*
995 * Use PIN or PUK to unlock SIM card
996 *
997 * If PUK is null, unlock SIM card with PIN
998 *
999 * If PUK is not null, unlock SIM card with PUK and set PIN code
1000 */
Wink Saville9de0f752013-10-22 19:04:03 -07001001 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001002
1003 while (mHandler == null) {
1004 try {
1005 wait();
1006 } catch (InterruptedException e) {
1007 Thread.currentThread().interrupt();
1008 }
1009 }
1010 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1011
1012 if (puk == null) {
1013 mSimCard.supplyPin(pin, callback);
1014 } else {
1015 mSimCard.supplyPuk(puk, pin, callback);
1016 }
1017
1018 while (!mDone) {
1019 try {
1020 Log.d(LOG_TAG, "wait for done");
1021 wait();
1022 } catch (InterruptedException e) {
1023 // Restore the interrupted status
1024 Thread.currentThread().interrupt();
1025 }
1026 }
1027 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001028 int[] resultArray = new int[2];
1029 resultArray[0] = mResult;
1030 resultArray[1] = mRetryCount;
1031 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001032 }
1033 }
1034
1035 public void updateServiceLocation() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001036 updateServiceLocationForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001037
1038 }
1039
Wink Savilleadd7cc52014-09-08 14:23:09 -07001040 public void updateServiceLocationForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001041 // No permission check needed here: this call is harmless, and it's
1042 // needed for the ServiceState.requestStateUpdate() call (which is
1043 // already intentionally exposed to 3rd parties.)
Wink Saville36469e72014-06-11 15:17:00 -07001044 getPhone(subId).updateServiceLocation();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001045 }
1046
1047 public boolean isRadioOn() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001048 return isRadioOnForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001049 }
1050
Wink Savilleadd7cc52014-09-08 14:23:09 -07001051 public boolean isRadioOnForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001052 return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001053 }
1054
1055 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001056 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001057
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001058 }
Wink Saville36469e72014-06-11 15:17:00 -07001059
Wink Savilleadd7cc52014-09-08 14:23:09 -07001060 public void toggleRadioOnOffForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001061 enforceModifyPermission();
Wink Savilleadd7cc52014-09-08 14:23:09 -07001062 getPhone(subId).setRadioPower(!isRadioOnForSubscriber(subId));
Wink Saville36469e72014-06-11 15:17:00 -07001063 }
1064
1065 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001066 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001067 }
1068
Wink Savilleadd7cc52014-09-08 14:23:09 -07001069 public boolean setRadioForSubscriber(long subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001070 enforceModifyPermission();
1071 if ((getPhone(subId).getServiceState().getState() !=
1072 ServiceState.STATE_POWER_OFF) != turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001073 toggleRadioOnOffForSubscriber(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001074 }
1075 return true;
1076 }
Wink Saville36469e72014-06-11 15:17:00 -07001077
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001078 public boolean needMobileRadioShutdown() {
1079 /*
1080 * If any of the Radios are available, it will need to be
1081 * shutdown. So return true if any Radio is available.
1082 */
1083 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1084 Phone phone = PhoneFactory.getPhone(i);
1085 if (phone != null && phone.isRadioAvailable()) return true;
1086 }
1087 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1088 return false;
1089 }
1090
1091 public void shutdownMobileRadios() {
1092 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1093 logv("Shutting down Phone " + i);
1094 shutdownRadioUsingPhoneId(i);
1095 }
1096 }
1097
1098 private void shutdownRadioUsingPhoneId(int phoneId) {
1099 enforceModifyPermission();
1100 Phone phone = PhoneFactory.getPhone(phoneId);
1101 if (phone != null && phone.isRadioAvailable()) {
1102 phone.shutdownRadio();
1103 }
1104 }
1105
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001106 public boolean setRadioPower(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001107 return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001108 }
1109
Wink Savilleadd7cc52014-09-08 14:23:09 -07001110 public boolean setRadioPowerForSubscriber(long subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001111 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001112 getPhone(subId).setRadioPower(turnOn);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001113 return true;
1114 }
1115
Wink Saville36469e72014-06-11 15:17:00 -07001116 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001117 public boolean enableDataConnectivity() {
1118 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001119 long subId = SubscriptionManager.getDefaultDataSubId();
1120 getPhone(subId).setDataEnabled(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001121 return true;
1122 }
1123
Wink Saville36469e72014-06-11 15:17:00 -07001124 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001125 public boolean disableDataConnectivity() {
1126 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001127 long subId = SubscriptionManager.getDefaultDataSubId();
1128 getPhone(subId).setDataEnabled(false);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001129 return true;
1130 }
1131
Wink Saville36469e72014-06-11 15:17:00 -07001132 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001133 public boolean isDataConnectivityPossible() {
Wink Saville36469e72014-06-11 15:17:00 -07001134 long subId = SubscriptionManager.getDefaultDataSubId();
1135 return getPhone(subId).isDataConnectivityPossible();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001136 }
1137
1138 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001139 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07001140 }
1141
Wink Savilleadd7cc52014-09-08 14:23:09 -07001142 public boolean handlePinMmiForSubscriber(long subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001143 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001144 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001145 }
1146
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001147 public int getCallState() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001148 return getCallStateForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001149 }
1150
Wink Savilleadd7cc52014-09-08 14:23:09 -07001151 public int getCallStateForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001152 return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001153 }
1154
1155 public int getDataState() {
Wink Saville36469e72014-06-11 15:17:00 -07001156 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1157 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001158 }
1159
1160 public int getDataActivity() {
Wink Saville36469e72014-06-11 15:17:00 -07001161 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1162 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001163 }
1164
1165 @Override
1166 public Bundle getCellLocation() {
1167 try {
1168 mApp.enforceCallingOrSelfPermission(
1169 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1170 } catch (SecurityException e) {
1171 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1172 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1173 // is the weaker precondition
1174 mApp.enforceCallingOrSelfPermission(
1175 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1176 }
1177
Jake Hambye994d462014-02-03 13:10:13 -08001178 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001179 if (DBG_LOC) log("getCellLocation: is active user");
1180 Bundle data = new Bundle();
1181 mPhone.getCellLocation().fillInNotifierBundle(data);
1182 return data;
1183 } else {
1184 if (DBG_LOC) log("getCellLocation: suppress non-active user");
1185 return null;
1186 }
1187 }
1188
1189 @Override
1190 public void enableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001191 enableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001192 }
1193
Wink Savilleadd7cc52014-09-08 14:23:09 -07001194 public void enableLocationUpdatesForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001195 mApp.enforceCallingOrSelfPermission(
1196 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001197 getPhone(subId).enableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001198 }
1199
1200 @Override
1201 public void disableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001202 disableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001203 }
1204
Wink Savilleadd7cc52014-09-08 14:23:09 -07001205 public void disableLocationUpdatesForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001206 mApp.enforceCallingOrSelfPermission(
1207 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001208 getPhone(subId).disableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001209 }
1210
1211 @Override
1212 @SuppressWarnings("unchecked")
1213 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1214 try {
1215 mApp.enforceCallingOrSelfPermission(
1216 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1217 } catch (SecurityException e) {
1218 // If we have ACCESS_FINE_LOCATION permission, skip the check
1219 // for ACCESS_COARSE_LOCATION
1220 // A failure should throw the SecurityException from
1221 // ACCESS_COARSE_LOCATION since this is the weaker precondition
1222 mApp.enforceCallingOrSelfPermission(
1223 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1224 }
1225
1226 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1227 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1228 return null;
1229 }
Jake Hambye994d462014-02-03 13:10:13 -08001230 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001231 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1232
1233 ArrayList<NeighboringCellInfo> cells = null;
1234
1235 try {
1236 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
Wink Saville36469e72014-06-11 15:17:00 -07001237 CMD_HANDLE_NEIGHBORING_CELL, null, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001238 } catch (RuntimeException e) {
Wink Saville36469e72014-06-11 15:17:00 -07001239 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001240 }
1241 return cells;
1242 } else {
1243 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1244 return null;
1245 }
1246 }
1247
1248
1249 @Override
1250 public List<CellInfo> getAllCellInfo() {
1251 try {
1252 mApp.enforceCallingOrSelfPermission(
1253 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1254 } catch (SecurityException e) {
1255 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1256 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1257 // is the weaker precondition
1258 mApp.enforceCallingOrSelfPermission(
1259 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1260 }
1261
Jake Hambye994d462014-02-03 13:10:13 -08001262 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001263 if (DBG_LOC) log("getAllCellInfo: is active user");
1264 return mPhone.getAllCellInfo();
1265 } else {
1266 if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1267 return null;
1268 }
1269 }
1270
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001271 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001272 public void setCellInfoListRate(int rateInMillis) {
1273 mPhone.setCellInfoListRate(rateInMillis);
1274 }
1275
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001276 //
1277 // Internal helper methods.
1278 //
1279
Jake Hambye994d462014-02-03 13:10:13 -08001280 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001281 boolean ok;
1282
1283 boolean self = Binder.getCallingUid() == Process.myUid();
1284 if (!self) {
1285 // Get the caller's user id then clear the calling identity
1286 // which will be restored in the finally clause.
1287 int callingUser = UserHandle.getCallingUserId();
1288 long ident = Binder.clearCallingIdentity();
1289
1290 try {
1291 // With calling identity cleared the current user is the foreground user.
1292 int foregroundUser = ActivityManager.getCurrentUser();
1293 ok = (foregroundUser == callingUser);
1294 if (DBG_LOC) {
1295 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1296 + " callingUser=" + callingUser + " ok=" + ok);
1297 }
1298 } catch (Exception ex) {
1299 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1300 ok = false;
1301 } finally {
1302 Binder.restoreCallingIdentity(ident);
1303 }
1304 } else {
1305 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1306 ok = true;
1307 }
1308 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1309 return ok;
1310 }
1311
1312 /**
1313 * Make sure the caller has the READ_PHONE_STATE permission.
1314 *
1315 * @throws SecurityException if the caller does not have the required permission
1316 */
1317 private void enforceReadPermission() {
1318 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
1319 }
1320
1321 /**
1322 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1323 *
1324 * @throws SecurityException if the caller does not have the required permission
1325 */
1326 private void enforceModifyPermission() {
1327 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1328 }
1329
1330 /**
Junda Liua2e36012014-07-09 18:30:01 -07001331 * Make sure either system app or the caller has carrier privilege.
1332 *
1333 * @throws SecurityException if the caller does not have the required permission/privilege
1334 */
1335 private void enforceModifyPermissionOrCarrierPrivilege() {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001336 int permission = mApp.checkCallingOrSelfPermission(
1337 android.Manifest.permission.MODIFY_PHONE_STATE);
1338 if (permission == PackageManager.PERMISSION_GRANTED) {
1339 return;
1340 }
1341
1342 log("No modify permission, check carrier privilege next.");
1343 if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1344 loge("No Carrier Privilege.");
1345 throw new SecurityException("No modify permission or carrier privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001346 }
1347 }
1348
1349 /**
1350 * Make sure the caller has carrier privilege.
1351 *
1352 * @throws SecurityException if the caller does not have the required permission
1353 */
1354 private void enforceCarrierPrivilege() {
1355 if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001356 loge("No Carrier Privilege.");
1357 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001358 }
1359 }
1360
1361 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001362 * Make sure the caller has the CALL_PHONE permission.
1363 *
1364 * @throws SecurityException if the caller does not have the required permission
1365 */
1366 private void enforceCallPermission() {
1367 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1368 }
1369
Shishir Agrawal566b7612013-10-28 14:41:00 -07001370 /**
Gabriel Peal36ebb0d2014-03-20 09:20:43 -07001371 * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
1372 *
1373 * @throws SecurityException if the caller does not have the required permission
1374 */
1375 private void enforcePrivilegedPhoneStatePermission() {
1376 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1377 null);
1378 }
1379
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001380 private String createTelUrl(String number) {
1381 if (TextUtils.isEmpty(number)) {
1382 return null;
1383 }
1384
Jake Hambye994d462014-02-03 13:10:13 -08001385 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001386 }
1387
Ihab Awadf9e92732013-12-05 18:02:52 -08001388 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001389 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1390 }
1391
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001392 private static void logv(String msg) {
1393 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1394 }
1395
Ihab Awadf9e92732013-12-05 18:02:52 -08001396 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001397 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1398 }
1399
1400 public int getActivePhoneType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001401 return getActivePhoneTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001402 }
1403
Wink Savilleadd7cc52014-09-08 14:23:09 -07001404 public int getActivePhoneTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001405 return getPhone(subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001406 }
1407
1408 /**
1409 * Returns the CDMA ERI icon index to display
1410 */
1411 public int getCdmaEriIconIndex() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001412 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001413
1414 }
1415
Wink Savilleadd7cc52014-09-08 14:23:09 -07001416 public int getCdmaEriIconIndexForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001417 return getPhone(subId).getCdmaEriIconIndex();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001418 }
1419
1420 /**
1421 * Returns the CDMA ERI icon mode,
1422 * 0 - ON
1423 * 1 - FLASHING
1424 */
1425 public int getCdmaEriIconMode() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001426 return getCdmaEriIconModeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001427 }
1428
Wink Savilleadd7cc52014-09-08 14:23:09 -07001429 public int getCdmaEriIconModeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001430 return getPhone(subId).getCdmaEriIconMode();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001431 }
1432
1433 /**
1434 * Returns the CDMA ERI text,
1435 */
1436 public String getCdmaEriText() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001437 return getCdmaEriTextForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001438 }
1439
Wink Savilleadd7cc52014-09-08 14:23:09 -07001440 public String getCdmaEriTextForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001441 return getPhone(subId).getCdmaEriText();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001442 }
1443
1444 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001445 * Returns the CDMA MDN.
1446 */
1447 public String getCdmaMdn(long subId) {
1448 enforceModifyPermissionOrCarrierPrivilege();
1449 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1450 return getPhone(subId).getLine1Number();
1451 } else {
1452 return null;
1453 }
1454 }
1455
1456 /**
1457 * Returns the CDMA MIN.
1458 */
1459 public String getCdmaMin(long subId) {
1460 enforceModifyPermissionOrCarrierPrivilege();
1461 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1462 return getPhone(subId).getCdmaMin();
1463 } else {
1464 return null;
1465 }
1466 }
1467
1468 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001469 * Returns true if CDMA provisioning needs to run.
1470 */
1471 public boolean needsOtaServiceProvisioning() {
1472 return mPhone.needsOtaServiceProvisioning();
1473 }
1474
1475 /**
1476 * Returns the unread count of voicemails
1477 */
1478 public int getVoiceMessageCount() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001479 return getVoiceMessageCountForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001480 }
1481
1482 /**
1483 * Returns the unread count of voicemails for a subId
1484 */
Wink Savilleadd7cc52014-09-08 14:23:09 -07001485 public int getVoiceMessageCountForSubscriber( long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001486 return getPhone(subId).getVoiceMessageCount();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001487 }
1488
1489 /**
1490 * Returns the data network type
1491 *
1492 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
1493 */
1494 @Override
1495 public int getNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001496 return getNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001497 }
1498
1499 /**
1500 * Returns the network type for a subId
1501 */
1502 @Override
Wink Savilleadd7cc52014-09-08 14:23:09 -07001503 public int getNetworkTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001504 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001505 }
1506
1507 /**
1508 * Returns the data network type
1509 */
1510 @Override
1511 public int getDataNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001512 return getDataNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001513 }
1514
1515 /**
1516 * Returns the data network type for a subId
1517 */
1518 @Override
Wink Savilleadd7cc52014-09-08 14:23:09 -07001519 public int getDataNetworkTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001520 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001521 }
1522
1523 /**
1524 * Returns the data network type
1525 */
1526 @Override
1527 public int getVoiceNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001528 return getVoiceNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001529 }
1530
1531 /**
1532 * Returns the Voice network type for a subId
1533 */
1534 @Override
Wink Savilleadd7cc52014-09-08 14:23:09 -07001535 public int getVoiceNetworkTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001536 return getPhone(subId).getServiceState().getVoiceNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001537 }
1538
1539 /**
1540 * @return true if a ICC card is present
1541 */
1542 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07001543 // FIXME Make changes to pass defaultSimId of type int
1544 return hasIccCardUsingSlotId(getDefaultSubscription());
1545 }
1546
1547 /**
1548 * @return true if a ICC card is present for a slotId
1549 */
1550 public boolean hasIccCardUsingSlotId(long slotId) {
1551 return getPhone(slotId).getIccCard().hasIccCard();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001552 }
1553
1554 /**
1555 * Return if the current radio is LTE on CDMA. This
1556 * is a tri-state return value as for a period of time
1557 * the mode may be unknown.
1558 *
1559 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08001560 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001561 */
1562 public int getLteOnCdmaMode() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001563 return getLteOnCdmaModeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001564 }
1565
Wink Savilleadd7cc52014-09-08 14:23:09 -07001566 public int getLteOnCdmaModeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001567 return getPhone(subId).getLteOnCdmaMode();
1568 }
1569
1570 public void setPhone(Phone phone) {
1571 mPhone = phone;
1572 }
1573
1574 /**
1575 * {@hide}
1576 * Returns Default subId, 0 in the case of single standby.
1577 */
1578 private long getDefaultSubscription() {
1579 return SubscriptionManager.getDefaultSubId();
1580 }
1581
1582 private long getPreferredVoiceSubscription() {
1583 return SubscriptionManager.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001584 }
Ihab Awadf2177b72013-11-25 13:33:23 -08001585
1586 /**
1587 * @see android.telephony.TelephonyManager.WifiCallingChoices
1588 */
1589 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001590 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1591 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08001592 }
1593
1594 /**
1595 * @see android.telephony.TelephonyManager.WifiCallingChoices
1596 */
1597 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001598 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1599 Settings.System.putInt(mPhone.getContext().getContentResolver(),
1600 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08001601 }
1602
Sailesh Nepald1e68152013-12-12 19:08:02 -08001603 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07001604 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08001605 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08001606 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08001607
Shishir Agrawal566b7612013-10-28 14:41:00 -07001608 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001609 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
Junda Liua2e36012014-07-09 18:30:01 -07001610 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001611
1612 if (DBG) log("iccOpenLogicalChannel: " + AID);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001613 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1614 CMD_OPEN_CHANNEL, AID);
1615 if (DBG) log("iccOpenLogicalChannel: " + response);
1616 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07001617 }
1618
1619 @Override
1620 public boolean iccCloseLogicalChannel(int channel) {
Junda Liua2e36012014-07-09 18:30:01 -07001621 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001622
1623 if (DBG) log("iccCloseLogicalChannel: " + channel);
1624 if (channel < 0) {
1625 return false;
1626 }
Jake Hambye994d462014-02-03 13:10:13 -08001627 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001628 if (DBG) log("iccCloseLogicalChannel: " + success);
1629 return success;
1630 }
1631
1632 @Override
1633 public String iccTransmitApduLogicalChannel(int channel, int cla,
1634 int command, int p1, int p2, int p3, String data) {
Junda Liua2e36012014-07-09 18:30:01 -07001635 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001636
1637 if (DBG) {
1638 log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1639 " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1640 " data=" + data);
1641 }
1642
1643 if (channel < 0) {
1644 return "";
1645 }
1646
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001647 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawal566b7612013-10-28 14:41:00 -07001648 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1649 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1650
Shishir Agrawal566b7612013-10-28 14:41:00 -07001651 // Append the returned status code to the end of the response payload.
1652 String s = Integer.toHexString(
1653 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001654 if (response.payload != null) {
1655 s = IccUtils.bytesToHexString(response.payload) + s;
1656 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001657 return s;
1658 }
Jake Hambye994d462014-02-03 13:10:13 -08001659
Evan Charltonc66da362014-05-16 14:06:40 -07001660 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001661 public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1662 int p3, String data) {
1663 enforceModifyPermissionOrCarrierPrivilege();
1664
1665 if (DBG) {
1666 log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1667 + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1668 }
1669
1670 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1671 new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1672 if (DBG) log("iccTransmitApduBasicChannel: " + response);
1673
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001674 // Append the returned status code to the end of the response payload.
1675 String s = Integer.toHexString(
1676 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001677 if (response.payload != null) {
1678 s = IccUtils.bytesToHexString(response.payload) + s;
1679 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001680 return s;
1681 }
1682
1683 @Override
1684 public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1685 String filePath) {
1686 enforceModifyPermissionOrCarrierPrivilege();
1687
1688 if (DBG) {
1689 log("Exchange SIM_IO " + fileID + ":" + command + " " +
1690 p1 + " " + p2 + " " + p3 + ":" + filePath);
1691 }
1692
1693 IccIoResult response =
1694 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
Yong Jiang3edf3782014-10-03 13:23:28 -05001695 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath));
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001696
1697 if (DBG) {
1698 log("Exchange SIM_IO [R]" + response);
1699 }
1700
1701 byte[] result = null;
1702 int length = 2;
1703 if (response.payload != null) {
1704 length = 2 + response.payload.length;
1705 result = new byte[length];
1706 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1707 } else {
1708 result = new byte[length];
1709 }
1710
1711 result[length - 1] = (byte) response.sw2;
1712 result[length - 2] = (byte) response.sw1;
1713 return result;
1714 }
1715
1716 @Override
Evan Charltonc66da362014-05-16 14:06:40 -07001717 public String sendEnvelopeWithStatus(String content) {
Junda Liua2e36012014-07-09 18:30:01 -07001718 enforceModifyPermissionOrCarrierPrivilege();
Evan Charltonc66da362014-05-16 14:06:40 -07001719
1720 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1721 if (response.payload == null) {
1722 return "";
1723 }
1724
1725 // Append the returned status code to the end of the response payload.
1726 String s = Integer.toHexString(
1727 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1728 s = IccUtils.bytesToHexString(response.payload) + s;
1729 return s;
1730 }
1731
Jake Hambye994d462014-02-03 13:10:13 -08001732 /**
1733 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1734 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1735 *
1736 * @param itemID the ID of the item to read
1737 * @return the NV item as a String, or null on error.
1738 */
1739 @Override
1740 public String nvReadItem(int itemID) {
Junda Liua2e36012014-07-09 18:30:01 -07001741 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001742 if (DBG) log("nvReadItem: item " + itemID);
1743 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1744 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1745 return value;
1746 }
1747
1748 /**
1749 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1750 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1751 *
1752 * @param itemID the ID of the item to read
1753 * @param itemValue the value to write, as a String
1754 * @return true on success; false on any failure
1755 */
1756 @Override
1757 public boolean nvWriteItem(int itemID, String itemValue) {
Junda Liua2e36012014-07-09 18:30:01 -07001758 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001759 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1760 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1761 new Pair<Integer, String>(itemID, itemValue));
1762 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1763 return success;
1764 }
1765
1766 /**
1767 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1768 * Used for device configuration by some CDMA operators.
1769 *
1770 * @param preferredRoamingList byte array containing the new PRL
1771 * @return true on success; false on any failure
1772 */
1773 @Override
1774 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Junda Liua2e36012014-07-09 18:30:01 -07001775 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001776 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1777 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1778 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1779 return success;
1780 }
1781
1782 /**
1783 * Perform the specified type of NV config reset.
1784 * Used for device configuration by some CDMA operators.
1785 *
1786 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1787 * @return true on success; false on any failure
1788 */
1789 @Override
1790 public boolean nvResetConfig(int resetType) {
Junda Liua2e36012014-07-09 18:30:01 -07001791 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001792 if (DBG) log("nvResetConfig: type " + resetType);
1793 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1794 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1795 return success;
1796 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001797
1798 /**
Wink Saville36469e72014-06-11 15:17:00 -07001799 * {@hide}
1800 * Returns Default sim, 0 in the case of single standby.
1801 */
1802 public int getDefaultSim() {
1803 //TODO Need to get it from Telephony Devcontroller
1804 return 0;
1805 }
1806
ram87fca6f2014-07-18 18:58:44 +05301807 public String[] getPcscfAddress(String apnType) {
Wink Saville36469e72014-06-11 15:17:00 -07001808 enforceReadPermission();
ram87fca6f2014-07-18 18:58:44 +05301809 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07001810 }
1811
1812 public void setImsRegistrationState(boolean registered) {
1813 enforceModifyPermission();
1814 mPhone.setImsRegistrationState(registered);
1815 }
1816
1817 /**
Junda Liu84d15a22014-07-02 11:21:04 -07001818 * Get the calculated preferred network type.
1819 * Used for debugging incorrect network type.
1820 *
1821 * @return the preferred network type, defined in RILConstants.java.
1822 */
1823 @Override
1824 public int getCalculatedPreferredNetworkType() {
1825 enforceReadPermission();
Wink Saville08874612014-08-31 19:19:58 -07001826 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get PhoneId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07001827 }
1828
1829 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08001830 * Get the preferred network type.
1831 * Used for device configuration by some CDMA operators.
1832 *
1833 * @return the preferred network type, defined in RILConstants.java.
1834 */
1835 @Override
1836 public int getPreferredNetworkType() {
Junda Liua2e36012014-07-09 18:30:01 -07001837 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001838 if (DBG) log("getPreferredNetworkType");
1839 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
1840 int networkType = (result != null ? result[0] : -1);
1841 if (DBG) log("getPreferredNetworkType: " + networkType);
1842 return networkType;
1843 }
1844
1845 /**
1846 * Set the preferred network type.
1847 * Used for device configuration by some CDMA operators.
1848 *
1849 * @param networkType the preferred network type, defined in RILConstants.java.
1850 * @return true on success; false on any failure.
1851 */
1852 @Override
1853 public boolean setPreferredNetworkType(int networkType) {
Junda Liua2e36012014-07-09 18:30:01 -07001854 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001855 if (DBG) log("setPreferredNetworkType: type " + networkType);
1856 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
1857 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07001858 if (success) {
1859 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
1860 Settings.Global.PREFERRED_NETWORK_MODE, networkType);
1861 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001862 return success;
1863 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001864
1865 /**
1866 * Set mobile data enabled
1867 * Used by the user through settings etc to turn on/off mobile data
1868 *
1869 * @param enable {@code true} turn turn data on, else {@code false}
1870 */
1871 @Override
1872 public void setDataEnabled(boolean enable) {
1873 enforceModifyPermission();
1874 mPhone.setDataEnabled(enable);
1875 }
1876
1877 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07001878 * Get whether mobile data is enabled.
1879 *
1880 * Note that this used to be available from ConnectivityService, gated by
1881 * ACCESS_NETWORK_STATE permission, so this will accept either that or
1882 * our MODIFY_PHONE_STATE.
Robert Greenwalted86e582014-05-21 20:03:20 -07001883 *
1884 * @return {@code true} if data is enabled else {@code false}
1885 */
1886 @Override
1887 public boolean getDataEnabled() {
Robert Greenwalt646120a2014-05-23 11:54:03 -07001888 try {
1889 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1890 null);
1891 } catch (Exception e) {
1892 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1893 null);
1894 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001895 return mPhone.getDataEnabled();
1896 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001897
1898 @Override
1899 public int hasCarrierPrivileges() {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001900 UiccCard card = UiccController.getInstance().getUiccCard();
1901 if (card == null) {
1902 loge("hasCarrierPrivileges: No UICC");
1903 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1904 }
1905 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001906 mPhone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001907 }
Junda Liu29340342014-07-10 15:23:27 -07001908
1909 @Override
Shishir Agrawal6d5a2852014-07-11 16:32:57 -07001910 public int checkCarrierPrivilegesForPackage(String pkgname) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001911 UiccCard card = UiccController.getInstance().getUiccCard();
1912 if (card == null) {
1913 loge("checkCarrierPrivilegesForPackage: No UICC");
1914 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1915 }
1916 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
Junda Liu29340342014-07-10 15:23:27 -07001917 }
Derek Tan89e89d42014-07-08 17:00:10 -07001918
1919 @Override
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001920 public List<String> getCarrierPackageNamesForIntent(Intent intent) {
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001921 UiccCard card = UiccController.getInstance().getUiccCard();
1922 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001923 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001924 return null ;
1925 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001926 return card.getCarrierPackageNamesForIntent(
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001927 mPhone.getContext().getPackageManager(), intent);
1928 }
1929
Derek Tan97ebb422014-09-05 16:55:38 -07001930 private String getIccId(long subId) {
1931 UiccCard card = getPhone(subId).getUiccCard();
1932 if (card == null) {
1933 loge("getIccId: No UICC");
1934 return null;
1935 }
1936 String iccId = card.getIccId();
1937 if (TextUtils.isEmpty(iccId)) {
1938 loge("getIccId: ICC ID is null or empty.");
1939 return null;
1940 }
1941 return iccId;
1942 }
1943
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001944 @Override
Junda Liudf6b6b92014-09-05 18:13:46 -07001945 public void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable) {
Derek Tan352d8cd2014-07-12 12:57:11 -07001946 enforceModifyPermissionOrCarrierPrivilege();
Derek Tan97ebb422014-09-05 16:55:38 -07001947
1948 String iccId = getIccId(subId);
1949 if (iccId != null) {
1950 String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07001951 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
Derek Tan97ebb422014-09-05 16:55:38 -07001952 if (enable) {
1953 editor.putBoolean(snsPrefKey, true);
1954 } else {
1955 editor.remove(snsPrefKey);
1956 }
1957 editor.commit();
Derek Tan89e89d42014-07-08 17:00:10 -07001958 }
1959 }
1960
1961 @Override
Junda Liudf6b6b92014-09-05 18:13:46 -07001962 public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId) {
Derek Tan89e89d42014-07-08 17:00:10 -07001963 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07001964 String iccId = getIccId(subId);
1965 if (iccId != null) {
1966 String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07001967 return mTelephonySharedPreferences.getBoolean(snsPrefKey, false);
Derek Tan97ebb422014-09-05 16:55:38 -07001968 }
1969 return false;
Derek Tan89e89d42014-07-08 17:00:10 -07001970 }
Derek Tan7226c842014-07-02 17:42:23 -07001971
1972 @Override
Junda Liudf6b6b92014-09-05 18:13:46 -07001973 public void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number) {
Derek Tan352d8cd2014-07-12 12:57:11 -07001974 enforceModifyPermissionOrCarrierPrivilege();
Derek Tan97ebb422014-09-05 16:55:38 -07001975
1976 String iccId = getIccId(subId);
1977 if (iccId != null) {
1978 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07001979 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
Derek Tan97ebb422014-09-05 16:55:38 -07001980 if (alphaTag == null) {
1981 editor.remove(alphaTagPrefKey);
1982 } else {
1983 editor.putString(alphaTagPrefKey, alphaTag);
1984 }
1985
1986 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
1987 if (number == null) {
1988 editor.remove(numberPrefKey);
1989 } else {
1990 editor.putString(numberPrefKey, number);
1991 }
1992 editor.commit();
1993 }
Derek Tan7226c842014-07-02 17:42:23 -07001994 }
1995
1996 @Override
1997 public String getLine1NumberForDisplay(long subId) {
1998 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07001999
2000 String iccId = getIccId(subId);
2001 if (iccId != null) {
2002 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002003 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002004 }
Derek Tan97ebb422014-09-05 16:55:38 -07002005 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002006 }
2007
2008 @Override
2009 public String getLine1AlphaTagForDisplay(long subId) {
2010 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07002011
2012 String iccId = getIccId(subId);
2013 if (iccId != null) {
2014 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002015 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002016 }
Derek Tan97ebb422014-09-05 16:55:38 -07002017 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002018 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002019
2020 @Override
Shishir Agrawala3dfd752014-09-04 13:25:42 -07002021 public boolean setOperatorBrandOverride(String brand) {
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002022 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawala3dfd752014-09-04 13:25:42 -07002023 return mPhone.setOperatorBrandOverride(brand);
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002024 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002025
2026 @Override
2027 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2028 enforceModifyPermission();
2029
2030 int returnValue = 0;
2031 try {
2032 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2033 if(result.exception == null) {
2034 if (result.result != null) {
2035 byte[] responseData = (byte[])(result.result);
2036 if(responseData.length > oemResp.length) {
2037 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2038 responseData.length + "bytes. Buffer Size is " +
2039 oemResp.length + "bytes.");
2040 }
2041 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2042 returnValue = responseData.length;
2043 }
2044 } else {
2045 CommandException ex = (CommandException) result.exception;
2046 returnValue = ex.getCommandError().ordinal();
2047 if(returnValue > 0) returnValue *= -1;
2048 }
2049 } catch (RuntimeException e) {
2050 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2051 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2052 if(returnValue > 0) returnValue *= -1;
2053 }
2054
2055 return returnValue;
2056 }
Wink Saville5d475dd2014-10-17 15:00:58 -07002057
2058 @Override
2059 public void setRadioCapability(RadioAccessFamily[] rafs) {
2060 try {
2061 ProxyController.getInstance().setRadioCapability(rafs);
2062 } catch (RuntimeException e) {
2063 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
2064 }
2065 }
2066
2067 @Override
2068 public int getRadioAccessFamily(int phoneId) {
2069 return ProxyController.getInstance().getRadioAccessFamily(phoneId);
2070 }
Andrew Leedf14ead2014-10-17 14:22:52 -07002071
2072 @Override
2073 public void enableVideoCalling(boolean enable) {
2074 enforceModifyPermission();
2075 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2076 editor.putBoolean(PREF_ENABLE_VIDEO_CALLING, enable);
2077 editor.commit();
2078 }
2079
2080 @Override
2081 public boolean isVideoCallingEnabled() {
2082 enforceReadPermission();
2083 return mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true);
2084 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002085}