blob: f9a098929697647eec81802b57f517ae934bd285 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
19import android.app.ActivityManager;
20import android.app.AppOpsManager;
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -070021import android.content.ComponentName;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070022import android.content.Context;
23import android.content.Intent;
Derek Tan97ebb422014-09-05 16:55:38 -070024import android.content.SharedPreferences;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070025import android.content.pm.PackageInfo;
26import android.content.pm.PackageManager;
27import android.content.pm.Signature;
Wink Saville36469e72014-06-11 15:17:00 -070028import android.net.ConnectivityManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070029import android.net.Uri;
30import android.os.AsyncResult;
31import android.os.Binder;
32import android.os.Bundle;
33import android.os.Handler;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070034import android.os.IBinder;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070035import android.os.Looper;
36import android.os.Message;
37import android.os.Process;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070038import android.os.RemoteException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070039import android.os.ServiceManager;
Wink Saville08874612014-08-31 19:19:58 -070040import android.os.SystemProperties;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070041import android.os.UserHandle;
Derek Tan97ebb422014-09-05 16:55:38 -070042import android.preference.PreferenceManager;
Ihab Awadf2177b72013-11-25 13:33:23 -080043import android.provider.Settings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070044import android.telephony.CellInfo;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070045import android.telephony.IccOpenLogicalChannelResponse;
Jake Hambye994d462014-02-03 13:10:13 -080046import android.telephony.NeighboringCellInfo;
Wink Saville5d475dd2014-10-17 15:00:58 -070047import android.telephony.RadioAccessFamily;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070048import android.telephony.ServiceState;
Wink Saville36469e72014-06-11 15:17:00 -070049import android.telephony.SubscriptionManager;
Wink Saville08874612014-08-31 19:19:58 -070050import android.telephony.SubInfoRecord;
Ihab Awadf2177b72013-11-25 13:33:23 -080051import android.telephony.TelephonyManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070052import android.text.TextUtils;
53import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -080054import android.util.Pair;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070055
Shishir Agrawal566b7612013-10-28 14:41:00 -070056import com.android.internal.telephony.CallManager;
57import com.android.internal.telephony.CommandException;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070058import com.android.internal.telephony.Connection;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070059import com.android.internal.telephony.DefaultPhoneNotifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070060import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -080061import com.android.internal.telephony.IccCard;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070062import com.android.internal.telephony.Phone;
Wink Saville36469e72014-06-11 15:17:00 -070063import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -070064import com.android.internal.telephony.PhoneProxy;
65import com.android.internal.telephony.ProxyController;
Wink Saville36469e72014-06-11 15:17:00 -070066import com.android.internal.telephony.CallManager;
67import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070068import com.android.internal.telephony.PhoneConstants;
Wink Saville08874612014-08-31 19:19:58 -070069import com.android.internal.telephony.TelephonyIntents;
Wink Saville36469e72014-06-11 15:17:00 -070070import com.android.internal.telephony.dataconnection.DctController;
Derek Tan7226c842014-07-02 17:42:23 -070071import com.android.internal.telephony.uicc.AdnRecord;
Shishir Agrawal566b7612013-10-28 14:41:00 -070072import com.android.internal.telephony.uicc.IccIoResult;
73import com.android.internal.telephony.uicc.IccUtils;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -070074import com.android.internal.telephony.uicc.UiccCard;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070075import com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
Shishir Agrawal566b7612013-10-28 14:41:00 -070076import com.android.internal.telephony.uicc.UiccController;
Jake Hambye994d462014-02-03 13:10:13 -080077import com.android.internal.util.HexDump;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070078
Wink Saville36469e72014-06-11 15:17:00 -070079import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
80
Santos Cordon7d4ddf62013-07-10 11:58:08 -070081import java.util.ArrayList;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070082import java.util.HashMap;
Derek Tan89e89d42014-07-08 17:00:10 -070083import java.util.HashSet;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070084import java.util.Iterator;
Jake Hambye994d462014-02-03 13:10:13 -080085import java.util.List;
Gabriel Peal36ebb0d2014-03-20 09:20:43 -070086import java.util.Map;
Derek Tan89e89d42014-07-08 17:00:10 -070087import java.util.Set;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070088
89/**
90 * Implementation of the ITelephony interface.
91 */
Santos Cordon117fee72014-05-16 17:56:12 -070092public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -070093 private static final String LOG_TAG = "PhoneInterfaceManager";
94 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
95 private static final boolean DBG_LOC = false;
96
97 // Message codes used with mMainThreadHandler
98 private static final int CMD_HANDLE_PIN_MMI = 1;
99 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
100 private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
101 private static final int CMD_ANSWER_RINGING_CALL = 4;
102 private static final int CMD_END_CALL = 5; // not used yet
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700103 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
104 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700105 private static final int CMD_OPEN_CHANNEL = 9;
106 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
107 private static final int CMD_CLOSE_CHANNEL = 11;
108 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800109 private static final int CMD_NV_READ_ITEM = 13;
110 private static final int EVENT_NV_READ_ITEM_DONE = 14;
111 private static final int CMD_NV_WRITE_ITEM = 15;
112 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
113 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
114 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
115 private static final int CMD_NV_RESET_CONFIG = 19;
116 private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800117 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
118 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
119 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
120 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800121 private static final int CMD_SEND_ENVELOPE = 25;
122 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Derek Tan6b088ee2014-09-05 14:15:18 -0700123 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
124 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
125 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
126 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
127 private static final int CMD_EXCHANGE_SIM_IO = 31;
128 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700129
130 /** The singleton instance. */
131 private static PhoneInterfaceManager sInstance;
132
133 PhoneGlobals mApp;
134 Phone mPhone;
135 CallManager mCM;
136 AppOpsManager mAppOps;
137 MainThreadHandler mMainThreadHandler;
138
Derek Tan97ebb422014-09-05 16:55:38 -0700139 SharedPreferences carrierPrivilegeConfigs;
140 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
141 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
142 private static final String PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX =
143 "carrier_simplified_network_settings_";
Derek Tan89e89d42014-07-08 17:00:10 -0700144
145 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700146 * A request object to use for transmitting data to an ICC.
147 */
148 private static final class IccAPDUArgument {
149 public int channel, cla, command, p1, p2, p3;
150 public String data;
151
152 public IccAPDUArgument(int channel, int cla, int command,
153 int p1, int p2, int p3, String data) {
154 this.channel = channel;
155 this.cla = cla;
156 this.command = command;
157 this.p1 = p1;
158 this.p2 = p2;
159 this.p3 = p3;
160 this.data = data;
161 }
162 }
163
164 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700165 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
166 * request after sending. The main thread will notify the request when it is complete.
167 */
168 private static final class MainThreadRequest {
169 /** The argument to use for the request */
170 public Object argument;
171 /** The result of the request that is run on the main thread */
172 public Object result;
173
174 public MainThreadRequest(Object argument) {
175 this.argument = argument;
176 }
177 }
178
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800179 private static final class IncomingThirdPartyCallArgs {
180 public final ComponentName component;
181 public final String callId;
182 public final String callerDisplayName;
183
184 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
185 String callerDisplayName) {
186 this.component = component;
187 this.callId = callId;
188 this.callerDisplayName = callerDisplayName;
189 }
190 }
191
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700192 /**
193 * A handler that processes messages on the main thread in the phone process. Since many
194 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
195 * inbound binder threads to the main thread in the phone process. The Binder thread
196 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
197 * on, which will be notified when the operation completes and will contain the result of the
198 * request.
199 *
200 * <p>If a MainThreadRequest object is provided in the msg.obj field,
201 * note that request.result must be set to something non-null for the calling thread to
202 * unblock.
203 */
204 private final class MainThreadHandler extends Handler {
205 @Override
206 public void handleMessage(Message msg) {
207 MainThreadRequest request;
208 Message onCompleted;
209 AsyncResult ar;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700210 UiccCard uiccCard = UiccController.getInstance().getUiccCard();
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700211 IccAPDUArgument iccArgument;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700212
213 switch (msg.what) {
214 case CMD_HANDLE_PIN_MMI:
215 request = (MainThreadRequest) msg.obj;
Jake Hambye994d462014-02-03 13:10:13 -0800216 request.result = mPhone.handlePinMmi((String) request.argument);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700217 // Wake up the requesting thread
218 synchronized (request) {
219 request.notifyAll();
220 }
221 break;
222
223 case CMD_HANDLE_NEIGHBORING_CELL:
224 request = (MainThreadRequest) msg.obj;
225 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
226 request);
227 mPhone.getNeighboringCids(onCompleted);
228 break;
229
230 case EVENT_NEIGHBORING_CELL_DONE:
231 ar = (AsyncResult) msg.obj;
232 request = (MainThreadRequest) ar.userObj;
233 if (ar.exception == null && ar.result != null) {
234 request.result = ar.result;
235 } else {
236 // create an empty list to notify the waiting thread
Jake Hambye994d462014-02-03 13:10:13 -0800237 request.result = new ArrayList<NeighboringCellInfo>(0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700238 }
239 // Wake up the requesting thread
240 synchronized (request) {
241 request.notifyAll();
242 }
243 break;
244
245 case CMD_ANSWER_RINGING_CALL:
Wink Saville08874612014-08-31 19:19:58 -0700246 request = (MainThreadRequest) msg.obj;
247 long answer_subId = ((Long)request.argument).longValue();
248 answerRingingCallInternal(answer_subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700249 break;
250
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700251 case CMD_END_CALL:
252 request = (MainThreadRequest) msg.obj;
Wink Saville08874612014-08-31 19:19:58 -0700253 long end_subId = ((Long)request.argument).longValue();
254 final boolean hungUp;
255 int phoneType = getPhone(end_subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700256 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
257 // CDMA: If the user presses the Power button we treat it as
258 // ending the complete call session
Wink Saville08874612014-08-31 19:19:58 -0700259 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700260 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
261 // GSM: End the call as per the Phone state
262 hungUp = PhoneUtils.hangup(mCM);
263 } else {
264 throw new IllegalStateException("Unexpected phone type: " + phoneType);
265 }
266 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
267 request.result = hungUp;
268 // Wake up the requesting thread
269 synchronized (request) {
270 request.notifyAll();
271 }
272 break;
273
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700274 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700275 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700276 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700277 if (uiccCard == null) {
278 loge("iccTransmitApduLogicalChannel: No UICC");
279 request.result = new IccIoResult(0x6F, 0, (byte[])null);
280 synchronized (request) {
281 request.notifyAll();
282 }
283 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700284 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
285 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700286 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700287 iccArgument.channel, iccArgument.cla, iccArgument.command,
288 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700289 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700290 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700291 break;
292
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700293 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700294 ar = (AsyncResult) msg.obj;
295 request = (MainThreadRequest) ar.userObj;
296 if (ar.exception == null && ar.result != null) {
297 request.result = ar.result;
298 } else {
299 request.result = new IccIoResult(0x6F, 0, (byte[])null);
300 if (ar.result == null) {
301 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800302 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700303 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800304 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700305 } else {
306 loge("iccTransmitApduLogicalChannel: Unknown exception");
307 }
308 }
309 synchronized (request) {
310 request.notifyAll();
311 }
312 break;
313
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700314 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
315 request = (MainThreadRequest) msg.obj;
316 iccArgument = (IccAPDUArgument) request.argument;
317 if (uiccCard == null) {
318 loge("iccTransmitApduBasicChannel: No UICC");
319 request.result = new IccIoResult(0x6F, 0, (byte[])null);
320 synchronized (request) {
321 request.notifyAll();
322 }
323 } else {
324 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
325 request);
326 uiccCard.iccTransmitApduBasicChannel(
327 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
328 iccArgument.p3, iccArgument.data, onCompleted);
329 }
330 break;
331
332 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
333 ar = (AsyncResult) msg.obj;
334 request = (MainThreadRequest) ar.userObj;
335 if (ar.exception == null && ar.result != null) {
336 request.result = ar.result;
337 } else {
338 request.result = new IccIoResult(0x6F, 0, (byte[])null);
339 if (ar.result == null) {
340 loge("iccTransmitApduBasicChannel: Empty response");
341 } else if (ar.exception instanceof CommandException) {
342 loge("iccTransmitApduBasicChannel: CommandException: " +
343 ar.exception);
344 } else {
345 loge("iccTransmitApduBasicChannel: Unknown exception");
346 }
347 }
348 synchronized (request) {
349 request.notifyAll();
350 }
351 break;
352
353 case CMD_EXCHANGE_SIM_IO:
354 request = (MainThreadRequest) msg.obj;
355 iccArgument = (IccAPDUArgument) request.argument;
356 if (uiccCard == null) {
357 loge("iccExchangeSimIO: No UICC");
358 request.result = new IccIoResult(0x6F, 0, (byte[])null);
359 synchronized (request) {
360 request.notifyAll();
361 }
362 } else {
363 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
364 request);
365 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
366 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
367 iccArgument.data, onCompleted);
368 }
369 break;
370
371 case EVENT_EXCHANGE_SIM_IO_DONE:
372 ar = (AsyncResult) msg.obj;
373 request = (MainThreadRequest) ar.userObj;
374 if (ar.exception == null && ar.result != null) {
375 request.result = ar.result;
376 } else {
377 request.result = new IccIoResult(0x6f, 0, (byte[])null);
378 }
379 synchronized (request) {
380 request.notifyAll();
381 }
382 break;
383
Derek Tan4d5e5c12014-02-04 11:54:58 -0800384 case CMD_SEND_ENVELOPE:
385 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700386 if (uiccCard == null) {
387 loge("sendEnvelopeWithStatus: No UICC");
388 request.result = new IccIoResult(0x6F, 0, (byte[])null);
389 synchronized (request) {
390 request.notifyAll();
391 }
392 } else {
393 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
394 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
395 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800396 break;
397
398 case EVENT_SEND_ENVELOPE_DONE:
399 ar = (AsyncResult) msg.obj;
400 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700401 if (ar.exception == null && ar.result != null) {
402 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800403 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700404 request.result = new IccIoResult(0x6F, 0, (byte[])null);
405 if (ar.result == null) {
406 loge("sendEnvelopeWithStatus: Empty response");
407 } else if (ar.exception instanceof CommandException) {
408 loge("sendEnvelopeWithStatus: CommandException: " +
409 ar.exception);
410 } else {
411 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
412 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800413 }
414 synchronized (request) {
415 request.notifyAll();
416 }
417 break;
418
Shishir Agrawal566b7612013-10-28 14:41:00 -0700419 case CMD_OPEN_CHANNEL:
420 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700421 if (uiccCard == null) {
422 loge("iccOpenLogicalChannel: No UICC");
423 request.result = new IccIoResult(0x6F, 0, (byte[])null);
424 synchronized (request) {
425 request.notifyAll();
426 }
427 } else {
428 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
429 uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
430 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700431 break;
432
433 case EVENT_OPEN_CHANNEL_DONE:
434 ar = (AsyncResult) msg.obj;
435 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700436 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700437 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700438 int[] result = (int[]) ar.result;
439 int channelId = result[0];
440 byte[] selectResponse = null;
441 if (result.length > 1) {
442 selectResponse = new byte[result.length - 1];
443 for (int i = 1; i < result.length; ++i) {
444 selectResponse[i - 1] = (byte) result[i];
445 }
446 }
447 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700448 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700449 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700450 if (ar.result == null) {
451 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700452 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700453 if (ar.exception != null) {
454 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
455 }
456
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700457 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700458 if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
459 if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700460 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700461 } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700462 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700463 }
464 }
465 openChannelResp = new IccOpenLogicalChannelResponse(
466 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700467 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700468 request.result = openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700469 synchronized (request) {
470 request.notifyAll();
471 }
472 break;
473
474 case CMD_CLOSE_CHANNEL:
475 request = (MainThreadRequest) msg.obj;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700476 if (uiccCard == null) {
477 loge("iccCloseLogicalChannel: No UICC");
478 request.result = new IccIoResult(0x6F, 0, (byte[])null);
479 synchronized (request) {
480 request.notifyAll();
481 }
482 } else {
483 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
484 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
485 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700486 break;
487
488 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800489 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
490 break;
491
492 case CMD_NV_READ_ITEM:
493 request = (MainThreadRequest) msg.obj;
494 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
495 mPhone.nvReadItem((Integer) request.argument, onCompleted);
496 break;
497
498 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700499 ar = (AsyncResult) msg.obj;
500 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800501 if (ar.exception == null && ar.result != null) {
502 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700503 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800504 request.result = "";
505 if (ar.result == null) {
506 loge("nvReadItem: Empty response");
507 } else if (ar.exception instanceof CommandException) {
508 loge("nvReadItem: CommandException: " +
509 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700510 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800511 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700512 }
513 }
514 synchronized (request) {
515 request.notifyAll();
516 }
517 break;
518
Jake Hambye994d462014-02-03 13:10:13 -0800519 case CMD_NV_WRITE_ITEM:
520 request = (MainThreadRequest) msg.obj;
521 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
522 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
523 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
524 break;
525
526 case EVENT_NV_WRITE_ITEM_DONE:
527 handleNullReturnEvent(msg, "nvWriteItem");
528 break;
529
530 case CMD_NV_WRITE_CDMA_PRL:
531 request = (MainThreadRequest) msg.obj;
532 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
533 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
534 break;
535
536 case EVENT_NV_WRITE_CDMA_PRL_DONE:
537 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
538 break;
539
540 case CMD_NV_RESET_CONFIG:
541 request = (MainThreadRequest) msg.obj;
542 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
543 mPhone.nvResetConfig((Integer) request.argument, onCompleted);
544 break;
545
546 case EVENT_NV_RESET_CONFIG_DONE:
547 handleNullReturnEvent(msg, "nvResetConfig");
548 break;
549
Jake Hamby7c27be32014-03-03 13:25:59 -0800550 case CMD_GET_PREFERRED_NETWORK_TYPE:
551 request = (MainThreadRequest) msg.obj;
552 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
553 mPhone.getPreferredNetworkType(onCompleted);
554 break;
555
556 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
557 ar = (AsyncResult) msg.obj;
558 request = (MainThreadRequest) ar.userObj;
559 if (ar.exception == null && ar.result != null) {
560 request.result = ar.result; // Integer
561 } else {
562 request.result = -1;
563 if (ar.result == null) {
564 loge("getPreferredNetworkType: Empty response");
565 } else if (ar.exception instanceof CommandException) {
566 loge("getPreferredNetworkType: CommandException: " +
567 ar.exception);
568 } else {
569 loge("getPreferredNetworkType: Unknown exception");
570 }
571 }
572 synchronized (request) {
573 request.notifyAll();
574 }
575 break;
576
577 case CMD_SET_PREFERRED_NETWORK_TYPE:
578 request = (MainThreadRequest) msg.obj;
579 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
580 int networkType = (Integer) request.argument;
581 mPhone.setPreferredNetworkType(networkType, onCompleted);
582 break;
583
584 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
585 handleNullReturnEvent(msg, "setPreferredNetworkType");
586 break;
587
Steven Liu4bf01bc2014-07-17 11:05:29 -0500588 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
589 request = (MainThreadRequest)msg.obj;
590 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
591 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
592 break;
593
594 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
595 ar = (AsyncResult)msg.obj;
596 request = (MainThreadRequest)ar.userObj;
597 request.result = ar;
598 synchronized (request) {
599 request.notifyAll();
600 }
601 break;
602
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700603 default:
604 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
605 break;
606 }
607 }
Jake Hambye994d462014-02-03 13:10:13 -0800608
609 private void handleNullReturnEvent(Message msg, String command) {
610 AsyncResult ar = (AsyncResult) msg.obj;
611 MainThreadRequest request = (MainThreadRequest) ar.userObj;
612 if (ar.exception == null) {
613 request.result = true;
614 } else {
615 request.result = false;
616 if (ar.exception instanceof CommandException) {
617 loge(command + ": CommandException: " + ar.exception);
618 } else {
619 loge(command + ": Unknown exception");
620 }
621 }
622 synchronized (request) {
623 request.notifyAll();
624 }
625 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700626 }
627
628 /**
629 * Posts the specified command to be executed on the main thread,
630 * waits for the request to complete, and returns the result.
631 * @see #sendRequestAsync
632 */
633 private Object sendRequest(int command, Object argument) {
Santos Cordon500b0e02014-06-17 10:33:33 -0700634 return sendRequest(command, argument, null);
Wink Saville36469e72014-06-11 15:17:00 -0700635 }
636
637 /**
638 * Posts the specified command to be executed on the main thread,
639 * waits for the request to complete, and returns the result.
640 * @see #sendRequestAsync
641 */
642 private Object sendRequest(int command, Object argument, Object argument2) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700643 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
644 throw new RuntimeException("This method will deadlock if called from the main thread.");
645 }
646
647 MainThreadRequest request = new MainThreadRequest(argument);
648 Message msg = mMainThreadHandler.obtainMessage(command, request);
649 msg.sendToTarget();
650
651 // Wait for the request to complete
652 synchronized (request) {
653 while (request.result == null) {
654 try {
655 request.wait();
656 } catch (InterruptedException e) {
657 // Do nothing, go back and wait until the request is complete
658 }
659 }
660 }
661 return request.result;
662 }
663
664 /**
665 * Asynchronous ("fire and forget") version of sendRequest():
666 * Posts the specified command to be executed on the main thread, and
667 * returns immediately.
668 * @see #sendRequest
669 */
670 private void sendRequestAsync(int command) {
671 mMainThreadHandler.sendEmptyMessage(command);
672 }
673
674 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -0700675 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
676 * @see {@link #sendRequest(int,Object)}
677 */
678 private void sendRequestAsync(int command, Object argument) {
679 MainThreadRequest request = new MainThreadRequest(argument);
680 Message msg = mMainThreadHandler.obtainMessage(command, request);
681 msg.sendToTarget();
682 }
683
684 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700685 * Initialize the singleton PhoneInterfaceManager instance.
686 * This is only done once, at startup, from PhoneApp.onCreate().
687 */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700688 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700689 synchronized (PhoneInterfaceManager.class) {
690 if (sInstance == null) {
Sailesh Nepal194161e2014-07-03 08:57:44 -0700691 sInstance = new PhoneInterfaceManager(app, phone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700692 } else {
693 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
694 }
695 return sInstance;
696 }
697 }
698
699 /** Private constructor; @see init() */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700700 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700701 mApp = app;
702 mPhone = phone;
703 mCM = PhoneGlobals.getInstance().mCM;
704 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
705 mMainThreadHandler = new MainThreadHandler();
Derek Tan97ebb422014-09-05 16:55:38 -0700706 carrierPrivilegeConfigs =
707 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700708 publish();
709 }
710
711 private void publish() {
712 if (DBG) log("publish: " + this);
713
714 ServiceManager.addService("phone", this);
715 }
716
Wink Saville36469e72014-06-11 15:17:00 -0700717 // returns phone associated with the subId.
Wink Saville36469e72014-06-11 15:17:00 -0700718 private Phone getPhone(long subId) {
Legler Wuf8733b42014-09-25 11:00:54 +0800719 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -0700720 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700721 //
722 // Implementation of the ITelephony interface.
723 //
724
725 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700726 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -0700727 }
728
Wink Savilleadd7cc52014-09-08 14:23:09 -0700729 public void dialForSubscriber(long subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700730 if (DBG) log("dial: " + number);
731 // No permission check needed here: This is just a wrapper around the
732 // ACTION_DIAL intent, which is available to any app since it puts up
733 // the UI before it does anything.
734
735 String url = createTelUrl(number);
736 if (url == null) {
737 return;
738 }
739
740 // PENDING: should we just silently fail if phone is offhook or ringing?
Wink Saville36469e72014-06-11 15:17:00 -0700741 PhoneConstants.State state = mCM.getState(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700742 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
743 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
744 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
745 mApp.startActivity(intent);
746 }
747 }
748
749 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700750 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -0700751 }
752
Wink Savilleadd7cc52014-09-08 14:23:09 -0700753 public void callForSubscriber(long subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700754 if (DBG) log("call: " + number);
755
756 // This is just a wrapper around the ACTION_CALL intent, but we still
757 // need to do a permission check since we're calling startActivity()
758 // from the context of the phone app.
759 enforceCallPermission();
760
761 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
762 != AppOpsManager.MODE_ALLOWED) {
763 return;
764 }
765
766 String url = createTelUrl(number);
767 if (url == null) {
768 return;
769 }
770
Wink Saville08874612014-08-31 19:19:58 -0700771 boolean isValid = false;
Wink Saville10aa2e92014-09-04 10:46:34 -0700772 List<SubInfoRecord> slist = SubscriptionManager.getActiveSubInfoList();
Wink Saville08874612014-08-31 19:19:58 -0700773 for (SubInfoRecord subInfoRecord : slist) {
Wink Savilleb30c9a22014-09-04 22:42:02 -0700774 if (subInfoRecord.subId == subId) {
Wink Saville08874612014-08-31 19:19:58 -0700775 isValid = true;
776 break;
777 }
778 }
779 if (isValid == false) {
780 return;
781 }
782
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700783 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
Wink Saville36469e72014-06-11 15:17:00 -0700784 intent.putExtra(SUBSCRIPTION_KEY, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700785 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
786 mApp.startActivity(intent);
787 }
788
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700789 /**
790 * End a call based on call state
791 * @return true is a call was ended
792 */
793 public boolean endCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700794 return endCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700795 }
796
797 /**
798 * End a call based on the call state of the subId
799 * @return true is a call was ended
800 */
Wink Savilleadd7cc52014-09-08 14:23:09 -0700801 public boolean endCallForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700802 enforceCallPermission();
Wink Saville08874612014-08-31 19:19:58 -0700803 return (Boolean) sendRequest(CMD_END_CALL, new Long(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700804 }
805
806 public void answerRingingCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700807 answerRingingCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700808 }
809
Wink Savilleadd7cc52014-09-08 14:23:09 -0700810 public void answerRingingCallForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700811 if (DBG) log("answerRingingCall...");
812 // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
813 // but that can probably wait till the big TelephonyManager API overhaul.
814 // For now, protect this call with the MODIFY_PHONE_STATE permission.
815 enforceModifyPermission();
Wink Saville08874612014-08-31 19:19:58 -0700816 sendRequest(CMD_ANSWER_RINGING_CALL, new Long(subId), null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700817 }
818
819 /**
820 * Make the actual telephony calls to implement answerRingingCall().
821 * This should only be called from the main thread of the Phone app.
822 * @see #answerRingingCall
823 *
824 * TODO: it would be nice to return true if we answered the call, or
825 * false if there wasn't actually a ringing incoming call, or some
826 * other error occurred. (In other words, pass back the return value
827 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
828 * But that would require calling this method via sendRequest() rather
829 * than sendRequestAsync(), and right now we don't actually *need* that
830 * return value, so let's just return void for now.
831 */
Wink Saville08874612014-08-31 19:19:58 -0700832 private void answerRingingCallInternal(long subId) {
833 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700834 if (hasRingingCall) {
Wink Saville08874612014-08-31 19:19:58 -0700835 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
836 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700837 if (hasActiveCall && hasHoldingCall) {
838 // Both lines are in use!
839 // TODO: provide a flag to let the caller specify what
840 // policy to use if both lines are in use. (The current
841 // behavior is hardwired to "answer incoming, end ongoing",
842 // which is how the CALL button is specced to behave.)
843 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
844 return;
845 } else {
846 // answerCall() will automatically hold the current active
847 // call, if there is one.
848 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
849 return;
850 }
851 } else {
852 // No call was ringing.
853 return;
854 }
855 }
856
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700857 /**
Santos Cordon5422a8d2014-09-12 04:20:56 -0700858 * This method is no longer used and can be removed once TelephonyManager stops referring to it.
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700859 */
Santos Cordon5422a8d2014-09-12 04:20:56 -0700860 public void silenceRinger() {
861 Log.e(LOG_TAG, "silenseRinger not supported");
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700862 }
863
864 public boolean isOffhook() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700865 return isOffhookForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700866 }
867
Wink Savilleadd7cc52014-09-08 14:23:09 -0700868 public boolean isOffhookForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700869 return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700870 }
871
872 public boolean isRinging() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700873 return (isRingingForSubscriber(getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -0700874 }
875
Wink Savilleadd7cc52014-09-08 14:23:09 -0700876 public boolean isRingingForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700877 return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700878 }
879
880 public boolean isIdle() {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700881 return isIdleForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -0700882 }
883
Wink Savilleadd7cc52014-09-08 14:23:09 -0700884 public boolean isIdleForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -0700885 return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700886 }
887
888 public boolean isSimPinEnabled() {
889 enforceReadPermission();
890 return (PhoneGlobals.getInstance().isSimPinEnabled());
891 }
892
893 public boolean supplyPin(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700894 return supplyPinForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -0700895 }
896
Wink Savilleadd7cc52014-09-08 14:23:09 -0700897 public boolean supplyPinForSubscriber(long subId, String pin) {
898 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700899 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
900 }
901
902 public boolean supplyPuk(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700903 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -0700904 }
905
Wink Savilleadd7cc52014-09-08 14:23:09 -0700906 public boolean supplyPukForSubscriber(long subId, String puk, String pin) {
907 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -0700908 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
909 }
910
911 /** {@hide} */
912 public int[] supplyPinReportResult(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700913 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -0700914 }
915
Wink Savilleadd7cc52014-09-08 14:23:09 -0700916 public int[] supplyPinReportResultForSubscriber(long subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700917 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700918 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700919 checkSimPin.start();
920 return checkSimPin.unlockSim(null, pin);
921 }
922
Wink Saville9de0f752013-10-22 19:04:03 -0700923 /** {@hide} */
924 public int[] supplyPukReportResult(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700925 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -0700926 }
927
Wink Savilleadd7cc52014-09-08 14:23:09 -0700928 public int[] supplyPukReportResultForSubscriber(long subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700929 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -0700930 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700931 checkSimPuk.start();
932 return checkSimPuk.unlockSim(puk, pin);
933 }
934
935 /**
Wink Saville9de0f752013-10-22 19:04:03 -0700936 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700937 * a synchronous one.
938 */
939 private static class UnlockSim extends Thread {
940
941 private final IccCard mSimCard;
942
943 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -0700944 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
945 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700946
947 // For replies from SimCard interface
948 private Handler mHandler;
949
950 // For async handler to identify request type
951 private static final int SUPPLY_PIN_COMPLETE = 100;
952
953 public UnlockSim(IccCard simCard) {
954 mSimCard = simCard;
955 }
956
957 @Override
958 public void run() {
959 Looper.prepare();
960 synchronized (UnlockSim.this) {
961 mHandler = new Handler() {
962 @Override
963 public void handleMessage(Message msg) {
964 AsyncResult ar = (AsyncResult) msg.obj;
965 switch (msg.what) {
966 case SUPPLY_PIN_COMPLETE:
967 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
968 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -0700969 mRetryCount = msg.arg1;
970 if (ar.exception != null) {
971 if (ar.exception instanceof CommandException &&
972 ((CommandException)(ar.exception)).getCommandError()
973 == CommandException.Error.PASSWORD_INCORRECT) {
974 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
975 } else {
976 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
977 }
978 } else {
979 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
980 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700981 mDone = true;
982 UnlockSim.this.notifyAll();
983 }
984 break;
985 }
986 }
987 };
988 UnlockSim.this.notifyAll();
989 }
990 Looper.loop();
991 }
992
993 /*
994 * Use PIN or PUK to unlock SIM card
995 *
996 * If PUK is null, unlock SIM card with PIN
997 *
998 * If PUK is not null, unlock SIM card with PUK and set PIN code
999 */
Wink Saville9de0f752013-10-22 19:04:03 -07001000 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001001
1002 while (mHandler == null) {
1003 try {
1004 wait();
1005 } catch (InterruptedException e) {
1006 Thread.currentThread().interrupt();
1007 }
1008 }
1009 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1010
1011 if (puk == null) {
1012 mSimCard.supplyPin(pin, callback);
1013 } else {
1014 mSimCard.supplyPuk(puk, pin, callback);
1015 }
1016
1017 while (!mDone) {
1018 try {
1019 Log.d(LOG_TAG, "wait for done");
1020 wait();
1021 } catch (InterruptedException e) {
1022 // Restore the interrupted status
1023 Thread.currentThread().interrupt();
1024 }
1025 }
1026 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001027 int[] resultArray = new int[2];
1028 resultArray[0] = mResult;
1029 resultArray[1] = mRetryCount;
1030 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001031 }
1032 }
1033
1034 public void updateServiceLocation() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001035 updateServiceLocationForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001036
1037 }
1038
Wink Savilleadd7cc52014-09-08 14:23:09 -07001039 public void updateServiceLocationForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001040 // No permission check needed here: this call is harmless, and it's
1041 // needed for the ServiceState.requestStateUpdate() call (which is
1042 // already intentionally exposed to 3rd parties.)
Wink Saville36469e72014-06-11 15:17:00 -07001043 getPhone(subId).updateServiceLocation();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001044 }
1045
1046 public boolean isRadioOn() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001047 return isRadioOnForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001048 }
1049
Wink Savilleadd7cc52014-09-08 14:23:09 -07001050 public boolean isRadioOnForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001051 return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001052 }
1053
1054 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001055 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001056
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001057 }
Wink Saville36469e72014-06-11 15:17:00 -07001058
Wink Savilleadd7cc52014-09-08 14:23:09 -07001059 public void toggleRadioOnOffForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001060 enforceModifyPermission();
Wink Savilleadd7cc52014-09-08 14:23:09 -07001061 getPhone(subId).setRadioPower(!isRadioOnForSubscriber(subId));
Wink Saville36469e72014-06-11 15:17:00 -07001062 }
1063
1064 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001065 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001066 }
1067
Wink Savilleadd7cc52014-09-08 14:23:09 -07001068 public boolean setRadioForSubscriber(long subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001069 enforceModifyPermission();
1070 if ((getPhone(subId).getServiceState().getState() !=
1071 ServiceState.STATE_POWER_OFF) != turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001072 toggleRadioOnOffForSubscriber(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001073 }
1074 return true;
1075 }
Wink Saville36469e72014-06-11 15:17:00 -07001076
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001077 public boolean needMobileRadioShutdown() {
1078 /*
1079 * If any of the Radios are available, it will need to be
1080 * shutdown. So return true if any Radio is available.
1081 */
1082 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1083 Phone phone = PhoneFactory.getPhone(i);
1084 if (phone != null && phone.isRadioAvailable()) return true;
1085 }
1086 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1087 return false;
1088 }
1089
1090 public void shutdownMobileRadios() {
1091 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1092 logv("Shutting down Phone " + i);
1093 shutdownRadioUsingPhoneId(i);
1094 }
1095 }
1096
1097 private void shutdownRadioUsingPhoneId(int phoneId) {
1098 enforceModifyPermission();
1099 Phone phone = PhoneFactory.getPhone(phoneId);
1100 if (phone != null && phone.isRadioAvailable()) {
1101 phone.shutdownRadio();
1102 }
1103 }
1104
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001105 public boolean setRadioPower(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001106 return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001107 }
1108
Wink Savilleadd7cc52014-09-08 14:23:09 -07001109 public boolean setRadioPowerForSubscriber(long subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001110 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001111 getPhone(subId).setRadioPower(turnOn);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001112 return true;
1113 }
1114
Wink Saville36469e72014-06-11 15:17:00 -07001115 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001116 public boolean enableDataConnectivity() {
1117 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001118 long subId = SubscriptionManager.getDefaultDataSubId();
1119 getPhone(subId).setDataEnabled(true);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001120 return true;
1121 }
1122
Wink Saville36469e72014-06-11 15:17:00 -07001123 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001124 public boolean disableDataConnectivity() {
1125 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001126 long subId = SubscriptionManager.getDefaultDataSubId();
1127 getPhone(subId).setDataEnabled(false);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001128 return true;
1129 }
1130
Wink Saville36469e72014-06-11 15:17:00 -07001131 // FIXME: subId version needed
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001132 public boolean isDataConnectivityPossible() {
Wink Saville36469e72014-06-11 15:17:00 -07001133 long subId = SubscriptionManager.getDefaultDataSubId();
1134 return getPhone(subId).isDataConnectivityPossible();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001135 }
1136
1137 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001138 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07001139 }
1140
Wink Savilleadd7cc52014-09-08 14:23:09 -07001141 public boolean handlePinMmiForSubscriber(long subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001142 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001143 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001144 }
1145
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001146 public int getCallState() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001147 return getCallStateForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001148 }
1149
Wink Savilleadd7cc52014-09-08 14:23:09 -07001150 public int getCallStateForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001151 return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001152 }
1153
1154 public int getDataState() {
Wink Saville36469e72014-06-11 15:17:00 -07001155 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1156 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001157 }
1158
1159 public int getDataActivity() {
Wink Saville36469e72014-06-11 15:17:00 -07001160 Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
1161 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001162 }
1163
1164 @Override
1165 public Bundle getCellLocation() {
1166 try {
1167 mApp.enforceCallingOrSelfPermission(
1168 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1169 } catch (SecurityException e) {
1170 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1171 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1172 // is the weaker precondition
1173 mApp.enforceCallingOrSelfPermission(
1174 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1175 }
1176
Jake Hambye994d462014-02-03 13:10:13 -08001177 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001178 if (DBG_LOC) log("getCellLocation: is active user");
1179 Bundle data = new Bundle();
1180 mPhone.getCellLocation().fillInNotifierBundle(data);
1181 return data;
1182 } else {
1183 if (DBG_LOC) log("getCellLocation: suppress non-active user");
1184 return null;
1185 }
1186 }
1187
1188 @Override
1189 public void enableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001190 enableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001191 }
1192
Wink Savilleadd7cc52014-09-08 14:23:09 -07001193 public void enableLocationUpdatesForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001194 mApp.enforceCallingOrSelfPermission(
1195 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001196 getPhone(subId).enableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001197 }
1198
1199 @Override
1200 public void disableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001201 disableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001202 }
1203
Wink Savilleadd7cc52014-09-08 14:23:09 -07001204 public void disableLocationUpdatesForSubscriber(long subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001205 mApp.enforceCallingOrSelfPermission(
1206 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Wink Saville36469e72014-06-11 15:17:00 -07001207 getPhone(subId).disableLocationUpdates();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001208 }
1209
1210 @Override
1211 @SuppressWarnings("unchecked")
1212 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1213 try {
1214 mApp.enforceCallingOrSelfPermission(
1215 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1216 } catch (SecurityException e) {
1217 // If we have ACCESS_FINE_LOCATION permission, skip the check
1218 // for ACCESS_COARSE_LOCATION
1219 // A failure should throw the SecurityException from
1220 // ACCESS_COARSE_LOCATION since this is the weaker precondition
1221 mApp.enforceCallingOrSelfPermission(
1222 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1223 }
1224
1225 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1226 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1227 return null;
1228 }
Jake Hambye994d462014-02-03 13:10:13 -08001229 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001230 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1231
1232 ArrayList<NeighboringCellInfo> cells = null;
1233
1234 try {
1235 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
Wink Saville36469e72014-06-11 15:17:00 -07001236 CMD_HANDLE_NEIGHBORING_CELL, null, null);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001237 } catch (RuntimeException e) {
Wink Saville36469e72014-06-11 15:17:00 -07001238 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001239 }
1240 return cells;
1241 } else {
1242 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1243 return null;
1244 }
1245 }
1246
1247
1248 @Override
1249 public List<CellInfo> getAllCellInfo() {
1250 try {
1251 mApp.enforceCallingOrSelfPermission(
1252 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1253 } catch (SecurityException e) {
1254 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1255 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1256 // is the weaker precondition
1257 mApp.enforceCallingOrSelfPermission(
1258 android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
1259 }
1260
Jake Hambye994d462014-02-03 13:10:13 -08001261 if (checkIfCallerIsSelfOrForegroundUser()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001262 if (DBG_LOC) log("getAllCellInfo: is active user");
1263 return mPhone.getAllCellInfo();
1264 } else {
1265 if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1266 return null;
1267 }
1268 }
1269
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001270 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001271 public void setCellInfoListRate(int rateInMillis) {
1272 mPhone.setCellInfoListRate(rateInMillis);
1273 }
1274
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001275 //
1276 // Internal helper methods.
1277 //
1278
Jake Hambye994d462014-02-03 13:10:13 -08001279 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001280 boolean ok;
1281
1282 boolean self = Binder.getCallingUid() == Process.myUid();
1283 if (!self) {
1284 // Get the caller's user id then clear the calling identity
1285 // which will be restored in the finally clause.
1286 int callingUser = UserHandle.getCallingUserId();
1287 long ident = Binder.clearCallingIdentity();
1288
1289 try {
1290 // With calling identity cleared the current user is the foreground user.
1291 int foregroundUser = ActivityManager.getCurrentUser();
1292 ok = (foregroundUser == callingUser);
1293 if (DBG_LOC) {
1294 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1295 + " callingUser=" + callingUser + " ok=" + ok);
1296 }
1297 } catch (Exception ex) {
1298 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1299 ok = false;
1300 } finally {
1301 Binder.restoreCallingIdentity(ident);
1302 }
1303 } else {
1304 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1305 ok = true;
1306 }
1307 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1308 return ok;
1309 }
1310
1311 /**
1312 * Make sure the caller has the READ_PHONE_STATE permission.
1313 *
1314 * @throws SecurityException if the caller does not have the required permission
1315 */
1316 private void enforceReadPermission() {
1317 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
1318 }
1319
1320 /**
1321 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1322 *
1323 * @throws SecurityException if the caller does not have the required permission
1324 */
1325 private void enforceModifyPermission() {
1326 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1327 }
1328
1329 /**
Junda Liua2e36012014-07-09 18:30:01 -07001330 * Make sure either system app or the caller has carrier privilege.
1331 *
1332 * @throws SecurityException if the caller does not have the required permission/privilege
1333 */
1334 private void enforceModifyPermissionOrCarrierPrivilege() {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001335 int permission = mApp.checkCallingOrSelfPermission(
1336 android.Manifest.permission.MODIFY_PHONE_STATE);
1337 if (permission == PackageManager.PERMISSION_GRANTED) {
1338 return;
1339 }
1340
1341 log("No modify permission, check carrier privilege next.");
1342 if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1343 loge("No Carrier Privilege.");
1344 throw new SecurityException("No modify permission or carrier privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001345 }
1346 }
1347
1348 /**
1349 * Make sure the caller has carrier privilege.
1350 *
1351 * @throws SecurityException if the caller does not have the required permission
1352 */
1353 private void enforceCarrierPrivilege() {
1354 if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001355 loge("No Carrier Privilege.");
1356 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001357 }
1358 }
1359
1360 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001361 * Make sure the caller has the CALL_PHONE permission.
1362 *
1363 * @throws SecurityException if the caller does not have the required permission
1364 */
1365 private void enforceCallPermission() {
1366 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1367 }
1368
Shishir Agrawal566b7612013-10-28 14:41:00 -07001369 /**
Gabriel Peal36ebb0d2014-03-20 09:20:43 -07001370 * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
1371 *
1372 * @throws SecurityException if the caller does not have the required permission
1373 */
1374 private void enforcePrivilegedPhoneStatePermission() {
1375 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
1376 null);
1377 }
1378
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001379 private String createTelUrl(String number) {
1380 if (TextUtils.isEmpty(number)) {
1381 return null;
1382 }
1383
Jake Hambye994d462014-02-03 13:10:13 -08001384 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001385 }
1386
Ihab Awadf9e92732013-12-05 18:02:52 -08001387 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001388 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1389 }
1390
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001391 private static void logv(String msg) {
1392 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1393 }
1394
Ihab Awadf9e92732013-12-05 18:02:52 -08001395 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001396 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1397 }
1398
1399 public int getActivePhoneType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001400 return getActivePhoneTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001401 }
1402
Wink Savilleadd7cc52014-09-08 14:23:09 -07001403 public int getActivePhoneTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001404 return getPhone(subId).getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001405 }
1406
1407 /**
1408 * Returns the CDMA ERI icon index to display
1409 */
1410 public int getCdmaEriIconIndex() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001411 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001412
1413 }
1414
Wink Savilleadd7cc52014-09-08 14:23:09 -07001415 public int getCdmaEriIconIndexForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001416 return getPhone(subId).getCdmaEriIconIndex();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001417 }
1418
1419 /**
1420 * Returns the CDMA ERI icon mode,
1421 * 0 - ON
1422 * 1 - FLASHING
1423 */
1424 public int getCdmaEriIconMode() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001425 return getCdmaEriIconModeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001426 }
1427
Wink Savilleadd7cc52014-09-08 14:23:09 -07001428 public int getCdmaEriIconModeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001429 return getPhone(subId).getCdmaEriIconMode();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001430 }
1431
1432 /**
1433 * Returns the CDMA ERI text,
1434 */
1435 public String getCdmaEriText() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001436 return getCdmaEriTextForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001437 }
1438
Wink Savilleadd7cc52014-09-08 14:23:09 -07001439 public String getCdmaEriTextForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001440 return getPhone(subId).getCdmaEriText();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001441 }
1442
1443 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001444 * Returns the CDMA MDN.
1445 */
1446 public String getCdmaMdn(long subId) {
1447 enforceModifyPermissionOrCarrierPrivilege();
1448 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1449 return getPhone(subId).getLine1Number();
1450 } else {
1451 return null;
1452 }
1453 }
1454
1455 /**
1456 * Returns the CDMA MIN.
1457 */
1458 public String getCdmaMin(long subId) {
1459 enforceModifyPermissionOrCarrierPrivilege();
1460 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1461 return getPhone(subId).getCdmaMin();
1462 } else {
1463 return null;
1464 }
1465 }
1466
1467 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001468 * Returns true if CDMA provisioning needs to run.
1469 */
1470 public boolean needsOtaServiceProvisioning() {
1471 return mPhone.needsOtaServiceProvisioning();
1472 }
1473
1474 /**
1475 * Returns the unread count of voicemails
1476 */
1477 public int getVoiceMessageCount() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001478 return getVoiceMessageCountForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001479 }
1480
1481 /**
1482 * Returns the unread count of voicemails for a subId
1483 */
Wink Savilleadd7cc52014-09-08 14:23:09 -07001484 public int getVoiceMessageCountForSubscriber( long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001485 return getPhone(subId).getVoiceMessageCount();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001486 }
1487
1488 /**
1489 * Returns the data network type
1490 *
1491 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
1492 */
1493 @Override
1494 public int getNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001495 return getNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001496 }
1497
1498 /**
1499 * Returns the network type for a subId
1500 */
1501 @Override
Wink Savilleadd7cc52014-09-08 14:23:09 -07001502 public int getNetworkTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001503 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001504 }
1505
1506 /**
1507 * Returns the data network type
1508 */
1509 @Override
1510 public int getDataNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001511 return getDataNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001512 }
1513
1514 /**
1515 * Returns the data network type for a subId
1516 */
1517 @Override
Wink Savilleadd7cc52014-09-08 14:23:09 -07001518 public int getDataNetworkTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001519 return getPhone(subId).getServiceState().getDataNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001520 }
1521
1522 /**
1523 * Returns the data network type
1524 */
1525 @Override
1526 public int getVoiceNetworkType() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001527 return getVoiceNetworkTypeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001528 }
1529
1530 /**
1531 * Returns the Voice network type for a subId
1532 */
1533 @Override
Wink Savilleadd7cc52014-09-08 14:23:09 -07001534 public int getVoiceNetworkTypeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001535 return getPhone(subId).getServiceState().getVoiceNetworkType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001536 }
1537
1538 /**
1539 * @return true if a ICC card is present
1540 */
1541 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07001542 // FIXME Make changes to pass defaultSimId of type int
1543 return hasIccCardUsingSlotId(getDefaultSubscription());
1544 }
1545
1546 /**
1547 * @return true if a ICC card is present for a slotId
1548 */
1549 public boolean hasIccCardUsingSlotId(long slotId) {
1550 return getPhone(slotId).getIccCard().hasIccCard();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001551 }
1552
1553 /**
1554 * Return if the current radio is LTE on CDMA. This
1555 * is a tri-state return value as for a period of time
1556 * the mode may be unknown.
1557 *
1558 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08001559 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001560 */
1561 public int getLteOnCdmaMode() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001562 return getLteOnCdmaModeForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001563 }
1564
Wink Savilleadd7cc52014-09-08 14:23:09 -07001565 public int getLteOnCdmaModeForSubscriber(long subId) {
Wink Saville36469e72014-06-11 15:17:00 -07001566 return getPhone(subId).getLteOnCdmaMode();
1567 }
1568
1569 public void setPhone(Phone phone) {
1570 mPhone = phone;
1571 }
1572
1573 /**
1574 * {@hide}
1575 * Returns Default subId, 0 in the case of single standby.
1576 */
1577 private long getDefaultSubscription() {
1578 return SubscriptionManager.getDefaultSubId();
1579 }
1580
1581 private long getPreferredVoiceSubscription() {
1582 return SubscriptionManager.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001583 }
Ihab Awadf2177b72013-11-25 13:33:23 -08001584
1585 /**
1586 * @see android.telephony.TelephonyManager.WifiCallingChoices
1587 */
1588 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001589 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1590 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08001591 }
1592
1593 /**
1594 * @see android.telephony.TelephonyManager.WifiCallingChoices
1595 */
1596 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08001597 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1598 Settings.System.putInt(mPhone.getContext().getContentResolver(),
1599 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08001600 }
1601
Sailesh Nepald1e68152013-12-12 19:08:02 -08001602 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07001603 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08001604 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08001605 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08001606
Shishir Agrawal566b7612013-10-28 14:41:00 -07001607 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001608 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
Junda Liua2e36012014-07-09 18:30:01 -07001609 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001610
1611 if (DBG) log("iccOpenLogicalChannel: " + AID);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001612 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1613 CMD_OPEN_CHANNEL, AID);
1614 if (DBG) log("iccOpenLogicalChannel: " + response);
1615 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07001616 }
1617
1618 @Override
1619 public boolean iccCloseLogicalChannel(int channel) {
Junda Liua2e36012014-07-09 18:30:01 -07001620 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001621
1622 if (DBG) log("iccCloseLogicalChannel: " + channel);
1623 if (channel < 0) {
1624 return false;
1625 }
Jake Hambye994d462014-02-03 13:10:13 -08001626 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07001627 if (DBG) log("iccCloseLogicalChannel: " + success);
1628 return success;
1629 }
1630
1631 @Override
1632 public String iccTransmitApduLogicalChannel(int channel, int cla,
1633 int command, int p1, int p2, int p3, String data) {
Junda Liua2e36012014-07-09 18:30:01 -07001634 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawal566b7612013-10-28 14:41:00 -07001635
1636 if (DBG) {
1637 log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1638 " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1639 " data=" + data);
1640 }
1641
1642 if (channel < 0) {
1643 return "";
1644 }
1645
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001646 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawal566b7612013-10-28 14:41:00 -07001647 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1648 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1649
Shishir Agrawal566b7612013-10-28 14:41:00 -07001650 // Append the returned status code to the end of the response payload.
1651 String s = Integer.toHexString(
1652 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001653 if (response.payload != null) {
1654 s = IccUtils.bytesToHexString(response.payload) + s;
1655 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07001656 return s;
1657 }
Jake Hambye994d462014-02-03 13:10:13 -08001658
Evan Charltonc66da362014-05-16 14:06:40 -07001659 @Override
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001660 public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1661 int p3, String data) {
1662 enforceModifyPermissionOrCarrierPrivilege();
1663
1664 if (DBG) {
1665 log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1666 + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1667 }
1668
1669 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1670 new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1671 if (DBG) log("iccTransmitApduBasicChannel: " + response);
1672
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001673 // Append the returned status code to the end of the response payload.
1674 String s = Integer.toHexString(
1675 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07001676 if (response.payload != null) {
1677 s = IccUtils.bytesToHexString(response.payload) + s;
1678 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001679 return s;
1680 }
1681
1682 @Override
1683 public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1684 String filePath) {
1685 enforceModifyPermissionOrCarrierPrivilege();
1686
1687 if (DBG) {
1688 log("Exchange SIM_IO " + fileID + ":" + command + " " +
1689 p1 + " " + p2 + " " + p3 + ":" + filePath);
1690 }
1691
1692 IccIoResult response =
1693 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
Yong Jiang3edf3782014-10-03 13:23:28 -05001694 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath));
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07001695
1696 if (DBG) {
1697 log("Exchange SIM_IO [R]" + response);
1698 }
1699
1700 byte[] result = null;
1701 int length = 2;
1702 if (response.payload != null) {
1703 length = 2 + response.payload.length;
1704 result = new byte[length];
1705 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1706 } else {
1707 result = new byte[length];
1708 }
1709
1710 result[length - 1] = (byte) response.sw2;
1711 result[length - 2] = (byte) response.sw1;
1712 return result;
1713 }
1714
1715 @Override
Evan Charltonc66da362014-05-16 14:06:40 -07001716 public String sendEnvelopeWithStatus(String content) {
Junda Liua2e36012014-07-09 18:30:01 -07001717 enforceModifyPermissionOrCarrierPrivilege();
Evan Charltonc66da362014-05-16 14:06:40 -07001718
1719 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1720 if (response.payload == null) {
1721 return "";
1722 }
1723
1724 // Append the returned status code to the end of the response payload.
1725 String s = Integer.toHexString(
1726 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1727 s = IccUtils.bytesToHexString(response.payload) + s;
1728 return s;
1729 }
1730
Jake Hambye994d462014-02-03 13:10:13 -08001731 /**
1732 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1733 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1734 *
1735 * @param itemID the ID of the item to read
1736 * @return the NV item as a String, or null on error.
1737 */
1738 @Override
1739 public String nvReadItem(int itemID) {
Junda Liua2e36012014-07-09 18:30:01 -07001740 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001741 if (DBG) log("nvReadItem: item " + itemID);
1742 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1743 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1744 return value;
1745 }
1746
1747 /**
1748 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1749 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1750 *
1751 * @param itemID the ID of the item to read
1752 * @param itemValue the value to write, as a String
1753 * @return true on success; false on any failure
1754 */
1755 @Override
1756 public boolean nvWriteItem(int itemID, String itemValue) {
Junda Liua2e36012014-07-09 18:30:01 -07001757 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001758 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1759 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1760 new Pair<Integer, String>(itemID, itemValue));
1761 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1762 return success;
1763 }
1764
1765 /**
1766 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1767 * Used for device configuration by some CDMA operators.
1768 *
1769 * @param preferredRoamingList byte array containing the new PRL
1770 * @return true on success; false on any failure
1771 */
1772 @Override
1773 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Junda Liua2e36012014-07-09 18:30:01 -07001774 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001775 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1776 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1777 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1778 return success;
1779 }
1780
1781 /**
1782 * Perform the specified type of NV config reset.
1783 * Used for device configuration by some CDMA operators.
1784 *
1785 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1786 * @return true on success; false on any failure
1787 */
1788 @Override
1789 public boolean nvResetConfig(int resetType) {
Junda Liua2e36012014-07-09 18:30:01 -07001790 enforceModifyPermissionOrCarrierPrivilege();
Jake Hambye994d462014-02-03 13:10:13 -08001791 if (DBG) log("nvResetConfig: type " + resetType);
1792 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1793 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1794 return success;
1795 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001796
1797 /**
Wink Saville36469e72014-06-11 15:17:00 -07001798 * {@hide}
1799 * Returns Default sim, 0 in the case of single standby.
1800 */
1801 public int getDefaultSim() {
1802 //TODO Need to get it from Telephony Devcontroller
1803 return 0;
1804 }
1805
ram87fca6f2014-07-18 18:58:44 +05301806 public String[] getPcscfAddress(String apnType) {
Wink Saville36469e72014-06-11 15:17:00 -07001807 enforceReadPermission();
ram87fca6f2014-07-18 18:58:44 +05301808 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07001809 }
1810
1811 public void setImsRegistrationState(boolean registered) {
1812 enforceModifyPermission();
1813 mPhone.setImsRegistrationState(registered);
1814 }
1815
1816 /**
Junda Liu84d15a22014-07-02 11:21:04 -07001817 * Get the calculated preferred network type.
1818 * Used for debugging incorrect network type.
1819 *
1820 * @return the preferred network type, defined in RILConstants.java.
1821 */
1822 @Override
1823 public int getCalculatedPreferredNetworkType() {
1824 enforceReadPermission();
Wink Saville08874612014-08-31 19:19:58 -07001825 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get PhoneId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07001826 }
1827
1828 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08001829 * Get the preferred network type.
1830 * Used for device configuration by some CDMA operators.
1831 *
1832 * @return the preferred network type, defined in RILConstants.java.
1833 */
1834 @Override
1835 public int getPreferredNetworkType() {
Junda Liua2e36012014-07-09 18:30:01 -07001836 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001837 if (DBG) log("getPreferredNetworkType");
1838 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
1839 int networkType = (result != null ? result[0] : -1);
1840 if (DBG) log("getPreferredNetworkType: " + networkType);
1841 return networkType;
1842 }
1843
1844 /**
1845 * Set the preferred network type.
1846 * Used for device configuration by some CDMA operators.
1847 *
1848 * @param networkType the preferred network type, defined in RILConstants.java.
1849 * @return true on success; false on any failure.
1850 */
1851 @Override
1852 public boolean setPreferredNetworkType(int networkType) {
Junda Liua2e36012014-07-09 18:30:01 -07001853 enforceModifyPermissionOrCarrierPrivilege();
Jake Hamby7c27be32014-03-03 13:25:59 -08001854 if (DBG) log("setPreferredNetworkType: type " + networkType);
1855 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
1856 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07001857 if (success) {
1858 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
1859 Settings.Global.PREFERRED_NETWORK_MODE, networkType);
1860 }
Jake Hamby7c27be32014-03-03 13:25:59 -08001861 return success;
1862 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001863
1864 /**
1865 * Set mobile data enabled
1866 * Used by the user through settings etc to turn on/off mobile data
1867 *
1868 * @param enable {@code true} turn turn data on, else {@code false}
1869 */
1870 @Override
1871 public void setDataEnabled(boolean enable) {
1872 enforceModifyPermission();
1873 mPhone.setDataEnabled(enable);
1874 }
1875
1876 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07001877 * Get whether mobile data is enabled.
1878 *
1879 * Note that this used to be available from ConnectivityService, gated by
1880 * ACCESS_NETWORK_STATE permission, so this will accept either that or
1881 * our MODIFY_PHONE_STATE.
Robert Greenwalted86e582014-05-21 20:03:20 -07001882 *
1883 * @return {@code true} if data is enabled else {@code false}
1884 */
1885 @Override
1886 public boolean getDataEnabled() {
Robert Greenwalt646120a2014-05-23 11:54:03 -07001887 try {
1888 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1889 null);
1890 } catch (Exception e) {
1891 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1892 null);
1893 }
Robert Greenwalted86e582014-05-21 20:03:20 -07001894 return mPhone.getDataEnabled();
1895 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001896
1897 @Override
1898 public int hasCarrierPrivileges() {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001899 UiccCard card = UiccController.getInstance().getUiccCard();
1900 if (card == null) {
1901 loge("hasCarrierPrivileges: No UICC");
1902 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1903 }
1904 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001905 mPhone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07001906 }
Junda Liu29340342014-07-10 15:23:27 -07001907
1908 @Override
Shishir Agrawal6d5a2852014-07-11 16:32:57 -07001909 public int checkCarrierPrivilegesForPackage(String pkgname) {
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07001910 UiccCard card = UiccController.getInstance().getUiccCard();
1911 if (card == null) {
1912 loge("checkCarrierPrivilegesForPackage: No UICC");
1913 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1914 }
1915 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
Junda Liu29340342014-07-10 15:23:27 -07001916 }
Derek Tan89e89d42014-07-08 17:00:10 -07001917
1918 @Override
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001919 public List<String> getCarrierPackageNamesForIntent(Intent intent) {
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001920 UiccCard card = UiccController.getInstance().getUiccCard();
1921 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001922 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001923 return null ;
1924 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07001925 return card.getCarrierPackageNamesForIntent(
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001926 mPhone.getContext().getPackageManager(), intent);
1927 }
1928
Derek Tan97ebb422014-09-05 16:55:38 -07001929 private String getIccId(long subId) {
1930 UiccCard card = getPhone(subId).getUiccCard();
1931 if (card == null) {
1932 loge("getIccId: No UICC");
1933 return null;
1934 }
1935 String iccId = card.getIccId();
1936 if (TextUtils.isEmpty(iccId)) {
1937 loge("getIccId: ICC ID is null or empty.");
1938 return null;
1939 }
1940 return iccId;
1941 }
1942
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07001943 @Override
Junda Liudf6b6b92014-09-05 18:13:46 -07001944 public void enableSimplifiedNetworkSettingsForSubscriber(long subId, boolean enable) {
Derek Tan352d8cd2014-07-12 12:57:11 -07001945 enforceModifyPermissionOrCarrierPrivilege();
Derek Tan97ebb422014-09-05 16:55:38 -07001946
1947 String iccId = getIccId(subId);
1948 if (iccId != null) {
1949 String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
1950 SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
1951 if (enable) {
1952 editor.putBoolean(snsPrefKey, true);
1953 } else {
1954 editor.remove(snsPrefKey);
1955 }
1956 editor.commit();
Derek Tan89e89d42014-07-08 17:00:10 -07001957 }
1958 }
1959
1960 @Override
Junda Liudf6b6b92014-09-05 18:13:46 -07001961 public boolean getSimplifiedNetworkSettingsEnabledForSubscriber(long subId) {
Derek Tan89e89d42014-07-08 17:00:10 -07001962 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07001963 String iccId = getIccId(subId);
1964 if (iccId != null) {
1965 String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
1966 return carrierPrivilegeConfigs.getBoolean(snsPrefKey, false);
1967 }
1968 return false;
Derek Tan89e89d42014-07-08 17:00:10 -07001969 }
Derek Tan7226c842014-07-02 17:42:23 -07001970
1971 @Override
Junda Liudf6b6b92014-09-05 18:13:46 -07001972 public void setLine1NumberForDisplayForSubscriber(long subId, String alphaTag, String number) {
Derek Tan352d8cd2014-07-12 12:57:11 -07001973 enforceModifyPermissionOrCarrierPrivilege();
Derek Tan97ebb422014-09-05 16:55:38 -07001974
1975 String iccId = getIccId(subId);
1976 if (iccId != null) {
1977 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
1978 SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
1979 if (alphaTag == null) {
1980 editor.remove(alphaTagPrefKey);
1981 } else {
1982 editor.putString(alphaTagPrefKey, alphaTag);
1983 }
1984
1985 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
1986 if (number == null) {
1987 editor.remove(numberPrefKey);
1988 } else {
1989 editor.putString(numberPrefKey, number);
1990 }
1991 editor.commit();
1992 }
Derek Tan7226c842014-07-02 17:42:23 -07001993 }
1994
1995 @Override
1996 public String getLine1NumberForDisplay(long subId) {
1997 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07001998
1999 String iccId = getIccId(subId);
2000 if (iccId != null) {
2001 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2002 return carrierPrivilegeConfigs.getString(numberPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002003 }
Derek Tan97ebb422014-09-05 16:55:38 -07002004 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002005 }
2006
2007 @Override
2008 public String getLine1AlphaTagForDisplay(long subId) {
2009 enforceReadPermission();
Derek Tan97ebb422014-09-05 16:55:38 -07002010
2011 String iccId = getIccId(subId);
2012 if (iccId != null) {
2013 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2014 return carrierPrivilegeConfigs.getString(alphaTagPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002015 }
Derek Tan97ebb422014-09-05 16:55:38 -07002016 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002017 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002018
2019 @Override
Shishir Agrawala3dfd752014-09-04 13:25:42 -07002020 public boolean setOperatorBrandOverride(String brand) {
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002021 enforceModifyPermissionOrCarrierPrivilege();
Shishir Agrawala3dfd752014-09-04 13:25:42 -07002022 return mPhone.setOperatorBrandOverride(brand);
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002023 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002024
2025 @Override
2026 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2027 enforceModifyPermission();
2028
2029 int returnValue = 0;
2030 try {
2031 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2032 if(result.exception == null) {
2033 if (result.result != null) {
2034 byte[] responseData = (byte[])(result.result);
2035 if(responseData.length > oemResp.length) {
2036 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2037 responseData.length + "bytes. Buffer Size is " +
2038 oemResp.length + "bytes.");
2039 }
2040 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2041 returnValue = responseData.length;
2042 }
2043 } else {
2044 CommandException ex = (CommandException) result.exception;
2045 returnValue = ex.getCommandError().ordinal();
2046 if(returnValue > 0) returnValue *= -1;
2047 }
2048 } catch (RuntimeException e) {
2049 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2050 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2051 if(returnValue > 0) returnValue *= -1;
2052 }
2053
2054 return returnValue;
2055 }
Wink Saville5d475dd2014-10-17 15:00:58 -07002056
2057 @Override
2058 public void setRadioCapability(RadioAccessFamily[] rafs) {
2059 try {
2060 ProxyController.getInstance().setRadioCapability(rafs);
2061 } catch (RuntimeException e) {
2062 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
2063 }
2064 }
2065
2066 @Override
2067 public int getRadioAccessFamily(int phoneId) {
2068 return ProxyController.getInstance().getRadioAccessFamily(phoneId);
2069 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002070}