blob: 7366d44b6f22c2fa03c2ca3d7e5b16f5f12f0b61 [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 Saville0f3b5fc2014-11-11 08:40:49 -080050import android.telephony.SubscriptionInfo;
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
Andrew Lee312e8172014-10-23 17:01:36 -070056import com.android.ims.ImsManager;
Shishir Agrawal566b7612013-10-28 14:41:00 -070057import com.android.internal.telephony.CallManager;
58import com.android.internal.telephony.CommandException;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070059import com.android.internal.telephony.Connection;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070060import com.android.internal.telephony.DefaultPhoneNotifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070061import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -080062import com.android.internal.telephony.IccCard;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070063import com.android.internal.telephony.Phone;
Wink Saville36469e72014-06-11 15:17:00 -070064import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -070065import com.android.internal.telephony.PhoneProxy;
66import com.android.internal.telephony.ProxyController;
Wink Saville36469e72014-06-11 15:17:00 -070067import com.android.internal.telephony.CallManager;
68import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070069import com.android.internal.telephony.PhoneConstants;
Wink Saville08874612014-08-31 19:19:58 -070070import com.android.internal.telephony.TelephonyIntents;
Wink Saville36469e72014-06-11 15:17:00 -070071import com.android.internal.telephony.dataconnection.DctController;
Derek Tan7226c842014-07-02 17:42:23 -070072import com.android.internal.telephony.uicc.AdnRecord;
Shishir Agrawal566b7612013-10-28 14:41:00 -070073import com.android.internal.telephony.uicc.IccIoResult;
74import com.android.internal.telephony.uicc.IccUtils;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -070075import com.android.internal.telephony.uicc.UiccCard;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070076import com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
Shishir Agrawal566b7612013-10-28 14:41:00 -070077import com.android.internal.telephony.uicc.UiccController;
Jake Hambye994d462014-02-03 13:10:13 -080078import com.android.internal.util.HexDump;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070079
Wink Saville36469e72014-06-11 15:17:00 -070080import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
81
Santos Cordon7d4ddf62013-07-10 11:58:08 -070082import java.util.ArrayList;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070083import java.util.HashMap;
Derek Tan89e89d42014-07-08 17:00:10 -070084import java.util.HashSet;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070085import java.util.Iterator;
Jake Hambye994d462014-02-03 13:10:13 -080086import java.util.List;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070087import java.util.Map;
Derek Tan89e89d42014-07-08 17:00:10 -070088import java.util.Set;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070089
90/**
91 * Implementation of the ITelephony interface.
92 */
Santos Cordon117fee72014-05-16 17:56:12 -070093public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070094 private static final String LOG_TAG = "PhoneInterfaceManager";
95 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
96 private static final boolean DBG_LOC = false;
97
98 // Message codes used with mMainThreadHandler
99 private static final int CMD_HANDLE_PIN_MMI = 1;
100 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
101 private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
102 private static final int CMD_ANSWER_RINGING_CALL = 4;
103 private static final int CMD_END_CALL = 5; // not used yet
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700104 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
105 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700106 private static final int CMD_OPEN_CHANNEL = 9;
107 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
108 private static final int CMD_CLOSE_CHANNEL = 11;
109 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800110 private static final int CMD_NV_READ_ITEM = 13;
111 private static final int EVENT_NV_READ_ITEM_DONE = 14;
112 private static final int CMD_NV_WRITE_ITEM = 15;
113 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
114 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
115 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
116 private static final int CMD_NV_RESET_CONFIG = 19;
117 private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800118 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
119 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
120 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
121 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800122 private static final int CMD_SEND_ENVELOPE = 25;
123 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Derek Tan6b088ee2014-09-05 14:15:18 -0700124 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
125 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
126 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
127 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
128 private static final int CMD_EXCHANGE_SIM_IO = 31;
129 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800130 private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
131 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700132
133 /** The singleton instance. */
134 private static PhoneInterfaceManager sInstance;
135
Wink Saville3ab207e2014-11-20 13:07:20 -0800136 private PhoneGlobals mApp;
137 private Phone mPhone;
138 private CallManager mCM;
139 private AppOpsManager mAppOps;
140 private MainThreadHandler mMainThreadHandler;
141 private SubscriptionManager mSubscriptionManager;
142 private SharedPreferences mTelephonySharedPreferences;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700143
Derek Tan97ebb422014-09-05 16:55:38 -0700144 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
145 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
Andrew Leedf14ead2014-10-17 14:22:52 -0700146 private static final String PREF_ENABLE_VIDEO_CALLING = "enable_video_calling";
Derek Tan89e89d42014-07-08 17:00:10 -0700147
148 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700149 * A request object to use for transmitting data to an ICC.
150 */
151 private static final class IccAPDUArgument {
152 public int channel, cla, command, p1, p2, p3;
153 public String data;
154
155 public IccAPDUArgument(int channel, int cla, int command,
156 int p1, int p2, int p3, String data) {
157 this.channel = channel;
158 this.cla = cla;
159 this.command = command;
160 this.p1 = p1;
161 this.p2 = p2;
162 this.p3 = p3;
163 this.data = data;
164 }
165 }
166
167 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700168 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
169 * request after sending. The main thread will notify the request when it is complete.
170 */
171 private static final class MainThreadRequest {
172 /** The argument to use for the request */
173 public Object argument;
174 /** The result of the request that is run on the main thread */
175 public Object result;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800176 /** The subscriber id that this request applies to. Null if default. */
177 public Integer subId;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700178
179 public MainThreadRequest(Object argument) {
180 this.argument = argument;
181 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800182
183 public MainThreadRequest(Object argument, Integer subId) {
184 this.argument = argument;
185 this.subId = subId;
186 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700187 }
188
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800189 private static final class IncomingThirdPartyCallArgs {
190 public final ComponentName component;
191 public final String callId;
192 public final String callerDisplayName;
193
194 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
195 String callerDisplayName) {
196 this.component = component;
197 this.callId = callId;
198 this.callerDisplayName = callerDisplayName;
199 }
200 }
201
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700202 /**
203 * A handler that processes messages on the main thread in the phone process. Since many
204 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
205 * inbound binder threads to the main thread in the phone process. The Binder thread
206 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
207 * on, which will be notified when the operation completes and will contain the result of the
208 * request.
209 *
210 * <p>If a MainThreadRequest object is provided in the msg.obj field,
211 * note that request.result must be set to something non-null for the calling thread to
212 * unblock.
213 */
214 private final class MainThreadHandler extends Handler {
215 @Override
216 public void handleMessage(Message msg) {
217 MainThreadRequest request;
218 Message onCompleted;
219 AsyncResult ar;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700220 UiccCard uiccCard = UiccController.getInstance().getUiccCard();
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700221 IccAPDUArgument iccArgument;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700222
223 switch (msg.what) {
224 case CMD_HANDLE_PIN_MMI:
225 request = (MainThreadRequest) msg.obj;
Jake Hambye994d462014-02-03 13:10:13 -0800226 request.result = mPhone.handlePinMmi((String) request.argument);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700227 // Wake up the requesting thread
228 synchronized (request) {
229 request.notifyAll();
230 }
231 break;
232
233 case CMD_HANDLE_NEIGHBORING_CELL:
234 request = (MainThreadRequest) msg.obj;
235 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
236 request);
237 mPhone.getNeighboringCids(onCompleted);
238 break;
239
240 case EVENT_NEIGHBORING_CELL_DONE:
241 ar = (AsyncResult) msg.obj;
242 request = (MainThreadRequest) ar.userObj;
243 if (ar.exception == null && ar.result != null) {
244 request.result = ar.result;
245 } else {
246 // create an empty list to notify the waiting thread
Jake Hambye994d462014-02-03 13:10:13 -0800247 request.result = new ArrayList<NeighboringCellInfo>(0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700248 }
249 // Wake up the requesting thread
250 synchronized (request) {
251 request.notifyAll();
252 }
253 break;
254
255 case CMD_ANSWER_RINGING_CALL:
Wink Saville08874612014-08-31 19:19:58 -0700256 request = (MainThreadRequest) msg.obj;
Wink Savilleb564aae2014-10-23 10:18:09 -0700257 int answer_subId = ((Integer)request.argument).intValue();
Wink Saville08874612014-08-31 19:19:58 -0700258 answerRingingCallInternal(answer_subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700259 break;
260
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700261 case CMD_END_CALL:
262 request = (MainThreadRequest) msg.obj;
Wink Savilleb564aae2014-10-23 10:18:09 -0700263 int end_subId = ((Integer)request.argument).intValue();
Wink Saville08874612014-08-31 19:19:58 -0700264 final boolean hungUp;
265 int phoneType = getPhone(end_subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700266 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
267 // CDMA: If the user presses the Power button we treat it as
268 // ending the complete call session
Wink Saville08874612014-08-31 19:19:58 -0700269 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700270 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
271 // GSM: End the call as per the Phone state
272 hungUp = PhoneUtils.hangup(mCM);
273 } else {
274 throw new IllegalStateException("Unexpected phone type: " + phoneType);
275 }
276 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
277 request.result = hungUp;
278 // Wake up the requesting thread
279 synchronized (request) {
280 request.notifyAll();
281 }
282 break;
283
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700284 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700285 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700286 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700287 if (uiccCard == null) {
288 loge("iccTransmitApduLogicalChannel: No UICC");
289 request.result = new IccIoResult(0x6F, 0, (byte[])null);
290 synchronized (request) {
291 request.notifyAll();
292 }
293 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700294 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
295 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700296 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700297 iccArgument.channel, iccArgument.cla, iccArgument.command,
298 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700299 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700300 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700301 break;
302
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700303 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700304 ar = (AsyncResult) msg.obj;
305 request = (MainThreadRequest) ar.userObj;
306 if (ar.exception == null && ar.result != null) {
307 request.result = ar.result;
308 } else {
309 request.result = new IccIoResult(0x6F, 0, (byte[])null);
310 if (ar.result == null) {
311 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800312 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700313 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800314 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700315 } else {
316 loge("iccTransmitApduLogicalChannel: Unknown exception");
317 }
318 }
319 synchronized (request) {
320 request.notifyAll();
321 }
322 break;
323
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700324 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
325 request = (MainThreadRequest) msg.obj;
326 iccArgument = (IccAPDUArgument) request.argument;
327 if (uiccCard == null) {
328 loge("iccTransmitApduBasicChannel: No UICC");
329 request.result = new IccIoResult(0x6F, 0, (byte[])null);
330 synchronized (request) {
331 request.notifyAll();
332 }
333 } else {
334 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
335 request);
336 uiccCard.iccTransmitApduBasicChannel(
337 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
338 iccArgument.p3, iccArgument.data, onCompleted);
339 }
340 break;
341
342 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
343 ar = (AsyncResult) msg.obj;
344 request = (MainThreadRequest) ar.userObj;
345 if (ar.exception == null && ar.result != null) {
346 request.result = ar.result;
347 } else {
348 request.result = new IccIoResult(0x6F, 0, (byte[])null);
349 if (ar.result == null) {
350 loge("iccTransmitApduBasicChannel: Empty response");
351 } else if (ar.exception instanceof CommandException) {
352 loge("iccTransmitApduBasicChannel: CommandException: " +
353 ar.exception);
354 } else {
355 loge("iccTransmitApduBasicChannel: Unknown exception");
356 }
357 }
358 synchronized (request) {
359 request.notifyAll();
360 }
361 break;
362
363 case CMD_EXCHANGE_SIM_IO:
364 request = (MainThreadRequest) msg.obj;
365 iccArgument = (IccAPDUArgument) request.argument;
366 if (uiccCard == null) {
367 loge("iccExchangeSimIO: No UICC");
368 request.result = new IccIoResult(0x6F, 0, (byte[])null);
369 synchronized (request) {
370 request.notifyAll();
371 }
372 } else {
373 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
374 request);
375 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
376 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
377 iccArgument.data, onCompleted);
378 }
379 break;
380
381 case EVENT_EXCHANGE_SIM_IO_DONE:
382 ar = (AsyncResult) msg.obj;
383 request = (MainThreadRequest) ar.userObj;
384 if (ar.exception == null && ar.result != null) {
385 request.result = ar.result;
386 } else {
387 request.result = new IccIoResult(0x6f, 0, (byte[])null);
388 }
389 synchronized (request) {
390 request.notifyAll();
391 }
392 break;
393
Derek Tan4d5e5c12014-02-04 11:54:58 -0800394 case CMD_SEND_ENVELOPE:
395 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700396 if (uiccCard == null) {
397 loge("sendEnvelopeWithStatus: No UICC");
398 request.result = new IccIoResult(0x6F, 0, (byte[])null);
399 synchronized (request) {
400 request.notifyAll();
401 }
402 } else {
403 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
404 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
405 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800406 break;
407
408 case EVENT_SEND_ENVELOPE_DONE:
409 ar = (AsyncResult) msg.obj;
410 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700411 if (ar.exception == null && ar.result != null) {
412 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800413 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700414 request.result = new IccIoResult(0x6F, 0, (byte[])null);
415 if (ar.result == null) {
416 loge("sendEnvelopeWithStatus: Empty response");
417 } else if (ar.exception instanceof CommandException) {
418 loge("sendEnvelopeWithStatus: CommandException: " +
419 ar.exception);
420 } else {
421 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
422 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800423 }
424 synchronized (request) {
425 request.notifyAll();
426 }
427 break;
428
Shishir Agrawal566b7612013-10-28 14:41:00 -0700429 case CMD_OPEN_CHANNEL:
430 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700431 if (uiccCard == null) {
432 loge("iccOpenLogicalChannel: No UICC");
433 request.result = new IccIoResult(0x6F, 0, (byte[])null);
434 synchronized (request) {
435 request.notifyAll();
436 }
437 } else {
438 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
439 uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
440 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700441 break;
442
443 case EVENT_OPEN_CHANNEL_DONE:
444 ar = (AsyncResult) msg.obj;
445 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700446 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700447 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700448 int[] result = (int[]) ar.result;
449 int channelId = result[0];
450 byte[] selectResponse = null;
451 if (result.length > 1) {
452 selectResponse = new byte[result.length - 1];
453 for (int i = 1; i < result.length; ++i) {
454 selectResponse[i - 1] = (byte) result[i];
455 }
456 }
457 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700458 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700459 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700460 if (ar.result == null) {
461 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700462 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700463 if (ar.exception != null) {
464 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
465 }
466
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700467 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700468 if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
469 if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700470 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700471 } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700472 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700473 }
474 }
475 openChannelResp = new IccOpenLogicalChannelResponse(
476 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700477 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700478 request.result = openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700479 synchronized (request) {
480 request.notifyAll();
481 }
482 break;
483
484 case CMD_CLOSE_CHANNEL:
485 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700486 if (uiccCard == null) {
487 loge("iccCloseLogicalChannel: No UICC");
488 request.result = new IccIoResult(0x6F, 0, (byte[])null);
489 synchronized (request) {
490 request.notifyAll();
491 }
492 } else {
493 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
494 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
495 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700496 break;
497
498 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800499 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
500 break;
501
502 case CMD_NV_READ_ITEM:
503 request = (MainThreadRequest) msg.obj;
504 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
505 mPhone.nvReadItem((Integer) request.argument, onCompleted);
506 break;
507
508 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700509 ar = (AsyncResult) msg.obj;
510 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800511 if (ar.exception == null && ar.result != null) {
512 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700513 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800514 request.result = "";
515 if (ar.result == null) {
516 loge("nvReadItem: Empty response");
517 } else if (ar.exception instanceof CommandException) {
518 loge("nvReadItem: CommandException: " +
519 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700520 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800521 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700522 }
523 }
524 synchronized (request) {
525 request.notifyAll();
526 }
527 break;
528
Jake Hambye994d462014-02-03 13:10:13 -0800529 case CMD_NV_WRITE_ITEM:
530 request = (MainThreadRequest) msg.obj;
531 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
532 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
533 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
534 break;
535
536 case EVENT_NV_WRITE_ITEM_DONE:
537 handleNullReturnEvent(msg, "nvWriteItem");
538 break;
539
540 case CMD_NV_WRITE_CDMA_PRL:
541 request = (MainThreadRequest) msg.obj;
542 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
543 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
544 break;
545
546 case EVENT_NV_WRITE_CDMA_PRL_DONE:
547 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
548 break;
549
550 case CMD_NV_RESET_CONFIG:
551 request = (MainThreadRequest) msg.obj;
552 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
553 mPhone.nvResetConfig((Integer) request.argument, onCompleted);
554 break;
555
556 case EVENT_NV_RESET_CONFIG_DONE:
557 handleNullReturnEvent(msg, "nvResetConfig");
558 break;
559
Jake Hamby7c27be32014-03-03 13:25:59 -0800560 case CMD_GET_PREFERRED_NETWORK_TYPE:
561 request = (MainThreadRequest) msg.obj;
562 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
563 mPhone.getPreferredNetworkType(onCompleted);
564 break;
565
566 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
567 ar = (AsyncResult) msg.obj;
568 request = (MainThreadRequest) ar.userObj;
569 if (ar.exception == null && ar.result != null) {
570 request.result = ar.result; // Integer
571 } else {
572 request.result = -1;
573 if (ar.result == null) {
574 loge("getPreferredNetworkType: Empty response");
575 } else if (ar.exception instanceof CommandException) {
576 loge("getPreferredNetworkType: CommandException: " +
577 ar.exception);
578 } else {
579 loge("getPreferredNetworkType: Unknown exception");
580 }
581 }
582 synchronized (request) {
583 request.notifyAll();
584 }
585 break;
586
587 case CMD_SET_PREFERRED_NETWORK_TYPE:
588 request = (MainThreadRequest) msg.obj;
589 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
590 int networkType = (Integer) request.argument;
591 mPhone.setPreferredNetworkType(networkType, onCompleted);
592 break;
593
594 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
595 handleNullReturnEvent(msg, "setPreferredNetworkType");
596 break;
597
Steven Liu4bf01bc2014-07-17 11:05:29 -0500598 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
599 request = (MainThreadRequest)msg.obj;
600 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
601 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
602 break;
603
604 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
605 ar = (AsyncResult)msg.obj;
606 request = (MainThreadRequest)ar.userObj;
607 request.result = ar;
608 synchronized (request) {
609 request.notifyAll();
610 }
611 break;
612
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800613 case CMD_SET_VOICEMAIL_NUMBER:
614 request = (MainThreadRequest) msg.obj;
615 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
616 Pair<String, String> tagNum = (Pair<String, String>) request.argument;
617 Phone phone = (request.subId == null) ? mPhone : getPhone(request.subId);
618 phone.setVoiceMailNumber(tagNum.first, tagNum.second, onCompleted);
619 break;
620
621 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
622 handleNullReturnEvent(msg, "setVoicemailNumber");
623 break;
624
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700625 default:
626 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
627 break;
628 }
629 }
Jake Hambye994d462014-02-03 13:10:13 -0800630
631 private void handleNullReturnEvent(Message msg, String command) {
632 AsyncResult ar = (AsyncResult) msg.obj;
633 MainThreadRequest request = (MainThreadRequest) ar.userObj;
634 if (ar.exception == null) {
635 request.result = true;
636 } else {
637 request.result = false;
638 if (ar.exception instanceof CommandException) {
639 loge(command + ": CommandException: " + ar.exception);
640 } else {
641 loge(command + ": Unknown exception");
642 }
643 }
644 synchronized (request) {
645 request.notifyAll();
646 }
647 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700648 }
649
650 /**
651 * Posts the specified command to be executed on the main thread,
652 * waits for the request to complete, and returns the result.
653 * @see #sendRequestAsync
654 */
655 private Object sendRequest(int command, Object argument) {
Santos Cordon500b0e02014-06-17 10:33:33 -0700656 return sendRequest(command, argument, null);
Wink Saville36469e72014-06-11 15:17:00 -0700657 }
658
659 /**
660 * Posts the specified command to be executed on the main thread,
661 * waits for the request to complete, and returns the result.
662 * @see #sendRequestAsync
663 */
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800664 private Object sendRequest(int command, Object argument, Integer subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700665 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
666 throw new RuntimeException("This method will deadlock if called from the main thread.");
667 }
668
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800669 MainThreadRequest request = new MainThreadRequest(argument, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700670 Message msg = mMainThreadHandler.obtainMessage(command, request);
671 msg.sendToTarget();
672
673 // Wait for the request to complete
674 synchronized (request) {
675 while (request.result == null) {
676 try {
677 request.wait();
678 } catch (InterruptedException e) {
679 // Do nothing, go back and wait until the request is complete
680 }
681 }
682 }
683 return request.result;
684 }
685
686 /**
687 * Asynchronous ("fire and forget") version of sendRequest():
688 * Posts the specified command to be executed on the main thread, and
689 * returns immediately.
690 * @see #sendRequest
691 */
692 private void sendRequestAsync(int command) {
693 mMainThreadHandler.sendEmptyMessage(command);
694 }
695
696 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -0700697 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
698 * @see {@link #sendRequest(int,Object)}
699 */
700 private void sendRequestAsync(int command, Object argument) {
701 MainThreadRequest request = new MainThreadRequest(argument);
702 Message msg = mMainThreadHandler.obtainMessage(command, request);
703 msg.sendToTarget();
704 }
705
706 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700707 * Initialize the singleton PhoneInterfaceManager instance.
708 * This is only done once, at startup, from PhoneApp.onCreate().
709 */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700710 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700711 synchronized (PhoneInterfaceManager.class) {
712 if (sInstance == null) {
Sailesh Nepal194161e2014-07-03 08:57:44 -0700713 sInstance = new PhoneInterfaceManager(app, phone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700714 } else {
715 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
716 }
717 return sInstance;
718 }
719 }
720
721 /** Private constructor; @see init() */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700722 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700723 mApp = app;
724 mPhone = phone;
725 mCM = PhoneGlobals.getInstance().mCM;
726 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
727 mMainThreadHandler = new MainThreadHandler();
Andrew Leedf14ead2014-10-17 14:22:52 -0700728 mTelephonySharedPreferences =
Derek Tan97ebb422014-09-05 16:55:38 -0700729 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
Wink Saville3ab207e2014-11-20 13:07:20 -0800730 mSubscriptionManager = SubscriptionManager.from(app);
731
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700732 publish();
733 }
734
735 private void publish() {
736 if (DBG) log("publish: " + this);
737
738 ServiceManager.addService("phone", this);
739 }
740
Wink Saville36469e72014-06-11 15:17:00 -0700741 // returns phone associated with the subId.
Wink Savilleb564aae2014-10-23 10:18:09 -0700742 private Phone getPhone(int subId) {
Legler Wuf8733b42014-09-25 11:00:54 +0800743 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -0700744 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700745 //
746 // Implementation of the ITelephony interface.
747 //
748
749 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700750 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -0700751 }
752
Wink Savilleb564aae2014-10-23 10:18:09 -0700753 public void dialForSubscriber(int subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700754 if (DBG) log("dial: " + number);
755 // No permission check needed here: This is just a wrapper around the
756 // ACTION_DIAL intent, which is available to any app since it puts up
757 // the UI before it does anything.
758
759 String url = createTelUrl(number);
760 if (url == null) {
761 return;
762 }
763
764 // PENDING: should we just silently fail if phone is offhook or ringing?
Wink Saville36469e72014-06-11 15:17:00 -0700765 PhoneConstants.State state = mCM.getState(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700766 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
767 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
768 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
769 mApp.startActivity(intent);
770 }
771 }
772
773 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700774 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -0700775 }
776
Wink Savilleb564aae2014-10-23 10:18:09 -0700777 public void callForSubscriber(int subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700778 if (DBG) log("call: " + number);
779
780 // This is just a wrapper around the ACTION_CALL intent, but we still
781 // need to do a permission check since we're calling startActivity()
782 // from the context of the phone app.
783 enforceCallPermission();
784
785 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
786 != AppOpsManager.MODE_ALLOWED) {
787 return;
788 }
789
790 String url = createTelUrl(number);
791 if (url == null) {
792 return;
793 }
794
Wink Saville08874612014-08-31 19:19:58 -0700795 boolean isValid = false;
Wink Saville3ab207e2014-11-20 13:07:20 -0800796 List<SubscriptionInfo> slist = mSubscriptionManager.getActiveSubscriptionInfoList();
797 if (slist != null) {
798 for (SubscriptionInfo subInfoRecord : slist) {
799 if (subInfoRecord.getSubscriptionId() == subId) {
800 isValid = true;
801 break;
802 }
Wink Saville08874612014-08-31 19:19:58 -0700803 }
804 }
805 if (isValid == false) {
806 return;
807 }
808
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700809 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
Wink Saville36469e72014-06-11 15:17:00 -0700810 intent.putExtra(SUBSCRIPTION_KEY, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700811 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
812 mApp.startActivity(intent);
813 }
814
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700815 /**
816 * End a call based on call state
817 * @return true is a call was ended
818 */
819 public boolean endCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700820 return endCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700821 }
822
823 /**
824 * End a call based on the call state of the subId
825 * @return true is a call was ended
826 */
Wink Savilleb564aae2014-10-23 10:18:09 -0700827 public boolean endCallForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700828 enforceCallPermission();
Wink Saville9f73bda2014-11-05 08:13:36 -0800829 return (Boolean) sendRequest(CMD_END_CALL, new Integer(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700830 }
831
832 public void answerRingingCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700833 answerRingingCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700834 }
835
Wink Savilleb564aae2014-10-23 10:18:09 -0700836 public void answerRingingCallForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700837 if (DBG) log("answerRingingCall...");
838 // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
839 // but that can probably wait till the big TelephonyManager API overhaul.
840 // For now, protect this call with the MODIFY_PHONE_STATE permission.
841 enforceModifyPermission();
Wink Saville9f73bda2014-11-05 08:13:36 -0800842 sendRequest(CMD_ANSWER_RINGING_CALL, new Integer(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700843 }
844
845 /**
846 * Make the actual telephony calls to implement answerRingingCall().
847 * This should only be called from the main thread of the Phone app.
848 * @see #answerRingingCall
849 *
850 * TODO: it would be nice to return true if we answered the call, or
851 * false if there wasn't actually a ringing incoming call, or some
852 * other error occurred. (In other words, pass back the return value
853 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
854 * But that would require calling this method via sendRequest() rather
855 * than sendRequestAsync(), and right now we don't actually *need* that
856 * return value, so let's just return void for now.
857 */
Wink Savilleb564aae2014-10-23 10:18:09 -0700858 private void answerRingingCallInternal(int subId) {
Wink Saville08874612014-08-31 19:19:58 -0700859 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700860 if (hasRingingCall) {
Wink Saville08874612014-08-31 19:19:58 -0700861 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
862 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700863 if (hasActiveCall && hasHoldingCall) {
864 // Both lines are in use!
865 // TODO: provide a flag to let the caller specify what
866 // policy to use if both lines are in use. (The current
867 // behavior is hardwired to "answer incoming, end ongoing",
868 // which is how the CALL button is specced to behave.)
869 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
870 return;
871 } else {
872 // answerCall() will automatically hold the current active
873 // call, if there is one.
874 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
875 return;
876 }
877 } else {
878 // No call was ringing.
879 return;
880 }
881 }
882
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700883 /**
Santos Cordon5422a8d2014-09-12 04:20:56 -0700884 * This method is no longer used and can be removed once TelephonyManager stops referring to it.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700885 */
Santos Cordon5422a8d2014-09-12 04:20:56 -0700886 public void silenceRinger() {
887 Log.e(LOG_TAG, "silenseRinger not supported");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700888 }
889
890 public boolean isOffhook() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700891 return isOffhookForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700892 }
893
Wink Savilleb564aae2014-10-23 10:18:09 -0700894 public boolean isOffhookForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700895 return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700896 }
897
898 public boolean isRinging() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700899 return (isRingingForSubscriber(getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -0700900 }
901
Wink Savilleb564aae2014-10-23 10:18:09 -0700902 public boolean isRingingForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700903 return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700904 }
905
906 public boolean isIdle() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700907 return isIdleForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700908 }
909
Wink Savilleb564aae2014-10-23 10:18:09 -0700910 public boolean isIdleForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700911 return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700912 }
913
914 public boolean isSimPinEnabled() {
915 enforceReadPermission();
916 return (PhoneGlobals.getInstance().isSimPinEnabled());
917 }
918
919 public boolean supplyPin(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700920 return supplyPinForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -0700921 }
922
Wink Savilleb564aae2014-10-23 10:18:09 -0700923 public boolean supplyPinForSubscriber(int subId, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700924 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700925 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
926 }
927
928 public boolean supplyPuk(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700929 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -0700930 }
931
Wink Savilleb564aae2014-10-23 10:18:09 -0700932 public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700933 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700934 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
935 }
936
937 /** {@hide} */
938 public int[] supplyPinReportResult(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700939 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -0700940 }
941
Wink Savilleb564aae2014-10-23 10:18:09 -0700942 public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700943 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700944 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700945 checkSimPin.start();
946 return checkSimPin.unlockSim(null, pin);
947 }
948
Wink Saville9de0f752013-10-22 19:04:03 -0700949 /** {@hide} */
950 public int[] supplyPukReportResult(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700951 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -0700952 }
953
Wink Savilleb564aae2014-10-23 10:18:09 -0700954 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700955 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700956 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700957 checkSimPuk.start();
958 return checkSimPuk.unlockSim(puk, pin);
959 }
960
961 /**
Wink Saville9de0f752013-10-22 19:04:03 -0700962 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700963 * a synchronous one.
964 */
965 private static class UnlockSim extends Thread {
966
967 private final IccCard mSimCard;
968
969 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -0700970 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
971 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700972
973 // For replies from SimCard interface
974 private Handler mHandler;
975
976 // For async handler to identify request type
977 private static final int SUPPLY_PIN_COMPLETE = 100;
978
979 public UnlockSim(IccCard simCard) {
980 mSimCard = simCard;
981 }
982
983 @Override
984 public void run() {
985 Looper.prepare();
986 synchronized (UnlockSim.this) {
987 mHandler = new Handler() {
988 @Override
989 public void handleMessage(Message msg) {
990 AsyncResult ar = (AsyncResult) msg.obj;
991 switch (msg.what) {
992 case SUPPLY_PIN_COMPLETE:
993 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
994 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -0700995 mRetryCount = msg.arg1;
996 if (ar.exception != null) {
997 if (ar.exception instanceof CommandException &&
998 ((CommandException)(ar.exception)).getCommandError()
999 == CommandException.Error.PASSWORD_INCORRECT) {
1000 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1001 } else {
1002 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1003 }
1004 } else {
1005 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1006 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001007 mDone = true;
1008 UnlockSim.this.notifyAll();
1009 }
1010 break;
1011 }
1012 }
1013 };
1014 UnlockSim.this.notifyAll();
1015 }
1016 Looper.loop();
1017 }
1018
1019 /*
1020 * Use PIN or PUK to unlock SIM card
1021 *
1022 * If PUK is null, unlock SIM card with PIN
1023 *
1024 * If PUK is not null, unlock SIM card with PUK and set PIN code
1025 */
Wink Saville9de0f752013-10-22 19:04:03 -07001026 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001027
1028 while (mHandler == null) {
1029 try {
1030 wait();
1031 } catch (InterruptedException e) {
1032 Thread.currentThread().interrupt();
1033 }
1034 }
1035 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1036
1037 if (puk == null) {
1038 mSimCard.supplyPin(pin, callback);
1039 } else {
1040 mSimCard.supplyPuk(puk, pin, callback);
1041 }
1042
1043 while (!mDone) {
1044 try {
1045 Log.d(LOG_TAG, "wait for done");
1046 wait();
1047 } catch (InterruptedException e) {
1048 // Restore the interrupted status
1049 Thread.currentThread().interrupt();
1050 }
1051 }
1052 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001053 int[] resultArray = new int[2];
1054 resultArray[0] = mResult;
1055 resultArray[1] = mRetryCount;
1056 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001057 }
1058 }
1059
1060 public void updateServiceLocation() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001061 updateServiceLocationForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001062
1063 }
1064
Wink Savilleb564aae2014-10-23 10:18:09 -07001065 public void updateServiceLocationForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001066 // No permission check needed here: this call is harmless, and it's
1067 // needed for the ServiceState.requestStateUpdate() call (which is
1068 // already intentionally exposed to 3rd parties.)
Wink Saville36469e72014-06-11 15:17:00 -07001069 getPhone(subId).updateServiceLocation();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001070 }
1071
1072 public boolean isRadioOn() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001073 return isRadioOnForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001074 }
1075
Wink Savilleb564aae2014-10-23 10:18:09 -07001076 public boolean isRadioOnForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001077 return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001078 }
1079
1080 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001081 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001082
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001083 }
Wink Saville36469e72014-06-11 15:17:00 -07001084
Wink Savilleb564aae2014-10-23 10:18:09 -07001085 public void toggleRadioOnOffForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001086 enforceModifyPermission();
Wink Savilleadd7cc52014-09-08 14:23:09 -07001087 getPhone(subId).setRadioPower(!isRadioOnForSubscriber(subId));
Wink Saville36469e72014-06-11 15:17:00 -07001088 }
1089
1090 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001091 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001092 }
1093
Wink Savilleb564aae2014-10-23 10:18:09 -07001094 public boolean setRadioForSubscriber(int subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001095 enforceModifyPermission();
1096 if ((getPhone(subId).getServiceState().getState() !=
1097 ServiceState.STATE_POWER_OFF) != turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001098 toggleRadioOnOffForSubscriber(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001099 }
1100 return true;
1101 }
Wink Saville36469e72014-06-11 15:17:00 -07001102
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001103 public boolean needMobileRadioShutdown() {
1104 /*
1105 * If any of the Radios are available, it will need to be
1106 * shutdown. So return true if any Radio is available.
1107 */
1108 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1109 Phone phone = PhoneFactory.getPhone(i);
1110 if (phone != null && phone.isRadioAvailable()) return true;
1111 }
1112 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1113 return false;
1114 }
1115
1116 public void shutdownMobileRadios() {
1117 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1118 logv("Shutting down Phone " + i);
1119 shutdownRadioUsingPhoneId(i);
1120 }
1121 }
1122
1123 private void shutdownRadioUsingPhoneId(int phoneId) {
1124 enforceModifyPermission();
1125 Phone phone = PhoneFactory.getPhone(phoneId);
1126 if (phone != null && phone.isRadioAvailable()) {
1127 phone.shutdownRadio();
1128 }
1129 }
1130
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001131 public boolean setRadioPower(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001132 return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001133 }
1134
Wink Savilleb564aae2014-10-23 10:18:09 -07001135 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001136 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001137 getPhone(subId).setRadioPower(turnOn);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001138 return true;
1139 }
1140
Wink Saville36469e72014-06-11 15:17:00 -07001141 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001142 public boolean enableDataConnectivity() {
1143 enforceModifyPermission();
Wink Savilleb564aae2014-10-23 10:18:09 -07001144 int subId = SubscriptionManager.getDefaultDataSubId();
Wink Saville36469e72014-06-11 15:17:00 -07001145 getPhone(subId).setDataEnabled(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001146 return true;
1147 }
1148
Wink Saville36469e72014-06-11 15:17:00 -07001149 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001150 public boolean disableDataConnectivity() {
1151 enforceModifyPermission();
Wink Savilleb564aae2014-10-23 10:18:09 -07001152 int subId = SubscriptionManager.getDefaultDataSubId();
Wink Saville36469e72014-06-11 15:17:00 -07001153 getPhone(subId).setDataEnabled(false);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001154 return true;
1155 }
1156
Wink Saville36469e72014-06-11 15:17:00 -07001157 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001158 public boolean isDataConnectivityPossible() {
Wink Savilleb564aae2014-10-23 10:18:09 -07001159 int subId = SubscriptionManager.getDefaultDataSubId();
Wink Saville36469e72014-06-11 15:17:00 -07001160 return getPhone(subId).isDataConnectivityPossible();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001161 }
1162
1163 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001164 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07001165 }
1166
Wink Savilleb564aae2014-10-23 10:18:09 -07001167 public boolean handlePinMmiForSubscriber(int subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001168 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001169 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001170 }
1171
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001172 public int getCallState() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001173 return getCallStateForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001174 }
1175
Wink Savilleb564aae2014-10-23 10:18:09 -07001176 public int getCallStateForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001177 return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001178 }
1179
1180 public int getDataState() {
Wink Saville36469e72014-06-11 15:17:00 -07001181 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1182 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001183 }
1184
1185 public int getDataActivity() {
Wink Saville36469e72014-06-11 15:17:00 -07001186 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1187 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001188 }
1189
1190 @Override
1191 public Bundle getCellLocation() {
1192 try {
1193 mApp.enforceCallingOrSelfPermission(
1194 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1195 } catch (SecurityException e) {
1196 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1197 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1198 // is the weaker precondition
1199 mApp.enforceCallingOrSelfPermission(
1200 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1201 }
1202
Jake Hambye994d462014-02-03 13:10:13 -08001203 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001204 if (DBG_LOC) log("getCellLocation: is active user");
1205 Bundle data = new Bundle();
1206 mPhone.getCellLocation().fillInNotifierBundle(data);
1207 return data;
1208 } else {
1209 if (DBG_LOC) log("getCellLocation: suppress non-active user");
1210 return null;
1211 }
1212 }
1213
1214 @Override
1215 public void enableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001216 enableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001217 }
1218
Wink Savilleb564aae2014-10-23 10:18:09 -07001219 public void enableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001220 mApp.enforceCallingOrSelfPermission(
1221 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001222 getPhone(subId).enableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001223 }
1224
1225 @Override
1226 public void disableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001227 disableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001228 }
1229
Wink Savilleb564aae2014-10-23 10:18:09 -07001230 public void disableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001231 mApp.enforceCallingOrSelfPermission(
1232 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001233 getPhone(subId).disableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001234 }
1235
1236 @Override
1237 @SuppressWarnings("unchecked")
1238 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1239 try {
1240 mApp.enforceCallingOrSelfPermission(
1241 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1242 } catch (SecurityException e) {
1243 // If we have ACCESS_FINE_LOCATION permission, skip the check
1244 // for ACCESS_COARSE_LOCATION
1245 // A failure should throw the SecurityException from
1246 // ACCESS_COARSE_LOCATION since this is the weaker precondition
1247 mApp.enforceCallingOrSelfPermission(
1248 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1249 }
1250
1251 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1252 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1253 return null;
1254 }
Jake Hambye994d462014-02-03 13:10:13 -08001255 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001256 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1257
1258 ArrayList<NeighboringCellInfo> cells = null;
1259
1260 try {
1261 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
Wink Saville36469e72014-06-11 15:17:00 -07001262 CMD_HANDLE_NEIGHBORING_CELL, null, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001263 } catch (RuntimeException e) {
Wink Saville36469e72014-06-11 15:17:00 -07001264 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001265 }
1266 return cells;
1267 } else {
1268 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1269 return null;
1270 }
1271 }
1272
1273
1274 @Override
1275 public List<CellInfo> getAllCellInfo() {
1276 try {
1277 mApp.enforceCallingOrSelfPermission(
1278 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1279 } catch (SecurityException e) {
1280 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1281 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1282 // is the weaker precondition
1283 mApp.enforceCallingOrSelfPermission(
1284 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1285 }
1286
Jake Hambye994d462014-02-03 13:10:13 -08001287 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001288 if (DBG_LOC) log("getAllCellInfo: is active user");
1289 return mPhone.getAllCellInfo();
1290 } else {
1291 if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1292 return null;
1293 }
1294 }
1295
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001296 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001297 public void setCellInfoListRate(int rateInMillis) {
1298 mPhone.setCellInfoListRate(rateInMillis);
1299 }
1300
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001301 //
1302 // Internal helper methods.
1303 //
1304
Jake Hambye994d462014-02-03 13:10:13 -08001305 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001306 boolean ok;
1307
1308 boolean self = Binder.getCallingUid() == Process.myUid();
1309 if (!self) {
1310 // Get the caller's user id then clear the calling identity
1311 // which will be restored in the finally clause.
1312 int callingUser = UserHandle.getCallingUserId();
1313 long ident = Binder.clearCallingIdentity();
1314
1315 try {
1316 // With calling identity cleared the current user is the foreground user.
1317 int foregroundUser = ActivityManager.getCurrentUser();
1318 ok = (foregroundUser == callingUser);
1319 if (DBG_LOC) {
1320 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1321 + " callingUser=" + callingUser + " ok=" + ok);
1322 }
1323 } catch (Exception ex) {
1324 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1325 ok = false;
1326 } finally {
1327 Binder.restoreCallingIdentity(ident);
1328 }
1329 } else {
1330 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1331 ok = true;
1332 }
1333 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1334 return ok;
1335 }
1336
1337 /**
1338 * Make sure the caller has the READ_PHONE_STATE permission.
1339 *
1340 * @throws SecurityException if the caller does not have the required permission
1341 */
1342 private void enforceReadPermission() {
1343 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
1344 }
1345
1346 /**
1347 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1348 *
1349 * @throws SecurityException if the caller does not have the required permission
1350 */
1351 private void enforceModifyPermission() {
1352 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1353 }
1354
1355 /**
Junda Liua2e36012014-07-09 18:30:01 -07001356 * Make sure either system app or the caller has carrier privilege.
1357 *
1358 * @throws SecurityException if the caller does not have the required permission/privilege
1359 */
1360 private void enforceModifyPermissionOrCarrierPrivilege() {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001361 int permission = mApp.checkCallingOrSelfPermission(
1362 android.Manifest.permission.MODIFY_PHONE_STATE);
1363 if (permission == PackageManager.PERMISSION_GRANTED) {
1364 return;
1365 }
1366
1367 log("No modify permission, check carrier privilege next.");
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08001368 if (getCarrierPrivilegeStatus() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001369 loge("No Carrier Privilege.");
1370 throw new SecurityException("No modify permission or carrier privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001371 }
1372 }
1373
1374 /**
1375 * Make sure the caller has carrier privilege.
1376 *
1377 * @throws SecurityException if the caller does not have the required permission
1378 */
1379 private void enforceCarrierPrivilege() {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08001380 if (getCarrierPrivilegeStatus() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001381 loge("No Carrier Privilege.");
1382 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001383 }
1384 }
1385
1386 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001387 * Make sure the caller has the CALL_PHONE permission.
1388 *
1389 * @throws SecurityException if the caller does not have the required permission
1390 */
1391 private void enforceCallPermission() {
1392 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1393 }
1394
Shishir Agrawal566b7612013-10-28 14:41:00 -07001395 /**
Gabriel Peal36ebb0d2014-03-20 09:20:43 -07001396 * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
1397 *
1398 * @throws SecurityException if the caller does not have the required permission
1399 */
1400 private void enforcePrivilegedPhoneStatePermission() {
1401 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1402 null);
1403 }
1404
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001405 private String createTelUrl(String number) {
1406 if (TextUtils.isEmpty(number)) {
1407 return null;
1408 }
1409
Jake Hambye994d462014-02-03 13:10:13 -08001410 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001411 }
1412
Ihab Awadf9e92732013-12-05 18:02:52 -08001413 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001414 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1415 }
1416
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001417 private static void logv(String msg) {
1418 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1419 }
1420
Ihab Awadf9e92732013-12-05 18:02:52 -08001421 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001422 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1423 }
1424
1425 public int getActivePhoneType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001426 return getActivePhoneTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001427 }
1428
Wink Savilleb564aae2014-10-23 10:18:09 -07001429 public int getActivePhoneTypeForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001430 return getPhone(subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001431 }
1432
1433 /**
1434 * Returns the CDMA ERI icon index to display
1435 */
1436 public int getCdmaEriIconIndex() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001437 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001438
1439 }
1440
Wink Savilleb564aae2014-10-23 10:18:09 -07001441 public int getCdmaEriIconIndexForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001442 return getPhone(subId).getCdmaEriIconIndex();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001443 }
1444
1445 /**
1446 * Returns the CDMA ERI icon mode,
1447 * 0 - ON
1448 * 1 - FLASHING
1449 */
1450 public int getCdmaEriIconMode() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001451 return getCdmaEriIconModeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001452 }
1453
Wink Savilleb564aae2014-10-23 10:18:09 -07001454 public int getCdmaEriIconModeForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001455 return getPhone(subId).getCdmaEriIconMode();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001456 }
1457
1458 /**
1459 * Returns the CDMA ERI text,
1460 */
1461 public String getCdmaEriText() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001462 return getCdmaEriTextForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001463 }
1464
Wink Savilleb564aae2014-10-23 10:18:09 -07001465 public String getCdmaEriTextForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001466 return getPhone(subId).getCdmaEriText();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001467 }
1468
1469 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001470 * Returns the CDMA MDN.
1471 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001472 public String getCdmaMdn(int subId) {
Junda Liuca05d5d2014-08-14 22:36:34 -07001473 enforceModifyPermissionOrCarrierPrivilege();
1474 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1475 return getPhone(subId).getLine1Number();
1476 } else {
1477 return null;
1478 }
1479 }
1480
1481 /**
1482 * Returns the CDMA MIN.
1483 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001484 public String getCdmaMin(int subId) {
Junda Liuca05d5d2014-08-14 22:36:34 -07001485 enforceModifyPermissionOrCarrierPrivilege();
1486 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1487 return getPhone(subId).getCdmaMin();
1488 } else {
1489 return null;
1490 }
1491 }
1492
1493 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001494 * Returns true if CDMA provisioning needs to run.
1495 */
1496 public boolean needsOtaServiceProvisioning() {
1497 return mPhone.needsOtaServiceProvisioning();
1498 }
1499
1500 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001501 * Sets the voice mail number of a given subId.
1502 */
1503 @Override
1504 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08001505 enforceCarrierPrivilege();
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001506 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
1507 new Pair<String, String>(alphaTag, number), new Integer(subId));
1508 return success;
1509 }
1510
1511 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001512 * Returns the unread count of voicemails
1513 */
1514 public int getVoiceMessageCount() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001515 return getVoiceMessageCountForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001516 }
1517
1518 /**
1519 * Returns the unread count of voicemails for a subId
1520 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001521 public int getVoiceMessageCountForSubscriber( int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001522 return getPhone(subId).getVoiceMessageCount();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001523 }
1524
1525 /**
1526 * Returns the data network type
1527 *
1528 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
1529 */
1530 @Override
1531 public int getNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001532 return getNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001533 }
1534
1535 /**
1536 * Returns the network type for a subId
1537 */
1538 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001539 public int getNetworkTypeForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001540 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001541 }
1542
1543 /**
1544 * Returns the data network type
1545 */
1546 @Override
1547 public int getDataNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001548 return getDataNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001549 }
1550
1551 /**
1552 * Returns the data network type for a subId
1553 */
1554 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001555 public int getDataNetworkTypeForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001556 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001557 }
1558
1559 /**
1560 * Returns the data network type
1561 */
1562 @Override
1563 public int getVoiceNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001564 return getVoiceNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001565 }
1566
1567 /**
1568 * Returns the Voice network type for a subId
1569 */
1570 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001571 public int getVoiceNetworkTypeForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001572 return getPhone(subId).getServiceState().getVoiceNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001573 }
1574
1575 /**
1576 * @return true if a ICC card is present
1577 */
1578 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07001579 // FIXME Make changes to pass defaultSimId of type int
1580 return hasIccCardUsingSlotId(getDefaultSubscription());
1581 }
1582
1583 /**
1584 * @return true if a ICC card is present for a slotId
1585 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001586 public boolean hasIccCardUsingSlotId(int slotId) {
Wink Saville36469e72014-06-11 15:17:00 -07001587 return getPhone(slotId).getIccCard().hasIccCard();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001588 }
1589
1590 /**
1591 * Return if the current radio is LTE on CDMA. This
1592 * is a tri-state return value as for a period of time
1593 * the mode may be unknown.
1594 *
1595 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08001596 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001597 */
1598 public int getLteOnCdmaMode() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001599 return getLteOnCdmaModeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001600 }
1601
Wink Savilleb564aae2014-10-23 10:18:09 -07001602 public int getLteOnCdmaModeForSubscriber(int subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001603 return getPhone(subId).getLteOnCdmaMode();
1604 }
1605
1606 public void setPhone(Phone phone) {
1607 mPhone = phone;
1608 }
1609
1610 /**
1611 * {@hide}
1612 * Returns Default subId, 0 in the case of single standby.
1613 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001614 private int getDefaultSubscription() {
Wink Saville36469e72014-06-11 15:17:00 -07001615 return SubscriptionManager.getDefaultSubId();
1616 }
1617
Wink Savilleb564aae2014-10-23 10:18:09 -07001618 private int getPreferredVoiceSubscription() {
Wink Saville36469e72014-06-11 15:17:00 -07001619 return SubscriptionManager.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001620 }
Ihab Awadf2177b72013-11-25 13:33:23 -08001621
1622 /**
1623 * @see android.telephony.TelephonyManager.WifiCallingChoices
1624 */
1625 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001626 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1627 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08001628 }
1629
1630 /**
1631 * @see android.telephony.TelephonyManager.WifiCallingChoices
1632 */
1633 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001634 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1635 Settings.System.putInt(mPhone.getContext().getContentResolver(),
1636 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08001637 }
1638
Sailesh Nepald1e68152013-12-12 19:08:02 -08001639 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07001640 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08001641 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08001642 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08001643
Shishir Agrawal566b7612013-10-28 14:41:00 -07001644 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001645 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
Junda Liua2e36012014-07-09 18:30:01 -07001646 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001647
1648 if (DBG) log("iccOpenLogicalChannel: " + AID);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001649 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1650 CMD_OPEN_CHANNEL, AID);
1651 if (DBG) log("iccOpenLogicalChannel: " + response);
1652 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07001653 }
1654
1655 @Override
1656 public boolean iccCloseLogicalChannel(int channel) {
Junda Liua2e36012014-07-09 18:30:01 -07001657 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001658
1659 if (DBG) log("iccCloseLogicalChannel: " + channel);
1660 if (channel < 0) {
1661 return false;
1662 }
Jake Hambye994d462014-02-03 13:10:13 -08001663 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001664 if (DBG) log("iccCloseLogicalChannel: " + success);
1665 return success;
1666 }
1667
1668 @Override
1669 public String iccTransmitApduLogicalChannel(int channel, int cla,
1670 int command, int p1, int p2, int p3, String data) {
Junda Liua2e36012014-07-09 18:30:01 -07001671 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001672
1673 if (DBG) {
1674 log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1675 " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1676 " data=" + data);
1677 }
1678
1679 if (channel < 0) {
1680 return "";
1681 }
1682
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001683 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawal566b7612013-10-28 14:41:00 -07001684 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1685 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1686
Shishir Agrawal566b7612013-10-28 14:41:00 -07001687 // Append the returned status code to the end of the response payload.
1688 String s = Integer.toHexString(
1689 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001690 if (response.payload != null) {
1691 s = IccUtils.bytesToHexString(response.payload) + s;
1692 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001693 return s;
1694 }
Jake Hambye994d462014-02-03 13:10:13 -08001695
Evan Charltonc66da362014-05-16 14:06:40 -07001696 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001697 public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1698 int p3, String data) {
1699 enforceModifyPermissionOrCarrierPrivilege();
1700
1701 if (DBG) {
1702 log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1703 + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1704 }
1705
1706 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1707 new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1708 if (DBG) log("iccTransmitApduBasicChannel: " + response);
1709
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001710 // Append the returned status code to the end of the response payload.
1711 String s = Integer.toHexString(
1712 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001713 if (response.payload != null) {
1714 s = IccUtils.bytesToHexString(response.payload) + s;
1715 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001716 return s;
1717 }
1718
1719 @Override
1720 public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1721 String filePath) {
1722 enforceModifyPermissionOrCarrierPrivilege();
1723
1724 if (DBG) {
1725 log("Exchange SIM_IO " + fileID + ":" + command + " " +
1726 p1 + " " + p2 + " " + p3 + ":" + filePath);
1727 }
1728
1729 IccIoResult response =
1730 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
Yong Jiang3edf3782014-10-03 13:23:28 -05001731 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath));
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001732
1733 if (DBG) {
1734 log("Exchange SIM_IO [R]" + response);
1735 }
1736
1737 byte[] result = null;
1738 int length = 2;
1739 if (response.payload != null) {
1740 length = 2 + response.payload.length;
1741 result = new byte[length];
1742 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1743 } else {
1744 result = new byte[length];
1745 }
1746
1747 result[length - 1] = (byte) response.sw2;
1748 result[length - 2] = (byte) response.sw1;
1749 return result;
1750 }
1751
1752 @Override
Evan Charltonc66da362014-05-16 14:06:40 -07001753 public String sendEnvelopeWithStatus(String content) {
Junda Liua2e36012014-07-09 18:30:01 -07001754 enforceModifyPermissionOrCarrierPrivilege();
Evan Charltonc66da362014-05-16 14:06:40 -07001755
1756 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1757 if (response.payload == null) {
1758 return "";
1759 }
1760
1761 // Append the returned status code to the end of the response payload.
1762 String s = Integer.toHexString(
1763 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1764 s = IccUtils.bytesToHexString(response.payload) + s;
1765 return s;
1766 }
1767
Jake Hambye994d462014-02-03 13:10:13 -08001768 /**
1769 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1770 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1771 *
1772 * @param itemID the ID of the item to read
1773 * @return the NV item as a String, or null on error.
1774 */
1775 @Override
1776 public String nvReadItem(int itemID) {
Junda Liua2e36012014-07-09 18:30:01 -07001777 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001778 if (DBG) log("nvReadItem: item " + itemID);
1779 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1780 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1781 return value;
1782 }
1783
1784 /**
1785 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1786 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1787 *
1788 * @param itemID the ID of the item to read
1789 * @param itemValue the value to write, as a String
1790 * @return true on success; false on any failure
1791 */
1792 @Override
1793 public boolean nvWriteItem(int itemID, String itemValue) {
Junda Liua2e36012014-07-09 18:30:01 -07001794 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001795 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1796 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1797 new Pair<Integer, String>(itemID, itemValue));
1798 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1799 return success;
1800 }
1801
1802 /**
1803 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1804 * Used for device configuration by some CDMA operators.
1805 *
1806 * @param preferredRoamingList byte array containing the new PRL
1807 * @return true on success; false on any failure
1808 */
1809 @Override
1810 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Junda Liua2e36012014-07-09 18:30:01 -07001811 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001812 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1813 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1814 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1815 return success;
1816 }
1817
1818 /**
1819 * Perform the specified type of NV config reset.
1820 * Used for device configuration by some CDMA operators.
1821 *
1822 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1823 * @return true on success; false on any failure
1824 */
1825 @Override
1826 public boolean nvResetConfig(int resetType) {
Junda Liua2e36012014-07-09 18:30:01 -07001827 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001828 if (DBG) log("nvResetConfig: type " + resetType);
1829 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1830 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1831 return success;
1832 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001833
1834 /**
Wink Saville36469e72014-06-11 15:17:00 -07001835 * {@hide}
1836 * Returns Default sim, 0 in the case of single standby.
1837 */
1838 public int getDefaultSim() {
1839 //TODO Need to get it from Telephony Devcontroller
1840 return 0;
1841 }
1842
ram87fca6f2014-07-18 18:58:44 +05301843 public String[] getPcscfAddress(String apnType) {
Wink Saville36469e72014-06-11 15:17:00 -07001844 enforceReadPermission();
ram87fca6f2014-07-18 18:58:44 +05301845 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07001846 }
1847
1848 public void setImsRegistrationState(boolean registered) {
1849 enforceModifyPermission();
1850 mPhone.setImsRegistrationState(registered);
1851 }
1852
1853 /**
Junda Liu84d15a22014-07-02 11:21:04 -07001854 * Get the calculated preferred network type.
1855 * Used for debugging incorrect network type.
1856 *
1857 * @return the preferred network type, defined in RILConstants.java.
1858 */
1859 @Override
1860 public int getCalculatedPreferredNetworkType() {
1861 enforceReadPermission();
Amit Mahajan43330e02014-11-18 11:54:45 -08001862 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07001863 }
1864
1865 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08001866 * Get the preferred network type.
1867 * Used for device configuration by some CDMA operators.
1868 *
1869 * @return the preferred network type, defined in RILConstants.java.
1870 */
1871 @Override
1872 public int getPreferredNetworkType() {
Junda Liua2e36012014-07-09 18:30:01 -07001873 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001874 if (DBG) log("getPreferredNetworkType");
1875 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
1876 int networkType = (result != null ? result[0] : -1);
1877 if (DBG) log("getPreferredNetworkType: " + networkType);
1878 return networkType;
1879 }
1880
1881 /**
1882 * Set the preferred network type.
1883 * Used for device configuration by some CDMA operators.
1884 *
1885 * @param networkType the preferred network type, defined in RILConstants.java.
1886 * @return true on success; false on any failure.
1887 */
1888 @Override
1889 public boolean setPreferredNetworkType(int networkType) {
Junda Liua2e36012014-07-09 18:30:01 -07001890 enforceModifyPermissionOrCarrierPrivilege();
PauloftheWest3c6ce5e2014-11-03 07:09:47 -08001891 final int phoneSubId = mPhone.getSubId();
Jake Hamby7c27be32014-03-03 13:25:59 -08001892 if (DBG) log("setPreferredNetworkType: type " + networkType);
1893 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
1894 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07001895 if (success) {
1896 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
PauloftheWest3c6ce5e2014-11-03 07:09:47 -08001897 Settings.Global.PREFERRED_NETWORK_MODE + phoneSubId, networkType);
Junda Liu80bc0d12014-07-14 16:36:44 -07001898 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001899 return success;
1900 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001901
1902 /**
1903 * Set mobile data enabled
1904 * Used by the user through settings etc to turn on/off mobile data
1905 *
1906 * @param enable {@code true} turn turn data on, else {@code false}
1907 */
1908 @Override
1909 public void setDataEnabled(boolean enable) {
1910 enforceModifyPermission();
1911 mPhone.setDataEnabled(enable);
1912 }
1913
1914 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07001915 * Get whether mobile data is enabled.
1916 *
1917 * Note that this used to be available from ConnectivityService, gated by
1918 * ACCESS_NETWORK_STATE permission, so this will accept either that or
1919 * our MODIFY_PHONE_STATE.
Robert Greenwalted86e582014-05-21 20:03:20 -07001920 *
1921 * @return {@code true} if data is enabled else {@code false}
1922 */
1923 @Override
1924 public boolean getDataEnabled() {
Robert Greenwalt646120a2014-05-23 11:54:03 -07001925 try {
1926 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1927 null);
1928 } catch (Exception e) {
1929 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1930 null);
1931 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001932 return mPhone.getDataEnabled();
1933 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001934
1935 @Override
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08001936 public int getCarrierPrivilegeStatus() {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001937 UiccCard card = UiccController.getInstance().getUiccCard();
1938 if (card == null) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08001939 loge("getCarrierPrivilegeStatus: No UICC");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001940 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1941 }
1942 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001943 mPhone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001944 }
Junda Liu29340342014-07-10 15:23:27 -07001945
1946 @Override
Shishir Agrawal6d5a2852014-07-11 16:32:57 -07001947 public int checkCarrierPrivilegesForPackage(String pkgname) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001948 UiccCard card = UiccController.getInstance().getUiccCard();
1949 if (card == null) {
1950 loge("checkCarrierPrivilegesForPackage: No UICC");
1951 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1952 }
1953 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
Junda Liu29340342014-07-10 15:23:27 -07001954 }
Derek Tan89e89d42014-07-08 17:00:10 -07001955
1956 @Override
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001957 public List<String> getCarrierPackageNamesForIntent(Intent intent) {
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001958 UiccCard card = UiccController.getInstance().getUiccCard();
1959 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001960 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001961 return null ;
1962 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001963 return card.getCarrierPackageNamesForIntent(
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001964 mPhone.getContext().getPackageManager(), intent);
1965 }
1966
Wink Savilleb564aae2014-10-23 10:18:09 -07001967 private String getIccId(int subId) {
Derek Tan97ebb422014-09-05 16:55:38 -07001968 UiccCard card = getPhone(subId).getUiccCard();
1969 if (card == null) {
1970 loge("getIccId: No UICC");
1971 return null;
1972 }
1973 String iccId = card.getIccId();
1974 if (TextUtils.isEmpty(iccId)) {
1975 loge("getIccId: ICC ID is null or empty.");
1976 return null;
1977 }
1978 return iccId;
1979 }
1980
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001981 @Override
Shishir Agrawal495d7e12014-12-01 11:50:28 -08001982 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08001983 enforceCarrierPrivilege();
Derek Tan97ebb422014-09-05 16:55:38 -07001984
1985 String iccId = getIccId(subId);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08001986 if (TextUtils.isEmpty(iccId)) {
1987 return false;
Derek Tan97ebb422014-09-05 16:55:38 -07001988 }
Shishir Agrawal495d7e12014-12-01 11:50:28 -08001989
1990 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
1991 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
1992 if (alphaTag == null) {
1993 editor.remove(alphaTagPrefKey);
1994 } else {
1995 editor.putString(alphaTagPrefKey, alphaTag);
1996 }
1997
1998 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
1999 if (number == null) {
2000 editor.remove(numberPrefKey);
2001 } else {
2002 editor.putString(numberPrefKey, number);
2003 }
2004 editor.commit();
2005 return true;
Derek Tan7226c842014-07-02 17:42:23 -07002006 }
2007
2008 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002009 public String getLine1NumberForDisplay(int subId) {
Derek Tan7226c842014-07-02 17:42:23 -07002010 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07002011
2012 String iccId = getIccId(subId);
2013 if (iccId != null) {
2014 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002015 return mTelephonySharedPreferences.getString(numberPrefKey, 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 }
2019
2020 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002021 public String getLine1AlphaTagForDisplay(int subId) {
Derek Tan7226c842014-07-02 17:42:23 -07002022 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07002023
2024 String iccId = getIccId(subId);
2025 if (iccId != null) {
2026 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002027 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002028 }
Derek Tan97ebb422014-09-05 16:55:38 -07002029 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002030 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002031
2032 @Override
Shishir Agrawala3dfd752014-09-04 13:25:42 -07002033 public boolean setOperatorBrandOverride(String brand) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08002034 enforceCarrierPrivilege();
Shishir Agrawala3dfd752014-09-04 13:25:42 -07002035 return mPhone.setOperatorBrandOverride(brand);
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002036 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002037
2038 @Override
2039 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2040 enforceModifyPermission();
2041
2042 int returnValue = 0;
2043 try {
2044 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2045 if(result.exception == null) {
2046 if (result.result != null) {
2047 byte[] responseData = (byte[])(result.result);
2048 if(responseData.length > oemResp.length) {
2049 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2050 responseData.length + "bytes. Buffer Size is " +
2051 oemResp.length + "bytes.");
2052 }
2053 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2054 returnValue = responseData.length;
2055 }
2056 } else {
2057 CommandException ex = (CommandException) result.exception;
2058 returnValue = ex.getCommandError().ordinal();
2059 if(returnValue > 0) returnValue *= -1;
2060 }
2061 } catch (RuntimeException e) {
2062 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2063 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2064 if(returnValue > 0) returnValue *= -1;
2065 }
2066
2067 return returnValue;
2068 }
Wink Saville5d475dd2014-10-17 15:00:58 -07002069
2070 @Override
2071 public void setRadioCapability(RadioAccessFamily[] rafs) {
2072 try {
2073 ProxyController.getInstance().setRadioCapability(rafs);
2074 } catch (RuntimeException e) {
2075 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
2076 }
2077 }
2078
2079 @Override
2080 public int getRadioAccessFamily(int phoneId) {
2081 return ProxyController.getInstance().getRadioAccessFamily(phoneId);
2082 }
Andrew Leedf14ead2014-10-17 14:22:52 -07002083
2084 @Override
2085 public void enableVideoCalling(boolean enable) {
2086 enforceModifyPermission();
2087 SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2088 editor.putBoolean(PREF_ENABLE_VIDEO_CALLING, enable);
2089 editor.commit();
2090 }
2091
2092 @Override
2093 public boolean isVideoCallingEnabled() {
2094 enforceReadPermission();
Andrew Lee77527ac2014-10-21 16:57:39 -07002095 // Check the user preference and the system-level IMS setting. Even if the user has
2096 // enabled video calling, if IMS is disabled we aren't able to support video calling.
2097 // In the long run, we may instead need to check if there exists a connection service
2098 // which can support video calling.
Andrew Lee312e8172014-10-23 17:01:36 -07002099 return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
2100 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
2101 && mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true);
Andrew Leedf14ead2014-10-17 14:22:52 -07002102 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002103}