blob: 407d05044b81006967af33a281c319eeb0847959 [file] [log] [blame]
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Ta-wei Yen87c49842016-05-13 21:19:52 -070019import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
20
Ta-wei Yen30a69c82016-12-27 14:52:32 -080021import android.Manifest.permission;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070022import android.app.ActivityManager;
23import android.app.AppOpsManager;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080024import android.app.PendingIntent;
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -070025import android.content.ComponentName;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070026import android.content.Context;
27import android.content.Intent;
Derek Tan97ebb422014-09-05 16:55:38 -070028import android.content.SharedPreferences;
Amith Yamasani6e118872016-02-19 12:53:51 -080029import android.content.pm.PackageInfo;
Shishir Agrawal60f9c952014-06-23 12:00:43 -070030import android.content.pm.PackageManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070031import android.net.Uri;
32import android.os.AsyncResult;
33import android.os.Binder;
34import android.os.Bundle;
35import android.os.Handler;
36import android.os.Looper;
37import android.os.Message;
38import android.os.Process;
Adam Lesinski903a54c2016-04-11 14:49:52 -070039import android.os.ResultReceiver;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070040import android.os.ServiceManager;
41import android.os.UserHandle;
Stuart Scott981d8582015-04-21 14:09:50 -070042import android.os.UserManager;
Sooraj Sasindran9a909312016-07-18 11:57:25 -070043import android.os.WorkSource;
Derek Tan97ebb422014-09-05 16:55:38 -070044import android.preference.PreferenceManager;
Ihab Awadf2177b72013-11-25 13:33:23 -080045import android.provider.Settings;
Meng Wang1a7c35a2016-05-05 20:56:15 -070046import android.service.carrier.CarrierIdentifier;
Santos Cordon7a1885b2015-02-03 11:15:19 -080047import android.telecom.PhoneAccount;
Nancy Chen31f9ba12016-01-06 11:42:12 -080048import android.telecom.PhoneAccountHandle;
Andrew Lee9431b832015-03-09 18:46:45 -070049import android.telecom.TelecomManager;
Junda Liu12f7d802015-05-01 12:06:44 -070050import android.telephony.CarrierConfigManager;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070051import android.telephony.CellInfo;
Sooraj Sasindran9a909312016-07-18 11:57:25 -070052import android.telephony.ClientRequestStats;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -070053import android.telephony.IccOpenLogicalChannelResponse;
Ta-wei Yen87c49842016-05-13 21:19:52 -070054import android.telephony.ModemActivityInfo;
Jake Hambye994d462014-02-03 13:10:13 -080055import android.telephony.NeighboringCellInfo;
Wink Saville5d475dd2014-10-17 15:00:58 -070056import android.telephony.RadioAccessFamily;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070057import android.telephony.ServiceState;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080058import android.telephony.SmsManager;
Wink Saville0f3b5fc2014-11-11 08:40:49 -080059import android.telephony.SubscriptionInfo;
Jeff Sharkey85190e62014-12-05 09:40:12 -080060import android.telephony.SubscriptionManager;
Sanket Padawe99ef1e32016-05-18 16:12:33 -070061import android.telephony.TelephonyHistogram;
Ta-wei Yenb6929602016-05-24 15:48:27 -070062import android.telephony.TelephonyManager;
63import android.telephony.VisualVoicemailSmsFilterSettings;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070064import android.text.TextUtils;
Jeff Sharkey85190e62014-12-05 09:40:12 -080065import android.util.ArraySet;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070066import android.util.Log;
Jake Hambye994d462014-02-03 13:10:13 -080067import android.util.Pair;
Jeff Sharkey85190e62014-12-05 09:40:12 -080068import android.util.Slog;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080069
Andrew Lee312e8172014-10-23 17:01:36 -070070import com.android.ims.ImsManager;
Shishir Agrawal566b7612013-10-28 14:41:00 -070071import com.android.internal.telephony.CallManager;
Shishir Agrawal302c8692015-06-19 13:49:39 -070072import com.android.internal.telephony.CellNetworkScanResult;
Shishir Agrawal566b7612013-10-28 14:41:00 -070073import com.android.internal.telephony.CommandException;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070074import com.android.internal.telephony.DefaultPhoneNotifier;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070075import com.android.internal.telephony.ITelephony;
Jake Hambye994d462014-02-03 13:10:13 -080076import com.android.internal.telephony.IccCard;
Narayan Kamath1c496c22015-04-16 14:40:19 +010077import com.android.internal.telephony.MccTable;
Shishir Agrawal302c8692015-06-19 13:49:39 -070078import com.android.internal.telephony.OperatorInfo;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070079import com.android.internal.telephony.Phone;
Ta-wei Yen87c49842016-05-13 21:19:52 -070080import com.android.internal.telephony.PhoneConstants;
Wink Saville36469e72014-06-11 15:17:00 -070081import com.android.internal.telephony.PhoneFactory;
Wink Saville5d475dd2014-10-17 15:00:58 -070082import com.android.internal.telephony.ProxyController;
Sanket Padawe99ef1e32016-05-18 16:12:33 -070083import com.android.internal.telephony.RIL;
Svet Ganovb320e182015-04-16 12:30:10 -070084import com.android.internal.telephony.RILConstants;
Wink Savilleac1bdfd2014-11-20 23:04:44 -080085import com.android.internal.telephony.SubscriptionController;
Shishir Agrawal566b7612013-10-28 14:41:00 -070086import com.android.internal.telephony.uicc.IccIoResult;
87import com.android.internal.telephony.uicc.IccUtils;
Shishir Agrawaleb8771e2014-07-22 11:24:08 -070088import com.android.internal.telephony.uicc.UiccCard;
Shishir Agrawal566b7612013-10-28 14:41:00 -070089import com.android.internal.telephony.uicc.UiccController;
Jake Hambye994d462014-02-03 13:10:13 -080090import com.android.internal.util.HexDump;
Ta-wei Yenb0f695b2016-08-08 17:33:11 -070091import com.android.phone.settings.VisualVoicemailSettingsUtil;
Nancy Chen31f9ba12016-01-06 11:42:12 -080092import com.android.phone.settings.VoicemailNotificationSettingsUtil;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080093
Ta-wei Yenc236d6b2016-06-21 13:33:12 -070094import java.io.FileDescriptor;
95import java.io.PrintWriter;
Ta-wei Yen30a69c82016-12-27 14:52:32 -080096import java.io.UnsupportedEncodingException;
97import java.nio.charset.StandardCharsets;
Santos Cordon7d4ddf62013-07-10 11:58:08 -070098import java.util.ArrayList;
Jeff Sharkey85190e62014-12-05 09:40:12 -080099import java.util.Arrays;
Jake Hambye994d462014-02-03 13:10:13 -0800100import java.util.List;
Narayan Kamath1c496c22015-04-16 14:40:19 +0100101import java.util.Locale;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800102import java.util.Map;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700103
104/**
105 * Implementation of the ITelephony interface.
106 */
Santos Cordon117fee72014-05-16 17:56:12 -0700107public class PhoneInterfaceManager extends ITelephony.Stub {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700108 private static final String LOG_TAG = "PhoneInterfaceManager";
109 private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
110 private static final boolean DBG_LOC = false;
Jeff Sharkey85190e62014-12-05 09:40:12 -0800111 private static final boolean DBG_MERGE = false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700112
113 // Message codes used with mMainThreadHandler
114 private static final int CMD_HANDLE_PIN_MMI = 1;
115 private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
116 private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
117 private static final int CMD_ANSWER_RINGING_CALL = 4;
118 private static final int CMD_END_CALL = 5; // not used yet
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700119 private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
120 private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700121 private static final int CMD_OPEN_CHANNEL = 9;
122 private static final int EVENT_OPEN_CHANNEL_DONE = 10;
123 private static final int CMD_CLOSE_CHANNEL = 11;
124 private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
Jake Hambye994d462014-02-03 13:10:13 -0800125 private static final int CMD_NV_READ_ITEM = 13;
126 private static final int EVENT_NV_READ_ITEM_DONE = 14;
127 private static final int CMD_NV_WRITE_ITEM = 15;
128 private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
129 private static final int CMD_NV_WRITE_CDMA_PRL = 17;
130 private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
131 private static final int CMD_NV_RESET_CONFIG = 19;
132 private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
Jake Hamby7c27be32014-03-03 13:25:59 -0800133 private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
134 private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
135 private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
136 private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
Sailesh Nepal35b59452014-03-06 09:26:56 -0800137 private static final int CMD_SEND_ENVELOPE = 25;
138 private static final int EVENT_SEND_ENVELOPE_DONE = 26;
Derek Tan6b088ee2014-09-05 14:15:18 -0700139 private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
140 private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
141 private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
142 private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
143 private static final int CMD_EXCHANGE_SIM_IO = 31;
144 private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800145 private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
146 private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
Stuart Scott54788802015-03-30 13:18:01 -0700147 private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
148 private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700149 private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
150 private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700151 private static final int CMD_PERFORM_NETWORK_SCAN = 39;
152 private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
153 private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
154 private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
Meng Wang1a7c35a2016-05-05 20:56:15 -0700155 private static final int CMD_SET_ALLOWED_CARRIERS = 43;
156 private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
157 private static final int CMD_GET_ALLOWED_CARRIERS = 45;
158 private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
pkanwar32d516d2016-10-14 19:37:38 -0700159 private static final int CMD_HANDLE_USSD_REQUEST = 47;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700160
161 /** The singleton instance. */
162 private static PhoneInterfaceManager sInstance;
163
Wink Saville3ab207e2014-11-20 13:07:20 -0800164 private PhoneGlobals mApp;
165 private Phone mPhone;
166 private CallManager mCM;
Stuart Scott981d8582015-04-21 14:09:50 -0700167 private UserManager mUserManager;
Wink Saville3ab207e2014-11-20 13:07:20 -0800168 private AppOpsManager mAppOps;
169 private MainThreadHandler mMainThreadHandler;
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800170 private SubscriptionController mSubscriptionController;
Wink Saville3ab207e2014-11-20 13:07:20 -0800171 private SharedPreferences mTelephonySharedPreferences;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700172
Derek Tan97ebb422014-09-05 16:55:38 -0700173 private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
174 private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
Jeff Sharkey85190e62014-12-05 09:40:12 -0800175 private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
Derek Tan89e89d42014-07-08 17:00:10 -0700176
177 /**
Shishir Agrawal566b7612013-10-28 14:41:00 -0700178 * A request object to use for transmitting data to an ICC.
179 */
180 private static final class IccAPDUArgument {
181 public int channel, cla, command, p1, p2, p3;
182 public String data;
183
184 public IccAPDUArgument(int channel, int cla, int command,
185 int p1, int p2, int p3, String data) {
186 this.channel = channel;
187 this.cla = cla;
188 this.command = command;
189 this.p1 = p1;
190 this.p2 = p2;
191 this.p3 = p3;
192 this.data = data;
193 }
194 }
195
196 /**
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700197 * A request object to use for transmitting data to an ICC.
198 */
199 private static final class ManualNetworkSelectionArgument {
200 public OperatorInfo operatorInfo;
201 public boolean persistSelection;
202
203 public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
204 this.operatorInfo = operatorInfo;
205 this.persistSelection = persistSelection;
206 }
207 }
208
209 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700210 * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
211 * request after sending. The main thread will notify the request when it is complete.
212 */
213 private static final class MainThreadRequest {
214 /** The argument to use for the request */
215 public Object argument;
216 /** The result of the request that is run on the main thread */
217 public Object result;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800218 // The subscriber id that this request applies to. Defaults to
219 // SubscriptionManager.INVALID_SUBSCRIPTION_ID
220 public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700221
222 public MainThreadRequest(Object argument) {
223 this.argument = argument;
224 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800225
226 public MainThreadRequest(Object argument, Integer subId) {
227 this.argument = argument;
Sanket Padawe56e75a32016-02-08 12:18:19 -0800228 if (subId != null) {
229 this.subId = subId;
230 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800231 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700232 }
233
Sailesh Nepalcc0375f2013-11-13 09:15:18 -0800234 private static final class IncomingThirdPartyCallArgs {
235 public final ComponentName component;
236 public final String callId;
237 public final String callerDisplayName;
238
239 public IncomingThirdPartyCallArgs(ComponentName component, String callId,
240 String callerDisplayName) {
241 this.component = component;
242 this.callId = callId;
243 this.callerDisplayName = callerDisplayName;
244 }
245 }
246
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700247 /**
248 * A handler that processes messages on the main thread in the phone process. Since many
249 * of the Phone calls are not thread safe this is needed to shuttle the requests from the
250 * inbound binder threads to the main thread in the phone process. The Binder thread
251 * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
252 * on, which will be notified when the operation completes and will contain the result of the
253 * request.
254 *
255 * <p>If a MainThreadRequest object is provided in the msg.obj field,
256 * note that request.result must be set to something non-null for the calling thread to
257 * unblock.
258 */
259 private final class MainThreadHandler extends Handler {
260 @Override
261 public void handleMessage(Message msg) {
262 MainThreadRequest request;
263 Message onCompleted;
264 AsyncResult ar;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800265 UiccCard uiccCard;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700266 IccAPDUArgument iccArgument;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700267
268 switch (msg.what) {
pkanwar32d516d2016-10-14 19:37:38 -0700269 case CMD_HANDLE_USSD_REQUEST: {
270 request = (MainThreadRequest) msg.obj;
271 final Phone phone = getPhoneFromRequest(request);
272 Pair<String, ResultReceiver> ussdObject = (Pair) request.argument;
273 String ussdRequest = ussdObject.first;
274 ResultReceiver wrappedCallback = ussdObject.second;
275 request.result = phone != null ?
276 phone.handleUssdRequest(ussdRequest, wrappedCallback)
277 :false;
278 // Wake up the requesting thread
279 synchronized (request) {
280 request.notifyAll();
281 }
282 break;
283 }
284
Yorke Lee716f67e2015-06-17 15:39:16 -0700285 case CMD_HANDLE_PIN_MMI: {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700286 request = (MainThreadRequest) msg.obj;
Yorke Lee716f67e2015-06-17 15:39:16 -0700287 final Phone phone = getPhoneFromRequest(request);
288 request.result = phone != null ?
289 getPhoneFromRequest(request).handlePinMmi((String) request.argument)
290 : false;
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700291 // Wake up the requesting thread
292 synchronized (request) {
293 request.notifyAll();
294 }
295 break;
Yorke Lee716f67e2015-06-17 15:39:16 -0700296 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700297
298 case CMD_HANDLE_NEIGHBORING_CELL:
299 request = (MainThreadRequest) msg.obj;
300 onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
301 request);
Sooraj Sasindran9a909312016-07-18 11:57:25 -0700302 mPhone.getNeighboringCids(onCompleted, (WorkSource)request.argument);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700303 break;
304
305 case EVENT_NEIGHBORING_CELL_DONE:
306 ar = (AsyncResult) msg.obj;
307 request = (MainThreadRequest) ar.userObj;
308 if (ar.exception == null && ar.result != null) {
309 request.result = ar.result;
310 } else {
311 // create an empty list to notify the waiting thread
Jake Hambye994d462014-02-03 13:10:13 -0800312 request.result = new ArrayList<NeighboringCellInfo>(0);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700313 }
314 // Wake up the requesting thread
315 synchronized (request) {
316 request.notifyAll();
317 }
318 break;
319
320 case CMD_ANSWER_RINGING_CALL:
Wink Saville08874612014-08-31 19:19:58 -0700321 request = (MainThreadRequest) msg.obj;
Stuart Scott584921c2015-01-15 17:10:34 -0800322 int answer_subId = request.subId;
Wink Saville08874612014-08-31 19:19:58 -0700323 answerRingingCallInternal(answer_subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700324 break;
325
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700326 case CMD_END_CALL:
327 request = (MainThreadRequest) msg.obj;
Stuart Scott584921c2015-01-15 17:10:34 -0800328 int end_subId = request.subId;
Wink Saville08874612014-08-31 19:19:58 -0700329 final boolean hungUp;
Anthony Leeae4e36d2015-05-21 07:17:46 -0700330 Phone phone = getPhone(end_subId);
331 if (phone == null) {
332 if (DBG) log("CMD_END_CALL: no phone for id: " + end_subId);
333 break;
334 }
335 int phoneType = phone.getPhoneType();
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700336 if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
337 // CDMA: If the user presses the Power button we treat it as
338 // ending the complete call session
Wink Saville08874612014-08-31 19:19:58 -0700339 hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700340 } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
341 // GSM: End the call as per the Phone state
342 hungUp = PhoneUtils.hangup(mCM);
343 } else {
344 throw new IllegalStateException("Unexpected phone type: " + phoneType);
345 }
346 if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
347 request.result = hungUp;
348 // Wake up the requesting thread
349 synchronized (request) {
350 request.notifyAll();
351 }
352 break;
353
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700354 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700355 request = (MainThreadRequest) msg.obj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700356 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800357 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700358 if (uiccCard == null) {
359 loge("iccTransmitApduLogicalChannel: No UICC");
360 request.result = new IccIoResult(0x6F, 0, (byte[])null);
361 synchronized (request) {
362 request.notifyAll();
363 }
364 } else {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700365 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
366 request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700367 uiccCard.iccTransmitApduLogicalChannel(
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700368 iccArgument.channel, iccArgument.cla, iccArgument.command,
369 iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
Shishir Agrawal566b7612013-10-28 14:41:00 -0700370 onCompleted);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700371 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700372 break;
373
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700374 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700375 ar = (AsyncResult) msg.obj;
376 request = (MainThreadRequest) ar.userObj;
377 if (ar.exception == null && ar.result != null) {
378 request.result = ar.result;
379 } else {
380 request.result = new IccIoResult(0x6F, 0, (byte[])null);
381 if (ar.result == null) {
382 loge("iccTransmitApduLogicalChannel: Empty response");
Jake Hambye994d462014-02-03 13:10:13 -0800383 } else if (ar.exception instanceof CommandException) {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700384 loge("iccTransmitApduLogicalChannel: CommandException: " +
Jake Hambye994d462014-02-03 13:10:13 -0800385 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700386 } else {
387 loge("iccTransmitApduLogicalChannel: Unknown exception");
388 }
389 }
390 synchronized (request) {
391 request.notifyAll();
392 }
393 break;
394
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700395 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
396 request = (MainThreadRequest) msg.obj;
397 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800398 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700399 if (uiccCard == null) {
400 loge("iccTransmitApduBasicChannel: No UICC");
401 request.result = new IccIoResult(0x6F, 0, (byte[])null);
402 synchronized (request) {
403 request.notifyAll();
404 }
405 } else {
406 onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
407 request);
408 uiccCard.iccTransmitApduBasicChannel(
409 iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
410 iccArgument.p3, iccArgument.data, onCompleted);
411 }
412 break;
413
414 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
415 ar = (AsyncResult) msg.obj;
416 request = (MainThreadRequest) ar.userObj;
417 if (ar.exception == null && ar.result != null) {
418 request.result = ar.result;
419 } else {
420 request.result = new IccIoResult(0x6F, 0, (byte[])null);
421 if (ar.result == null) {
422 loge("iccTransmitApduBasicChannel: Empty response");
423 } else if (ar.exception instanceof CommandException) {
424 loge("iccTransmitApduBasicChannel: CommandException: " +
425 ar.exception);
426 } else {
427 loge("iccTransmitApduBasicChannel: Unknown exception");
428 }
429 }
430 synchronized (request) {
431 request.notifyAll();
432 }
433 break;
434
435 case CMD_EXCHANGE_SIM_IO:
436 request = (MainThreadRequest) msg.obj;
437 iccArgument = (IccAPDUArgument) request.argument;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800438 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700439 if (uiccCard == null) {
440 loge("iccExchangeSimIO: No UICC");
441 request.result = new IccIoResult(0x6F, 0, (byte[])null);
442 synchronized (request) {
443 request.notifyAll();
444 }
445 } else {
446 onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
447 request);
448 uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
449 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
450 iccArgument.data, onCompleted);
451 }
452 break;
453
454 case EVENT_EXCHANGE_SIM_IO_DONE:
455 ar = (AsyncResult) msg.obj;
456 request = (MainThreadRequest) ar.userObj;
457 if (ar.exception == null && ar.result != null) {
458 request.result = ar.result;
459 } else {
460 request.result = new IccIoResult(0x6f, 0, (byte[])null);
461 }
462 synchronized (request) {
463 request.notifyAll();
464 }
465 break;
466
Derek Tan4d5e5c12014-02-04 11:54:58 -0800467 case CMD_SEND_ENVELOPE:
468 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800469 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700470 if (uiccCard == null) {
471 loge("sendEnvelopeWithStatus: No UICC");
472 request.result = new IccIoResult(0x6F, 0, (byte[])null);
473 synchronized (request) {
474 request.notifyAll();
475 }
476 } else {
477 onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
478 uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
479 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800480 break;
481
482 case EVENT_SEND_ENVELOPE_DONE:
483 ar = (AsyncResult) msg.obj;
484 request = (MainThreadRequest) ar.userObj;
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700485 if (ar.exception == null && ar.result != null) {
486 request.result = ar.result;
Derek Tan4d5e5c12014-02-04 11:54:58 -0800487 } else {
Shishir Agrawal9f9877d2014-03-14 09:36:27 -0700488 request.result = new IccIoResult(0x6F, 0, (byte[])null);
489 if (ar.result == null) {
490 loge("sendEnvelopeWithStatus: Empty response");
491 } else if (ar.exception instanceof CommandException) {
492 loge("sendEnvelopeWithStatus: CommandException: " +
493 ar.exception);
494 } else {
495 loge("sendEnvelopeWithStatus: exception:" + ar.exception);
496 }
Derek Tan4d5e5c12014-02-04 11:54:58 -0800497 }
498 synchronized (request) {
499 request.notifyAll();
500 }
501 break;
502
Shishir Agrawal566b7612013-10-28 14:41:00 -0700503 case CMD_OPEN_CHANNEL:
504 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800505 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700506 if (uiccCard == null) {
507 loge("iccOpenLogicalChannel: No UICC");
Shishir Agrawalfc0492a2016-02-17 11:15:33 -0800508 request.result = new IccOpenLogicalChannelResponse(-1,
509 IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700510 synchronized (request) {
511 request.notifyAll();
512 }
513 } else {
514 onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
515 uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
516 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700517 break;
518
519 case EVENT_OPEN_CHANNEL_DONE:
520 ar = (AsyncResult) msg.obj;
521 request = (MainThreadRequest) ar.userObj;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700522 IccOpenLogicalChannelResponse openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700523 if (ar.exception == null && ar.result != null) {
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700524 int[] result = (int[]) ar.result;
525 int channelId = result[0];
526 byte[] selectResponse = null;
527 if (result.length > 1) {
528 selectResponse = new byte[result.length - 1];
529 for (int i = 1; i < result.length; ++i) {
530 selectResponse[i - 1] = (byte) result[i];
531 }
532 }
533 openChannelResp = new IccOpenLogicalChannelResponse(channelId,
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700534 IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700535 } else {
Shishir Agrawal566b7612013-10-28 14:41:00 -0700536 if (ar.result == null) {
537 loge("iccOpenLogicalChannel: Empty response");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700538 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700539 if (ar.exception != null) {
540 loge("iccOpenLogicalChannel: Exception: " + ar.exception);
541 }
542
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700543 int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
Junda Liua754ba12015-05-20 01:17:52 -0700544 if (ar.exception instanceof CommandException) {
545 CommandException.Error error =
546 ((CommandException) (ar.exception)).getCommandError();
547 if (error == CommandException.Error.MISSING_RESOURCE) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700548 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
Junda Liua754ba12015-05-20 01:17:52 -0700549 } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
Shishir Agrawal527e8bf2014-08-25 08:54:56 -0700550 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -0700551 }
552 }
553 openChannelResp = new IccOpenLogicalChannelResponse(
554 IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700555 }
Shishir Agrawal82c8a462014-07-31 18:13:17 -0700556 request.result = openChannelResp;
Shishir Agrawal566b7612013-10-28 14:41:00 -0700557 synchronized (request) {
558 request.notifyAll();
559 }
560 break;
561
562 case CMD_CLOSE_CHANNEL:
563 request = (MainThreadRequest) msg.obj;
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800564 uiccCard = getUiccCardFromRequest(request);
Shishir Agrawaleb8771e2014-07-22 11:24:08 -0700565 if (uiccCard == null) {
566 loge("iccCloseLogicalChannel: No UICC");
567 request.result = new IccIoResult(0x6F, 0, (byte[])null);
568 synchronized (request) {
569 request.notifyAll();
570 }
571 } else {
572 onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
573 uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
574 }
Shishir Agrawal566b7612013-10-28 14:41:00 -0700575 break;
576
577 case EVENT_CLOSE_CHANNEL_DONE:
Jake Hambye994d462014-02-03 13:10:13 -0800578 handleNullReturnEvent(msg, "iccCloseLogicalChannel");
579 break;
580
581 case CMD_NV_READ_ITEM:
582 request = (MainThreadRequest) msg.obj;
583 onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
584 mPhone.nvReadItem((Integer) request.argument, onCompleted);
585 break;
586
587 case EVENT_NV_READ_ITEM_DONE:
Shishir Agrawal566b7612013-10-28 14:41:00 -0700588 ar = (AsyncResult) msg.obj;
589 request = (MainThreadRequest) ar.userObj;
Jake Hambye994d462014-02-03 13:10:13 -0800590 if (ar.exception == null && ar.result != null) {
591 request.result = ar.result; // String
Shishir Agrawal566b7612013-10-28 14:41:00 -0700592 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800593 request.result = "";
594 if (ar.result == null) {
595 loge("nvReadItem: Empty response");
596 } else if (ar.exception instanceof CommandException) {
597 loge("nvReadItem: CommandException: " +
598 ar.exception);
Shishir Agrawal566b7612013-10-28 14:41:00 -0700599 } else {
Jake Hambye994d462014-02-03 13:10:13 -0800600 loge("nvReadItem: Unknown exception");
Shishir Agrawal566b7612013-10-28 14:41:00 -0700601 }
602 }
603 synchronized (request) {
604 request.notifyAll();
605 }
606 break;
607
Jake Hambye994d462014-02-03 13:10:13 -0800608 case CMD_NV_WRITE_ITEM:
609 request = (MainThreadRequest) msg.obj;
610 onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
611 Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
612 mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
613 break;
614
615 case EVENT_NV_WRITE_ITEM_DONE:
616 handleNullReturnEvent(msg, "nvWriteItem");
617 break;
618
619 case CMD_NV_WRITE_CDMA_PRL:
620 request = (MainThreadRequest) msg.obj;
621 onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
622 mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
623 break;
624
625 case EVENT_NV_WRITE_CDMA_PRL_DONE:
626 handleNullReturnEvent(msg, "nvWriteCdmaPrl");
627 break;
628
629 case CMD_NV_RESET_CONFIG:
630 request = (MainThreadRequest) msg.obj;
631 onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
632 mPhone.nvResetConfig((Integer) request.argument, onCompleted);
633 break;
634
635 case EVENT_NV_RESET_CONFIG_DONE:
636 handleNullReturnEvent(msg, "nvResetConfig");
637 break;
638
Jake Hamby7c27be32014-03-03 13:25:59 -0800639 case CMD_GET_PREFERRED_NETWORK_TYPE:
640 request = (MainThreadRequest) msg.obj;
641 onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
Stuart Scott54788802015-03-30 13:18:01 -0700642 getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -0800643 break;
644
645 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
646 ar = (AsyncResult) msg.obj;
647 request = (MainThreadRequest) ar.userObj;
648 if (ar.exception == null && ar.result != null) {
649 request.result = ar.result; // Integer
650 } else {
Sanket Padawecfc2d352016-01-05 19:52:14 -0800651 request.result = null;
Jake Hamby7c27be32014-03-03 13:25:59 -0800652 if (ar.result == null) {
653 loge("getPreferredNetworkType: Empty response");
654 } else if (ar.exception instanceof CommandException) {
655 loge("getPreferredNetworkType: CommandException: " +
656 ar.exception);
657 } else {
658 loge("getPreferredNetworkType: Unknown exception");
659 }
660 }
661 synchronized (request) {
662 request.notifyAll();
663 }
664 break;
665
666 case CMD_SET_PREFERRED_NETWORK_TYPE:
667 request = (MainThreadRequest) msg.obj;
668 onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
669 int networkType = (Integer) request.argument;
Stuart Scott54788802015-03-30 13:18:01 -0700670 getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
Jake Hamby7c27be32014-03-03 13:25:59 -0800671 break;
672
673 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
674 handleNullReturnEvent(msg, "setPreferredNetworkType");
675 break;
676
Steven Liu4bf01bc2014-07-17 11:05:29 -0500677 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
678 request = (MainThreadRequest)msg.obj;
679 onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
680 mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
681 break;
682
683 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
684 ar = (AsyncResult)msg.obj;
685 request = (MainThreadRequest)ar.userObj;
686 request.result = ar;
687 synchronized (request) {
688 request.notifyAll();
689 }
690 break;
691
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800692 case CMD_SET_VOICEMAIL_NUMBER:
693 request = (MainThreadRequest) msg.obj;
694 onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
695 Pair<String, String> tagNum = (Pair<String, String>) request.argument;
Stuart Scott584921c2015-01-15 17:10:34 -0800696 getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
697 onCompleted);
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800698 break;
699
700 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
701 handleNullReturnEvent(msg, "setVoicemailNumber");
702 break;
703
Stuart Scott54788802015-03-30 13:18:01 -0700704 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
705 request = (MainThreadRequest) msg.obj;
706 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
707 request);
708 getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
709 break;
710
711 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
712 handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
713 break;
714
Shishir Agrawal302c8692015-06-19 13:49:39 -0700715 case CMD_PERFORM_NETWORK_SCAN:
716 request = (MainThreadRequest) msg.obj;
717 onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
718 getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
719 break;
720
721 case EVENT_PERFORM_NETWORK_SCAN_DONE:
722 ar = (AsyncResult) msg.obj;
723 request = (MainThreadRequest) ar.userObj;
724 CellNetworkScanResult cellScanResult;
725 if (ar.exception == null && ar.result != null) {
726 cellScanResult = new CellNetworkScanResult(
727 CellNetworkScanResult.STATUS_SUCCESS,
728 (List<OperatorInfo>) ar.result);
729 } else {
730 if (ar.result == null) {
731 loge("getCellNetworkScanResults: Empty response");
732 }
733 if (ar.exception != null) {
734 loge("getCellNetworkScanResults: Exception: " + ar.exception);
735 }
736 int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
737 if (ar.exception instanceof CommandException) {
738 CommandException.Error error =
739 ((CommandException) (ar.exception)).getCommandError();
740 if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
741 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
742 } else if (error == CommandException.Error.GENERIC_FAILURE) {
743 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
744 }
745 }
746 cellScanResult = new CellNetworkScanResult(errorCode, null);
747 }
748 request.result = cellScanResult;
749 synchronized (request) {
750 request.notifyAll();
751 }
752 break;
753
754 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
755 request = (MainThreadRequest) msg.obj;
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700756 ManualNetworkSelectionArgument selArg =
757 (ManualNetworkSelectionArgument) request.argument;
Shishir Agrawal302c8692015-06-19 13:49:39 -0700758 onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
759 request);
Shishir Agrawal77ba3172015-09-10 14:50:19 -0700760 getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
761 selArg.persistSelection, onCompleted);
Shishir Agrawal302c8692015-06-19 13:49:39 -0700762 break;
763
764 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
765 handleNullReturnEvent(msg, "setNetworkSelectionModeManual");
766 break;
767
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700768 case CMD_GET_MODEM_ACTIVITY_INFO:
769 request = (MainThreadRequest) msg.obj;
770 onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
Prerepa Viswanadham61a60ad2015-06-08 18:07:51 -0700771 mPhone.getModemActivityInfo(onCompleted);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700772 break;
773
774 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
775 ar = (AsyncResult) msg.obj;
776 request = (MainThreadRequest) ar.userObj;
777 if (ar.exception == null && ar.result != null) {
778 request.result = ar.result;
779 } else {
780 if (ar.result == null) {
781 loge("queryModemActivityInfo: Empty response");
782 } else if (ar.exception instanceof CommandException) {
783 loge("queryModemActivityInfo: CommandException: " +
784 ar.exception);
785 } else {
786 loge("queryModemActivityInfo: Unknown exception");
787 }
788 }
Amit Mahajand4766222016-01-28 15:28:28 -0800789 // Result cannot be null. Return ModemActivityInfo with all fields set to 0.
790 if (request.result == null) {
791 request.result = new ModemActivityInfo(0, 0, 0, null, 0, 0);
792 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -0700793 synchronized (request) {
794 request.notifyAll();
795 }
796 break;
797
Meng Wang1a7c35a2016-05-05 20:56:15 -0700798 case CMD_SET_ALLOWED_CARRIERS:
799 request = (MainThreadRequest) msg.obj;
800 onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
801 mPhone.setAllowedCarriers(
802 (List<CarrierIdentifier>) request.argument,
803 onCompleted);
804 break;
805
806 case EVENT_SET_ALLOWED_CARRIERS_DONE:
807 ar = (AsyncResult) msg.obj;
808 request = (MainThreadRequest) ar.userObj;
809 if (ar.exception == null && ar.result != null) {
810 request.result = ar.result;
811 } else {
812 if (ar.result == null) {
813 loge("setAllowedCarriers: Empty response");
814 } else if (ar.exception instanceof CommandException) {
815 loge("setAllowedCarriers: CommandException: " +
816 ar.exception);
817 } else {
818 loge("setAllowedCarriers: Unknown exception");
819 }
820 }
821 // Result cannot be null. Return -1 on error.
822 if (request.result == null) {
823 request.result = new int[]{-1};
824 }
825 synchronized (request) {
826 request.notifyAll();
827 }
828 break;
829
830 case CMD_GET_ALLOWED_CARRIERS:
831 request = (MainThreadRequest) msg.obj;
832 onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
833 mPhone.getAllowedCarriers(onCompleted);
834 break;
835
836 case EVENT_GET_ALLOWED_CARRIERS_DONE:
837 ar = (AsyncResult) msg.obj;
838 request = (MainThreadRequest) ar.userObj;
839 if (ar.exception == null && ar.result != null) {
840 request.result = ar.result;
841 } else {
842 if (ar.result == null) {
843 loge("getAllowedCarriers: Empty response");
844 } else if (ar.exception instanceof CommandException) {
845 loge("getAllowedCarriers: CommandException: " +
846 ar.exception);
847 } else {
848 loge("getAllowedCarriers: Unknown exception");
849 }
850 }
851 // Result cannot be null. Return empty list of CarrierIdentifier.
852 if (request.result == null) {
853 request.result = new ArrayList<CarrierIdentifier>(0);
854 }
855 synchronized (request) {
856 request.notifyAll();
857 }
858 break;
859
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700860 default:
861 Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
862 break;
863 }
864 }
Jake Hambye994d462014-02-03 13:10:13 -0800865
866 private void handleNullReturnEvent(Message msg, String command) {
867 AsyncResult ar = (AsyncResult) msg.obj;
868 MainThreadRequest request = (MainThreadRequest) ar.userObj;
869 if (ar.exception == null) {
870 request.result = true;
871 } else {
872 request.result = false;
873 if (ar.exception instanceof CommandException) {
874 loge(command + ": CommandException: " + ar.exception);
875 } else {
876 loge(command + ": Unknown exception");
877 }
878 }
879 synchronized (request) {
880 request.notifyAll();
881 }
882 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700883 }
884
885 /**
886 * Posts the specified command to be executed on the main thread,
887 * waits for the request to complete, and returns the result.
888 * @see #sendRequestAsync
889 */
890 private Object sendRequest(int command, Object argument) {
Sanket Padawe56e75a32016-02-08 12:18:19 -0800891 return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Wink Saville36469e72014-06-11 15:17:00 -0700892 }
893
894 /**
895 * Posts the specified command to be executed on the main thread,
896 * waits for the request to complete, and returns the result.
897 * @see #sendRequestAsync
898 */
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800899 private Object sendRequest(int command, Object argument, Integer subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700900 if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
901 throw new RuntimeException("This method will deadlock if called from the main thread.");
902 }
903
Shishir Agrawal76d5da92014-11-09 16:17:25 -0800904 MainThreadRequest request = new MainThreadRequest(argument, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700905 Message msg = mMainThreadHandler.obtainMessage(command, request);
906 msg.sendToTarget();
907
908 // Wait for the request to complete
909 synchronized (request) {
910 while (request.result == null) {
911 try {
912 request.wait();
913 } catch (InterruptedException e) {
914 // Do nothing, go back and wait until the request is complete
915 }
916 }
917 }
918 return request.result;
919 }
920
921 /**
922 * Asynchronous ("fire and forget") version of sendRequest():
923 * Posts the specified command to be executed on the main thread, and
924 * returns immediately.
925 * @see #sendRequest
926 */
927 private void sendRequestAsync(int command) {
928 mMainThreadHandler.sendEmptyMessage(command);
929 }
930
931 /**
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -0700932 * Same as {@link #sendRequestAsync(int)} except it takes an argument.
933 * @see {@link #sendRequest(int,Object)}
934 */
935 private void sendRequestAsync(int command, Object argument) {
936 MainThreadRequest request = new MainThreadRequest(argument);
937 Message msg = mMainThreadHandler.obtainMessage(command, request);
938 msg.sendToTarget();
939 }
940
941 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700942 * Initialize the singleton PhoneInterfaceManager instance.
943 * This is only done once, at startup, from PhoneApp.onCreate().
944 */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700945 /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700946 synchronized (PhoneInterfaceManager.class) {
947 if (sInstance == null) {
Sailesh Nepal194161e2014-07-03 08:57:44 -0700948 sInstance = new PhoneInterfaceManager(app, phone);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700949 } else {
950 Log.wtf(LOG_TAG, "init() called multiple times! sInstance = " + sInstance);
951 }
952 return sInstance;
953 }
954 }
955
956 /** Private constructor; @see init() */
Sailesh Nepal194161e2014-07-03 08:57:44 -0700957 private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700958 mApp = app;
959 mPhone = phone;
960 mCM = PhoneGlobals.getInstance().mCM;
Stuart Scott981d8582015-04-21 14:09:50 -0700961 mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700962 mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
963 mMainThreadHandler = new MainThreadHandler();
Andrew Leedf14ead2014-10-17 14:22:52 -0700964 mTelephonySharedPreferences =
Derek Tan97ebb422014-09-05 16:55:38 -0700965 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800966 mSubscriptionController = SubscriptionController.getInstance();
Wink Saville3ab207e2014-11-20 13:07:20 -0800967
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700968 publish();
969 }
970
971 private void publish() {
972 if (DBG) log("publish: " + this);
973
974 ServiceManager.addService("phone", this);
975 }
976
Stuart Scott584921c2015-01-15 17:10:34 -0800977 private Phone getPhoneFromRequest(MainThreadRequest request) {
Sanket Padawe56e75a32016-02-08 12:18:19 -0800978 return (request.subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
979 ? mPhone : getPhone(request.subId);
Stuart Scott584921c2015-01-15 17:10:34 -0800980 }
981
Shishir Agrawalc04d9752016-02-19 10:41:00 -0800982 private UiccCard getUiccCardFromRequest(MainThreadRequest request) {
983 Phone phone = getPhoneFromRequest(request);
984 return phone == null ? null :
985 UiccController.getInstance().getUiccCard(phone.getPhoneId());
986 }
987
Wink Saville36469e72014-06-11 15:17:00 -0700988 // returns phone associated with the subId.
Wink Savilleb564aae2014-10-23 10:18:09 -0700989 private Phone getPhone(int subId) {
Wink Savilleac1bdfd2014-11-20 23:04:44 -0800990 return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
Wink Saville36469e72014-06-11 15:17:00 -0700991 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -0700992 //
993 // Implementation of the ITelephony interface.
994 //
995
996 public void dial(String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -0700997 dialForSubscriber(getPreferredVoiceSubscription(), number);
Wink Saville36469e72014-06-11 15:17:00 -0700998 }
999
Wink Savilleb564aae2014-10-23 10:18:09 -07001000 public void dialForSubscriber(int subId, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001001 if (DBG) log("dial: " + number);
1002 // No permission check needed here: This is just a wrapper around the
1003 // ACTION_DIAL intent, which is available to any app since it puts up
1004 // the UI before it does anything.
1005
1006 String url = createTelUrl(number);
1007 if (url == null) {
1008 return;
1009 }
1010
1011 // PENDING: should we just silently fail if phone is offhook or ringing?
Wink Saville36469e72014-06-11 15:17:00 -07001012 PhoneConstants.State state = mCM.getState(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001013 if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
1014 Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
1015 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1016 mApp.startActivity(intent);
1017 }
1018 }
1019
1020 public void call(String callingPackage, String number) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001021 callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
Wink Saville36469e72014-06-11 15:17:00 -07001022 }
1023
Wink Savilleb564aae2014-10-23 10:18:09 -07001024 public void callForSubscriber(int subId, String callingPackage, String number) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001025 if (DBG) log("call: " + number);
1026
1027 // This is just a wrapper around the ACTION_CALL intent, but we still
1028 // need to do a permission check since we're calling startActivity()
1029 // from the context of the phone app.
1030 enforceCallPermission();
1031
1032 if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
1033 != AppOpsManager.MODE_ALLOWED) {
1034 return;
1035 }
1036
1037 String url = createTelUrl(number);
1038 if (url == null) {
1039 return;
1040 }
1041
Wink Saville08874612014-08-31 19:19:58 -07001042 boolean isValid = false;
Narayan Kamath1c496c22015-04-16 14:40:19 +01001043 final List<SubscriptionInfo> slist = getActiveSubscriptionInfoList();
Wink Saville3ab207e2014-11-20 13:07:20 -08001044 if (slist != null) {
1045 for (SubscriptionInfo subInfoRecord : slist) {
1046 if (subInfoRecord.getSubscriptionId() == subId) {
1047 isValid = true;
1048 break;
1049 }
Wink Saville08874612014-08-31 19:19:58 -07001050 }
1051 }
1052 if (isValid == false) {
1053 return;
1054 }
1055
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001056 Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
Wink Saville36469e72014-06-11 15:17:00 -07001057 intent.putExtra(SUBSCRIPTION_KEY, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001058 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1059 mApp.startActivity(intent);
1060 }
1061
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001062 /**
1063 * End a call based on call state
1064 * @return true is a call was ended
1065 */
1066 public boolean endCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001067 return endCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001068 }
1069
1070 /**
1071 * End a call based on the call state of the subId
1072 * @return true is a call was ended
1073 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001074 public boolean endCallForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001075 enforceCallPermission();
Stuart Scott584921c2015-01-15 17:10:34 -08001076 return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001077 }
1078
1079 public void answerRingingCall() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001080 answerRingingCallForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001081 }
1082
Wink Savilleb564aae2014-10-23 10:18:09 -07001083 public void answerRingingCallForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001084 if (DBG) log("answerRingingCall...");
1085 // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
1086 // but that can probably wait till the big TelephonyManager API overhaul.
1087 // For now, protect this call with the MODIFY_PHONE_STATE permission.
1088 enforceModifyPermission();
Stuart Scott584921c2015-01-15 17:10:34 -08001089 sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId));
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001090 }
1091
1092 /**
1093 * Make the actual telephony calls to implement answerRingingCall().
1094 * This should only be called from the main thread of the Phone app.
1095 * @see #answerRingingCall
1096 *
1097 * TODO: it would be nice to return true if we answered the call, or
1098 * false if there wasn't actually a ringing incoming call, or some
1099 * other error occurred. (In other words, pass back the return value
1100 * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
1101 * But that would require calling this method via sendRequest() rather
1102 * than sendRequestAsync(), and right now we don't actually *need* that
1103 * return value, so let's just return void for now.
1104 */
Wink Savilleb564aae2014-10-23 10:18:09 -07001105 private void answerRingingCallInternal(int subId) {
Wink Saville08874612014-08-31 19:19:58 -07001106 final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001107 if (hasRingingCall) {
Wink Saville08874612014-08-31 19:19:58 -07001108 final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
1109 final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001110 if (hasActiveCall && hasHoldingCall) {
1111 // Both lines are in use!
1112 // TODO: provide a flag to let the caller specify what
1113 // policy to use if both lines are in use. (The current
1114 // behavior is hardwired to "answer incoming, end ongoing",
1115 // which is how the CALL button is specced to behave.)
1116 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
1117 return;
1118 } else {
1119 // answerCall() will automatically hold the current active
1120 // call, if there is one.
1121 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
1122 return;
1123 }
1124 } else {
1125 // No call was ringing.
1126 return;
1127 }
1128 }
1129
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001130 /**
Santos Cordon5422a8d2014-09-12 04:20:56 -07001131 * This method is no longer used and can be removed once TelephonyManager stops referring to it.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001132 */
Santos Cordon5422a8d2014-09-12 04:20:56 -07001133 public void silenceRinger() {
1134 Log.e(LOG_TAG, "silenseRinger not supported");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001135 }
1136
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001137 @Override
1138 public boolean isOffhook(String callingPackage) {
1139 return isOffhookForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001140 }
1141
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001142 @Override
1143 public boolean isOffhookForSubscriber(int subId, String callingPackage) {
1144 if (!canReadPhoneState(callingPackage, "isOffhookForSubscriber")) {
1145 return false;
1146 }
1147
Sanket Padawe356d7632015-06-22 14:03:32 -07001148 final Phone phone = getPhone(subId);
1149 if (phone != null) {
1150 return (phone.getState() == PhoneConstants.State.OFFHOOK);
1151 } else {
1152 return false;
1153 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001154 }
1155
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001156 @Override
1157 public boolean isRinging(String callingPackage) {
1158 return (isRingingForSubscriber(getDefaultSubscription(), callingPackage));
Wink Saville36469e72014-06-11 15:17:00 -07001159 }
1160
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001161 @Override
1162 public boolean isRingingForSubscriber(int subId, String callingPackage) {
1163 if (!canReadPhoneState(callingPackage, "isRingingForSubscriber")) {
1164 return false;
1165 }
1166
Sanket Padawe356d7632015-06-22 14:03:32 -07001167 final Phone phone = getPhone(subId);
1168 if (phone != null) {
1169 return (phone.getState() == PhoneConstants.State.RINGING);
1170 } else {
1171 return false;
1172 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001173 }
1174
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001175 @Override
1176 public boolean isIdle(String callingPackage) {
1177 return isIdleForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001178 }
1179
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001180 @Override
1181 public boolean isIdleForSubscriber(int subId, String callingPackage) {
1182 if (!canReadPhoneState(callingPackage, "isIdleForSubscriber")) {
1183 return false;
1184 }
1185
Sanket Padawe356d7632015-06-22 14:03:32 -07001186 final Phone phone = getPhone(subId);
1187 if (phone != null) {
1188 return (phone.getState() == PhoneConstants.State.IDLE);
1189 } else {
1190 return false;
1191 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001192 }
1193
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001194 public boolean supplyPin(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001195 return supplyPinForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -07001196 }
1197
Wink Savilleb564aae2014-10-23 10:18:09 -07001198 public boolean supplyPinForSubscriber(int subId, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001199 int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07001200 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1201 }
1202
1203 public boolean supplyPuk(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001204 return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -07001205 }
1206
Wink Savilleb564aae2014-10-23 10:18:09 -07001207 public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001208 int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
Wink Saville9de0f752013-10-22 19:04:03 -07001209 return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1210 }
1211
1212 /** {@hide} */
1213 public int[] supplyPinReportResult(String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001214 return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
Wink Saville36469e72014-06-11 15:17:00 -07001215 }
1216
Wink Savilleb564aae2014-10-23 10:18:09 -07001217 public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001218 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001219 final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001220 checkSimPin.start();
1221 return checkSimPin.unlockSim(null, pin);
1222 }
1223
Wink Saville9de0f752013-10-22 19:04:03 -07001224 /** {@hide} */
1225 public int[] supplyPukReportResult(String puk, String pin) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001226 return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
Wink Saville36469e72014-06-11 15:17:00 -07001227 }
1228
Wink Savilleb564aae2014-10-23 10:18:09 -07001229 public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001230 enforceModifyPermission();
Wink Saville36469e72014-06-11 15:17:00 -07001231 final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001232 checkSimPuk.start();
1233 return checkSimPuk.unlockSim(puk, pin);
1234 }
1235
1236 /**
Wink Saville9de0f752013-10-22 19:04:03 -07001237 * Helper thread to turn async call to SimCard#supplyPin into
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001238 * a synchronous one.
1239 */
1240 private static class UnlockSim extends Thread {
1241
1242 private final IccCard mSimCard;
1243
1244 private boolean mDone = false;
Wink Saville9de0f752013-10-22 19:04:03 -07001245 private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1246 private int mRetryCount = -1;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001247
1248 // For replies from SimCard interface
1249 private Handler mHandler;
1250
1251 // For async handler to identify request type
1252 private static final int SUPPLY_PIN_COMPLETE = 100;
1253
1254 public UnlockSim(IccCard simCard) {
1255 mSimCard = simCard;
1256 }
1257
1258 @Override
1259 public void run() {
1260 Looper.prepare();
1261 synchronized (UnlockSim.this) {
1262 mHandler = new Handler() {
1263 @Override
1264 public void handleMessage(Message msg) {
1265 AsyncResult ar = (AsyncResult) msg.obj;
1266 switch (msg.what) {
1267 case SUPPLY_PIN_COMPLETE:
1268 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
1269 synchronized (UnlockSim.this) {
Wink Saville9de0f752013-10-22 19:04:03 -07001270 mRetryCount = msg.arg1;
1271 if (ar.exception != null) {
1272 if (ar.exception instanceof CommandException &&
1273 ((CommandException)(ar.exception)).getCommandError()
1274 == CommandException.Error.PASSWORD_INCORRECT) {
1275 mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1276 } else {
1277 mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1278 }
1279 } else {
1280 mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1281 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001282 mDone = true;
1283 UnlockSim.this.notifyAll();
1284 }
1285 break;
1286 }
1287 }
1288 };
1289 UnlockSim.this.notifyAll();
1290 }
1291 Looper.loop();
1292 }
1293
1294 /*
1295 * Use PIN or PUK to unlock SIM card
1296 *
1297 * If PUK is null, unlock SIM card with PIN
1298 *
1299 * If PUK is not null, unlock SIM card with PUK and set PIN code
1300 */
Wink Saville9de0f752013-10-22 19:04:03 -07001301 synchronized int[] unlockSim(String puk, String pin) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001302
1303 while (mHandler == null) {
1304 try {
1305 wait();
1306 } catch (InterruptedException e) {
1307 Thread.currentThread().interrupt();
1308 }
1309 }
1310 Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1311
1312 if (puk == null) {
1313 mSimCard.supplyPin(pin, callback);
1314 } else {
1315 mSimCard.supplyPuk(puk, pin, callback);
1316 }
1317
1318 while (!mDone) {
1319 try {
1320 Log.d(LOG_TAG, "wait for done");
1321 wait();
1322 } catch (InterruptedException e) {
1323 // Restore the interrupted status
1324 Thread.currentThread().interrupt();
1325 }
1326 }
1327 Log.d(LOG_TAG, "done");
Wink Saville9de0f752013-10-22 19:04:03 -07001328 int[] resultArray = new int[2];
1329 resultArray[0] = mResult;
1330 resultArray[1] = mRetryCount;
1331 return resultArray;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001332 }
1333 }
1334
1335 public void updateServiceLocation() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001336 updateServiceLocationForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001337
1338 }
1339
Wink Savilleb564aae2014-10-23 10:18:09 -07001340 public void updateServiceLocationForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001341 // No permission check needed here: this call is harmless, and it's
1342 // needed for the ServiceState.requestStateUpdate() call (which is
1343 // already intentionally exposed to 3rd parties.)
Sanket Padawe356d7632015-06-22 14:03:32 -07001344 final Phone phone = getPhone(subId);
1345 if (phone != null) {
1346 phone.updateServiceLocation();
1347 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001348 }
1349
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001350 @Override
1351 public boolean isRadioOn(String callingPackage) {
1352 return isRadioOnForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001353 }
1354
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001355 @Override
1356 public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
1357 if (!canReadPhoneState(callingPackage, "isRadioOnForSubscriber")) {
1358 return false;
1359 }
1360 return isRadioOnForSubscriber(subId);
1361 }
1362
1363 private boolean isRadioOnForSubscriber(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07001364 final Phone phone = getPhone(subId);
1365 if (phone != null) {
1366 return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1367 } else {
1368 return false;
1369 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001370 }
1371
1372 public void toggleRadioOnOff() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001373 toggleRadioOnOffForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001374
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001375 }
Wink Saville36469e72014-06-11 15:17:00 -07001376
Wink Savilleb564aae2014-10-23 10:18:09 -07001377 public void toggleRadioOnOffForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001378 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001379 final Phone phone = getPhone(subId);
1380 if (phone != null) {
1381 phone.setRadioPower(!isRadioOnForSubscriber(subId));
1382 }
Wink Saville36469e72014-06-11 15:17:00 -07001383 }
1384
1385 public boolean setRadio(boolean turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001386 return setRadioForSubscriber(getDefaultSubscription(), turnOn);
Wink Saville36469e72014-06-11 15:17:00 -07001387 }
1388
Wink Savilleb564aae2014-10-23 10:18:09 -07001389 public boolean setRadioForSubscriber(int subId, boolean turnOn) {
Wink Saville36469e72014-06-11 15:17:00 -07001390 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001391 final Phone phone = getPhone(subId);
1392 if (phone == null) {
1393 return false;
1394 }
1395 if ((phone.getServiceState().getState() !=
Wink Saville36469e72014-06-11 15:17:00 -07001396 ServiceState.STATE_POWER_OFF) != turnOn) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001397 toggleRadioOnOffForSubscriber(subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001398 }
1399 return true;
1400 }
Wink Saville36469e72014-06-11 15:17:00 -07001401
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001402 public boolean needMobileRadioShutdown() {
1403 /*
1404 * If any of the Radios are available, it will need to be
1405 * shutdown. So return true if any Radio is available.
1406 */
1407 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1408 Phone phone = PhoneFactory.getPhone(i);
1409 if (phone != null && phone.isRadioAvailable()) return true;
1410 }
1411 logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1412 return false;
1413 }
1414
1415 public void shutdownMobileRadios() {
1416 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1417 logv("Shutting down Phone " + i);
1418 shutdownRadioUsingPhoneId(i);
1419 }
1420 }
1421
1422 private void shutdownRadioUsingPhoneId(int phoneId) {
1423 enforceModifyPermission();
1424 Phone phone = PhoneFactory.getPhone(phoneId);
1425 if (phone != null && phone.isRadioAvailable()) {
1426 phone.shutdownRadio();
1427 }
1428 }
1429
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001430 public boolean setRadioPower(boolean turnOn) {
Wei Liu9ae2a062016-08-08 11:09:34 -07001431 final Phone defaultPhone = PhoneFactory.getDefaultPhone();
1432 if (defaultPhone != null) {
1433 defaultPhone.setRadioPower(turnOn);
1434 return true;
1435 } else {
1436 loge("There's no default phone.");
1437 return false;
1438 }
Wink Saville36469e72014-06-11 15:17:00 -07001439 }
1440
Wink Savilleb564aae2014-10-23 10:18:09 -07001441 public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001442 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001443 final Phone phone = getPhone(subId);
1444 if (phone != null) {
1445 phone.setRadioPower(turnOn);
1446 return true;
1447 } else {
1448 return false;
1449 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001450 }
1451
Wink Saville36469e72014-06-11 15:17:00 -07001452 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001453 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001454 public boolean enableDataConnectivity() {
1455 enforceModifyPermission();
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001456 int subId = mSubscriptionController.getDefaultDataSubId();
Sanket Padawe356d7632015-06-22 14:03:32 -07001457 final Phone phone = getPhone(subId);
1458 if (phone != null) {
1459 phone.setDataEnabled(true);
1460 return true;
1461 } else {
1462 return false;
1463 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001464 }
1465
Wink Saville36469e72014-06-11 15:17:00 -07001466 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001467 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001468 public boolean disableDataConnectivity() {
1469 enforceModifyPermission();
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001470 int subId = mSubscriptionController.getDefaultDataSubId();
Sanket Padawe356d7632015-06-22 14:03:32 -07001471 final Phone phone = getPhone(subId);
1472 if (phone != null) {
1473 phone.setDataEnabled(false);
1474 return true;
1475 } else {
1476 return false;
1477 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001478 }
1479
Wink Saville36469e72014-06-11 15:17:00 -07001480 // FIXME: subId version needed
Sanket Padawe356d7632015-06-22 14:03:32 -07001481 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001482 public boolean isDataConnectivityPossible() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001483 int subId = mSubscriptionController.getDefaultDataSubId();
Sanket Padawe356d7632015-06-22 14:03:32 -07001484 final Phone phone = getPhone(subId);
1485 if (phone != null) {
1486 return phone.isDataConnectivityPossible();
1487 } else {
1488 return false;
1489 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001490 }
1491
1492 public boolean handlePinMmi(String dialString) {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001493 return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
Wink Saville36469e72014-06-11 15:17:00 -07001494 }
1495
pkanwarae03a6b2016-11-06 20:37:09 -08001496 public void handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback) {
pkanwar32d516d2016-10-14 19:37:38 -07001497 enforceCallPermission();
pkanwar32d516d2016-10-14 19:37:38 -07001498 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1499 return;
1500 }
1501 Pair<String, ResultReceiver> ussdObject = new Pair(ussdRequest, wrappedCallback);
1502 sendRequest(CMD_HANDLE_USSD_REQUEST, ussdObject, subId);
1503 };
1504
1505
Wink Savilleb564aae2014-10-23 10:18:09 -07001506 public boolean handlePinMmiForSubscriber(int subId, String dialString) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001507 enforceModifyPermission();
Sanket Padawe356d7632015-06-22 14:03:32 -07001508 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1509 return false;
1510 }
Wink Saville36469e72014-06-11 15:17:00 -07001511 return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001512 }
1513
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001514 public int getCallState() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001515 return getCallStateForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001516 }
1517
Shishir Agrawala9f32182016-04-12 12:00:16 -07001518 public int getCallStateForSlot(int slotId) {
1519 Phone phone = PhoneFactory.getPhone(slotId);
1520 return phone == null ? TelephonyManager.CALL_STATE_IDLE :
1521 DefaultPhoneNotifier.convertCallState(phone.getState());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001522 }
1523
Sanket Padawe356d7632015-06-22 14:03:32 -07001524 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001525 public int getDataState() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001526 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
Sanket Padawe356d7632015-06-22 14:03:32 -07001527 if (phone != null) {
1528 return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
1529 } else {
1530 return DefaultPhoneNotifier.convertDataState(PhoneConstants.DataState.DISCONNECTED);
1531 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001532 }
1533
Sanket Padawe356d7632015-06-22 14:03:32 -07001534 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001535 public int getDataActivity() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08001536 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
Sanket Padawe356d7632015-06-22 14:03:32 -07001537 if (phone != null) {
1538 return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
1539 } else {
1540 return TelephonyManager.DATA_ACTIVITY_NONE;
1541 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001542 }
1543
1544 @Override
Svetoslav64fad262015-04-14 14:35:21 -07001545 public Bundle getCellLocation(String callingPackage) {
1546 enforceFineOrCoarseLocationPermission("getCellLocation");
1547
1548 // OP_COARSE_LOCATION controls both fine and coarse location.
1549 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1550 callingPackage) != AppOpsManager.MODE_ALLOWED) {
Amit Mahajan9acc70d2015-06-02 13:17:33 -07001551 log("getCellLocation: returning null; mode != allowed");
Svetoslav64fad262015-04-14 14:35:21 -07001552 return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001553 }
1554
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001555 if (checkIfCallerIsSelfOrForegroundUser() ||
1556 checkCallerInteractAcrossUsersFull()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001557 if (DBG_LOC) log("getCellLocation: is active user");
1558 Bundle data = new Bundle();
Legler Wu2c01cdf2014-12-08 19:00:59 +08001559 Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
Sanket Padawe356d7632015-06-22 14:03:32 -07001560 if (phone == null) {
1561 return null;
1562 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07001563
1564 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
1565 phone.getCellLocation(workSource).fillInNotifierBundle(data);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001566 return data;
1567 } else {
Amit Mahajan9acc70d2015-06-02 13:17:33 -07001568 log("getCellLocation: suppress non-active user");
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001569 return null;
1570 }
1571 }
1572
Svetoslav64fad262015-04-14 14:35:21 -07001573 private void enforceFineOrCoarseLocationPermission(String message) {
1574 try {
1575 mApp.enforceCallingOrSelfPermission(
1576 android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1577 } catch (SecurityException e) {
1578 // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1579 // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1580 // is the weaker precondition
1581 mApp.enforceCallingOrSelfPermission(
1582 android.Manifest.permission.ACCESS_COARSE_LOCATION, message);
1583 }
1584 }
1585
1586
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001587 @Override
1588 public void enableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001589 enableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001590 }
1591
Sanket Padawe356d7632015-06-22 14:03:32 -07001592 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001593 public void enableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001594 mApp.enforceCallingOrSelfPermission(
1595 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Sanket Padawe356d7632015-06-22 14:03:32 -07001596 final Phone phone = getPhone(subId);
1597 if (phone != null) {
1598 phone.enableLocationUpdates();
1599 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001600 }
1601
1602 @Override
1603 public void disableLocationUpdates() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07001604 disableLocationUpdatesForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001605 }
1606
Sanket Padawe356d7632015-06-22 14:03:32 -07001607 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001608 public void disableLocationUpdatesForSubscriber(int subId) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001609 mApp.enforceCallingOrSelfPermission(
1610 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
Sanket Padawe356d7632015-06-22 14:03:32 -07001611 final Phone phone = getPhone(subId);
1612 if (phone != null) {
1613 phone.disableLocationUpdates();
1614 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001615 }
1616
1617 @Override
1618 @SuppressWarnings("unchecked")
1619 public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
Svetoslav64fad262015-04-14 14:35:21 -07001620 enforceFineOrCoarseLocationPermission("getNeighboringCellInfo");
1621
1622 // OP_COARSE_LOCATION controls both fine and coarse location.
1623 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1624 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1625 return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001626 }
1627
1628 if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1629 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1630 return null;
1631 }
Svetoslav64fad262015-04-14 14:35:21 -07001632
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001633 if (checkIfCallerIsSelfOrForegroundUser() ||
1634 checkCallerInteractAcrossUsersFull()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001635 if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1636
1637 ArrayList<NeighboringCellInfo> cells = null;
1638
Sooraj Sasindran9a909312016-07-18 11:57:25 -07001639 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001640 try {
1641 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
Sooraj Sasindran9a909312016-07-18 11:57:25 -07001642 CMD_HANDLE_NEIGHBORING_CELL, workSource,
Sanket Padawe56e75a32016-02-08 12:18:19 -08001643 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001644 } catch (RuntimeException e) {
Wink Saville36469e72014-06-11 15:17:00 -07001645 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001646 }
1647 return cells;
1648 } else {
1649 if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1650 return null;
1651 }
1652 }
1653
1654
1655 @Override
Svetoslav64fad262015-04-14 14:35:21 -07001656 public List<CellInfo> getAllCellInfo(String callingPackage) {
1657 enforceFineOrCoarseLocationPermission("getAllCellInfo");
1658
1659 // OP_COARSE_LOCATION controls both fine and coarse location.
1660 if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1661 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1662 return null;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001663 }
1664
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001665 if (checkIfCallerIsSelfOrForegroundUser() ||
1666 checkCallerInteractAcrossUsersFull()) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001667 if (DBG_LOC) log("getAllCellInfo: is active user");
Sooraj Sasindran9a909312016-07-18 11:57:25 -07001668 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
Legler Wu2c01cdf2014-12-08 19:00:59 +08001669 List<CellInfo> cellInfos = new ArrayList<CellInfo>();
1670 for (Phone phone : PhoneFactory.getPhones()) {
Sooraj Sasindran9a909312016-07-18 11:57:25 -07001671 final List<CellInfo> info = phone.getAllCellInfo(workSource);
1672 if (info != null) cellInfos.addAll(info);
Legler Wu2c01cdf2014-12-08 19:00:59 +08001673 }
1674 return cellInfos;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001675 } else {
1676 if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1677 return null;
1678 }
1679 }
1680
Sailesh Nepalbd76e4e2013-10-27 13:59:44 -07001681 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001682 public void setCellInfoListRate(int rateInMillis) {
Sooraj Sasindran9a909312016-07-18 11:57:25 -07001683 WorkSource workSource = getWorkSource(null, Binder.getCallingUid());
1684 mPhone.setCellInfoListRate(rateInMillis, workSource);
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001685 }
1686
Shishir Agrawala9f32182016-04-12 12:00:16 -07001687 @Override
1688 public String getImeiForSlot(int slotId, String callingPackage) {
1689 if (!canReadPhoneState(callingPackage, "getImeiForSlot")) {
1690 return null;
1691 }
1692 Phone phone = PhoneFactory.getPhone(slotId);
1693 return phone == null ? null : phone.getImei();
1694 }
1695
1696 @Override
1697 public String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage) {
1698 if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) {
1699 return null;
1700 }
1701 Phone phone = PhoneFactory.getPhone(slotId);
1702 return phone == null ? null : phone.getDeviceSvn();
1703 }
1704
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001705 //
1706 // Internal helper methods.
1707 //
1708
Sanket Padaweee13a9b2016-03-08 17:30:28 -08001709 /**
1710 * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL.
1711 */
1712 private boolean checkCallerInteractAcrossUsersFull() {
1713 return mPhone.getContext().checkCallingOrSelfPermission(
1714 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1715 == PackageManager.PERMISSION_GRANTED;
1716 }
1717
Jake Hambye994d462014-02-03 13:10:13 -08001718 private static boolean checkIfCallerIsSelfOrForegroundUser() {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001719 boolean ok;
1720
1721 boolean self = Binder.getCallingUid() == Process.myUid();
1722 if (!self) {
1723 // Get the caller's user id then clear the calling identity
1724 // which will be restored in the finally clause.
1725 int callingUser = UserHandle.getCallingUserId();
1726 long ident = Binder.clearCallingIdentity();
1727
1728 try {
1729 // With calling identity cleared the current user is the foreground user.
1730 int foregroundUser = ActivityManager.getCurrentUser();
1731 ok = (foregroundUser == callingUser);
1732 if (DBG_LOC) {
1733 log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1734 + " callingUser=" + callingUser + " ok=" + ok);
1735 }
1736 } catch (Exception ex) {
1737 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1738 ok = false;
1739 } finally {
1740 Binder.restoreCallingIdentity(ident);
1741 }
1742 } else {
1743 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1744 ok = true;
1745 }
1746 if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1747 return ok;
1748 }
1749
1750 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001751 * Make sure the caller has the MODIFY_PHONE_STATE permission.
1752 *
1753 * @throws SecurityException if the caller does not have the required permission
1754 */
1755 private void enforceModifyPermission() {
1756 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1757 }
1758
1759 /**
Junda Liua2e36012014-07-09 18:30:01 -07001760 * Make sure either system app or the caller has carrier privilege.
1761 *
1762 * @throws SecurityException if the caller does not have the required permission/privilege
1763 */
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001764 private void enforceModifyPermissionOrCarrierPrivilege(int subId) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001765 int permission = mApp.checkCallingOrSelfPermission(
1766 android.Manifest.permission.MODIFY_PHONE_STATE);
1767 if (permission == PackageManager.PERMISSION_GRANTED) {
1768 return;
1769 }
1770
1771 log("No modify permission, check carrier privilege next.");
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001772 enforceCarrierPrivilege(subId);
Junda Liua2e36012014-07-09 18:30:01 -07001773 }
1774
1775 /**
1776 * Make sure the caller has carrier privilege.
1777 *
1778 * @throws SecurityException if the caller does not have the required permission
1779 */
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001780 private void enforceCarrierPrivilege(int subId) {
1781 if (getCarrierPrivilegeStatus(subId) !=
1782 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
Shishir Agrawalf1ac4c92014-07-14 13:54:28 -07001783 loge("No Carrier Privilege.");
1784 throw new SecurityException("No Carrier Privilege.");
Junda Liua2e36012014-07-09 18:30:01 -07001785 }
1786 }
1787
1788 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001789 * Make sure the caller has the CALL_PHONE permission.
1790 *
1791 * @throws SecurityException if the caller does not have the required permission
1792 */
1793 private void enforceCallPermission() {
1794 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1795 }
1796
Stuart Scott8eef64f2015-04-08 15:13:54 -07001797 private void enforceConnectivityInternalPermission() {
1798 mApp.enforceCallingOrSelfPermission(
1799 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1800 "ConnectivityService");
1801 }
1802
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001803 private String createTelUrl(String number) {
1804 if (TextUtils.isEmpty(number)) {
1805 return null;
1806 }
1807
Jake Hambye994d462014-02-03 13:10:13 -08001808 return "tel:" + number;
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001809 }
1810
Ihab Awadf9e92732013-12-05 18:02:52 -08001811 private static void log(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001812 Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1813 }
1814
Naveen Kalla1fd79bd2014-08-08 00:48:59 -07001815 private static void logv(String msg) {
1816 Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1817 }
1818
Ihab Awadf9e92732013-12-05 18:02:52 -08001819 private static void loge(String msg) {
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001820 Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1821 }
1822
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001823 @Override
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001824 public int getActivePhoneType() {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001825 return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07001826 }
1827
Sanket Padawe356d7632015-06-22 14:03:32 -07001828 @Override
Shishir Agrawala9f32182016-04-12 12:00:16 -07001829 public int getActivePhoneTypeForSlot(int slotId) {
1830 final Phone phone = PhoneFactory.getPhone(slotId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001831 if (phone == null) {
1832 return PhoneConstants.PHONE_TYPE_NONE;
1833 } else {
Shishir Agrawala9f32182016-04-12 12:00:16 -07001834 return phone.getPhoneType();
Sanket Padawe356d7632015-06-22 14:03:32 -07001835 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001836 }
1837
1838 /**
1839 * Returns the CDMA ERI icon index to display
1840 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001841 @Override
1842 public int getCdmaEriIconIndex(String callingPackage) {
1843 return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001844 }
1845
Sanket Padawe356d7632015-06-22 14:03:32 -07001846 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001847 public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
1848 if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
1849 return -1;
1850 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001851 final Phone phone = getPhone(subId);
1852 if (phone != null) {
1853 return phone.getCdmaEriIconIndex();
1854 } else {
1855 return -1;
1856 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001857 }
1858
1859 /**
1860 * Returns the CDMA ERI icon mode,
1861 * 0 - ON
1862 * 1 - FLASHING
1863 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001864 @Override
1865 public int getCdmaEriIconMode(String callingPackage) {
1866 return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001867 }
1868
Sanket Padawe356d7632015-06-22 14:03:32 -07001869 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001870 public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
1871 if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
1872 return -1;
1873 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001874 final Phone phone = getPhone(subId);
1875 if (phone != null) {
1876 return phone.getCdmaEriIconMode();
1877 } else {
1878 return -1;
1879 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001880 }
1881
1882 /**
1883 * Returns the CDMA ERI text,
1884 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001885 @Override
1886 public String getCdmaEriText(String callingPackage) {
1887 return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07001888 }
1889
Sanket Padawe356d7632015-06-22 14:03:32 -07001890 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07001891 public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
1892 if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
1893 return null;
1894 }
Sanket Padawe356d7632015-06-22 14:03:32 -07001895 final Phone phone = getPhone(subId);
1896 if (phone != null) {
1897 return phone.getCdmaEriText();
1898 } else {
1899 return null;
1900 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001901 }
1902
1903 /**
Junda Liuca05d5d2014-08-14 22:36:34 -07001904 * Returns the CDMA MDN.
1905 */
Sanket Padawe356d7632015-06-22 14:03:32 -07001906 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001907 public String getCdmaMdn(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001908 enforceModifyPermissionOrCarrierPrivilege(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001909 final Phone phone = getPhone(subId);
1910 if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
1911 return phone.getLine1Number();
Junda Liuca05d5d2014-08-14 22:36:34 -07001912 } else {
1913 return null;
1914 }
1915 }
1916
1917 /**
1918 * Returns the CDMA MIN.
1919 */
Sanket Padawe356d7632015-06-22 14:03:32 -07001920 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07001921 public String getCdmaMin(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001922 enforceModifyPermissionOrCarrierPrivilege(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07001923 final Phone phone = getPhone(subId);
1924 if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1925 return phone.getCdmaMin();
Junda Liuca05d5d2014-08-14 22:36:34 -07001926 } else {
1927 return null;
1928 }
1929 }
1930
1931 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07001932 * Returns true if CDMA provisioning needs to run.
1933 */
1934 public boolean needsOtaServiceProvisioning() {
1935 return mPhone.needsOtaServiceProvisioning();
1936 }
1937
1938 /**
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001939 * Sets the voice mail number of a given subId.
1940 */
1941 @Override
1942 public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08001943 enforceCarrierPrivilege(subId);
Shishir Agrawal76d5da92014-11-09 16:17:25 -08001944 Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
1945 new Pair<String, String>(alphaTag, number), new Integer(subId));
1946 return success;
1947 }
1948
Ta-wei Yen87c49842016-05-13 21:19:52 -07001949 @Override
Ta-wei Yenb0f695b2016-08-08 17:33:11 -07001950 public void setVisualVoicemailEnabled(String callingPackage,
1951 PhoneAccountHandle phoneAccountHandle, boolean enabled) {
1952 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1953 if (!TextUtils.equals(callingPackage,
1954 TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
1955 enforceModifyPermissionOrCarrierPrivilege(
1956 PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
1957 }
1958 VisualVoicemailSettingsUtil.setEnabled(mPhone.getContext(), phoneAccountHandle, enabled);
1959 }
1960
1961 @Override
1962 public boolean isVisualVoicemailEnabled(String callingPackage,
1963 PhoneAccountHandle phoneAccountHandle) {
1964 if (!canReadPhoneState(callingPackage, "isVisualVoicemailEnabled")) {
1965 return false;
1966 }
1967 return VisualVoicemailSettingsUtil.isEnabled(mPhone.getContext(), phoneAccountHandle);
1968 }
1969
1970 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07001971 public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
1972 VisualVoicemailSmsFilterSettings settings) {
1973 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001974 VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07001975 .enableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId,
1976 settings);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001977 }
1978
1979 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07001980 public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
1981 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001982 VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07001983 .disableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001984 }
1985
1986 @Override
Ta-wei Yenb6929602016-05-24 15:48:27 -07001987 public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
1988 String callingPackage, int subId) {
1989 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001990 return VisualVoicemailSmsFilterConfig
Ta-wei Yenb6929602016-05-24 15:48:27 -07001991 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), callingPackage, subId);
Ta-wei Yen87c49842016-05-13 21:19:52 -07001992 }
1993
1994 @Override
Ta-wei Yen30a69c82016-12-27 14:52:32 -08001995 public VisualVoicemailSmsFilterSettings getActiveVisualVoicemailSmsFilterSettings(int subId) {
Ta-wei Yenb6929602016-05-24 15:48:27 -07001996 enforceReadPrivilegedPermission();
Ta-wei Yen87c49842016-05-13 21:19:52 -07001997 return VisualVoicemailSmsFilterConfig
Ta-wei Yen30a69c82016-12-27 14:52:32 -08001998 .getActiveVisualVoicemailSmsFilterSettings(mPhone.getContext(), subId);
1999 }
2000
2001 @Override
2002 public void sendVisualVoicemailSmsForSubscriber(String callingPackage, int subId,
2003 String number, int port, String text, PendingIntent sentIntent) {
2004 mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
2005 enforceDefaultDialer(callingPackage);
2006 enforceSendSmsPermission();
2007 // Make the calls as the phone process.
2008 final long identity = Binder.clearCallingIdentity();
2009 try {
2010 SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(subId);
2011 if (port == 0) {
2012 smsManager.sendTextMessageWithSelfPermissions(number, null, text,
2013 sentIntent, null, false);
2014 } else {
2015 byte[] data = text.getBytes(StandardCharsets.UTF_8);
2016 smsManager.sendDataMessageWithSelfPermissions(number, null,
2017 (short) port, data, sentIntent, null);
2018 }
2019 } finally {
2020 Binder.restoreCallingIdentity(identity);
2021 }
Ta-wei Yen87c49842016-05-13 21:19:52 -07002022 }
Shishir Agrawal76d5da92014-11-09 16:17:25 -08002023 /**
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002024 * Returns the unread count of voicemails
2025 */
2026 public int getVoiceMessageCount() {
Wink Savilleadd7cc52014-09-08 14:23:09 -07002027 return getVoiceMessageCountForSubscriber(getDefaultSubscription());
Wink Saville36469e72014-06-11 15:17:00 -07002028 }
2029
2030 /**
2031 * Returns the unread count of voicemails for a subId
2032 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002033 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002034 public int getVoiceMessageCountForSubscriber( int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002035 final Phone phone = getPhone(subId);
2036 if (phone != null) {
2037 return phone.getVoiceMessageCount();
2038 } else {
2039 return 0;
2040 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002041 }
2042
2043 /**
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002044 * Returns the data network type.
2045 * Legacy call, permission-free.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002046 *
2047 * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
2048 */
2049 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002050 public int getNetworkType() {
2051 final Phone phone = getPhone(getDefaultSubscription());
2052 if (phone != null) {
2053 return phone.getServiceState().getDataNetworkType();
2054 } else {
2055 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2056 }
Wink Saville36469e72014-06-11 15:17:00 -07002057 }
2058
2059 /**
2060 * Returns the network type for a subId
2061 */
2062 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002063 public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
2064 if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
2065 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2066 }
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002067
Sanket Padawe356d7632015-06-22 14:03:32 -07002068 final Phone phone = getPhone(subId);
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002069 if (phone != null) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002070 return phone.getServiceState().getDataNetworkType();
2071 } else {
2072 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2073 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002074 }
2075
2076 /**
2077 * Returns the data network type
2078 */
2079 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002080 public int getDataNetworkType(String callingPackage) {
2081 return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002082 }
2083
2084 /**
2085 * Returns the data network type for a subId
2086 */
2087 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002088 public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
2089 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2090 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2091 }
2092
Sanket Padawe356d7632015-06-22 14:03:32 -07002093 final Phone phone = getPhone(subId);
2094 if (phone != null) {
2095 return phone.getServiceState().getDataNetworkType();
2096 } else {
2097 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2098 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002099 }
2100
2101 /**
Wink Saville36469e72014-06-11 15:17:00 -07002102 * Returns the Voice network type for a subId
2103 */
2104 @Override
Robert Greenwalta5dcfcb2015-07-10 09:06:29 -07002105 public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
2106 if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2107 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2108 }
2109
Sanket Padawe356d7632015-06-22 14:03:32 -07002110 final Phone phone = getPhone(subId);
2111 if (phone != null) {
2112 return phone.getServiceState().getVoiceNetworkType();
2113 } else {
2114 return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2115 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002116 }
2117
2118 /**
2119 * @return true if a ICC card is present
2120 */
2121 public boolean hasIccCard() {
Wink Saville36469e72014-06-11 15:17:00 -07002122 // FIXME Make changes to pass defaultSimId of type int
Amit Mahajana6fc2a82015-01-06 11:53:51 -08002123 return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription()));
Wink Saville36469e72014-06-11 15:17:00 -07002124 }
2125
2126 /**
2127 * @return true if a ICC card is present for a slotId
2128 */
Sanket Padawe356d7632015-06-22 14:03:32 -07002129 @Override
Wink Savilleb564aae2014-10-23 10:18:09 -07002130 public boolean hasIccCardUsingSlotId(int slotId) {
fionaxu6e6c68b2016-06-23 13:31:32 -07002131 final Phone phone = PhoneFactory.getPhone(slotId);
2132 if (phone != null) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002133 return phone.getIccCard().hasIccCard();
Amit Mahajana6fc2a82015-01-06 11:53:51 -08002134 } else {
2135 return false;
2136 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002137 }
2138
2139 /**
2140 * Return if the current radio is LTE on CDMA. This
2141 * is a tri-state return value as for a period of time
2142 * the mode may be unknown.
2143 *
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002144 * @param callingPackage the name of the package making the call.
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002145 * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
Jake Hambye994d462014-02-03 13:10:13 -08002146 * or {@link Phone#LTE_ON_CDMA_TRUE}
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002147 */
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002148 @Override
2149 public int getLteOnCdmaMode(String callingPackage) {
2150 return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
Wink Saville36469e72014-06-11 15:17:00 -07002151 }
2152
Sanket Padawe356d7632015-06-22 14:03:32 -07002153 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002154 public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
2155 if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
2156 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2157 }
2158
Sanket Padawe356d7632015-06-22 14:03:32 -07002159 final Phone phone = getPhone(subId);
2160 if (phone == null) {
2161 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2162 } else {
2163 return phone.getLteOnCdmaMode();
2164 }
Wink Saville36469e72014-06-11 15:17:00 -07002165 }
2166
2167 public void setPhone(Phone phone) {
2168 mPhone = phone;
2169 }
2170
2171 /**
2172 * {@hide}
2173 * Returns Default subId, 0 in the case of single standby.
2174 */
Wink Savilleb564aae2014-10-23 10:18:09 -07002175 private int getDefaultSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08002176 return mSubscriptionController.getDefaultSubId();
Wink Saville36469e72014-06-11 15:17:00 -07002177 }
2178
Shishir Agrawala9f32182016-04-12 12:00:16 -07002179 private int getSlotForDefaultSubscription() {
2180 return mSubscriptionController.getPhoneId(getDefaultSubscription());
2181 }
2182
Wink Savilleb564aae2014-10-23 10:18:09 -07002183 private int getPreferredVoiceSubscription() {
Wink Savilleac1bdfd2014-11-20 23:04:44 -08002184 return mSubscriptionController.getDefaultVoiceSubId();
Santos Cordon7d4ddf62013-07-10 11:58:08 -07002185 }
Ihab Awadf2177b72013-11-25 13:33:23 -08002186
2187 /**
2188 * @see android.telephony.TelephonyManager.WifiCallingChoices
2189 */
2190 public int getWhenToMakeWifiCalls() {
Sailesh Nepald1e68152013-12-12 19:08:02 -08002191 return Settings.System.getInt(mPhone.getContext().getContentResolver(),
2192 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
Ihab Awadf2177b72013-11-25 13:33:23 -08002193 }
2194
2195 /**
2196 * @see android.telephony.TelephonyManager.WifiCallingChoices
2197 */
2198 public void setWhenToMakeWifiCalls(int preference) {
Sailesh Nepald1e68152013-12-12 19:08:02 -08002199 if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
2200 Settings.System.putInt(mPhone.getContext().getContentResolver(),
2201 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
Ihab Awadf9e92732013-12-05 18:02:52 -08002202 }
2203
Sailesh Nepald1e68152013-12-12 19:08:02 -08002204 private static int getWhenToMakeWifiCallsDefaultPreference() {
Santos Cordonda120f42014-08-06 04:44:34 -07002205 // TODO: Use a build property to choose this value.
Evan Charlton9829e882013-12-19 15:30:38 -08002206 return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
Ihab Awadf2177b72013-11-25 13:33:23 -08002207 }
Shishir Agrawal69f68122013-12-16 17:25:49 -08002208
Shishir Agrawal566b7612013-10-28 14:41:00 -07002209 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002210 public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) {
2211 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002212
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002213 if (DBG) log("iccOpenLogicalChannel: subId=" + subId + " aid=" + AID);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002214 IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002215 CMD_OPEN_CHANNEL, AID, subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002216 if (DBG) log("iccOpenLogicalChannel: " + response);
2217 return response;
Shishir Agrawal566b7612013-10-28 14:41:00 -07002218 }
2219
2220 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002221 public boolean iccCloseLogicalChannel(int subId, int channel) {
2222 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002223
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002224 if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002225 if (channel < 0) {
2226 return false;
2227 }
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002228 Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel, subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002229 if (DBG) log("iccCloseLogicalChannel: " + success);
2230 return success;
2231 }
2232
2233 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002234 public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
Shishir Agrawal566b7612013-10-28 14:41:00 -07002235 int command, int p1, int p2, int p3, String data) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002236 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002237
2238 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002239 log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel +
2240 " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
Shishir Agrawal566b7612013-10-28 14:41:00 -07002241 " data=" + data);
2242 }
2243
2244 if (channel < 0) {
2245 return "";
2246 }
2247
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002248 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002249 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId);
Shishir Agrawal566b7612013-10-28 14:41:00 -07002250 if (DBG) log("iccTransmitApduLogicalChannel: " + response);
2251
Shishir Agrawal566b7612013-10-28 14:41:00 -07002252 // Append the returned status code to the end of the response payload.
2253 String s = Integer.toHexString(
2254 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07002255 if (response.payload != null) {
2256 s = IccUtils.bytesToHexString(response.payload) + s;
2257 }
Shishir Agrawal566b7612013-10-28 14:41:00 -07002258 return s;
2259 }
Jake Hambye994d462014-02-03 13:10:13 -08002260
Evan Charltonc66da362014-05-16 14:06:40 -07002261 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002262 public String iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002263 int p3, String data) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002264 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002265
2266 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002267 log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd=" + command
2268 + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002269 }
2270
2271 IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002272 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002273 if (DBG) log("iccTransmitApduBasicChannel: " + response);
2274
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002275 // Append the returned status code to the end of the response payload.
2276 String s = Integer.toHexString(
2277 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
Shishir Agrawal5ec14172014-08-05 17:05:45 -07002278 if (response.payload != null) {
2279 s = IccUtils.bytesToHexString(response.payload) + s;
2280 }
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002281 return s;
2282 }
2283
2284 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002285 public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002286 String filePath) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002287 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002288
2289 if (DBG) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002290 log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " +
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002291 p1 + " " + p2 + " " + p3 + ":" + filePath);
2292 }
2293
2294 IccIoResult response =
2295 (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002296 new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
2297 subId);
Shishir Agrawalda0bb0d2014-07-29 21:18:53 -07002298
2299 if (DBG) {
2300 log("Exchange SIM_IO [R]" + response);
2301 }
2302
2303 byte[] result = null;
2304 int length = 2;
2305 if (response.payload != null) {
2306 length = 2 + response.payload.length;
2307 result = new byte[length];
2308 System.arraycopy(response.payload, 0, result, 0, response.payload.length);
2309 } else {
2310 result = new byte[length];
2311 }
2312
2313 result[length - 1] = (byte) response.sw2;
2314 result[length - 2] = (byte) response.sw1;
2315 return result;
2316 }
2317
2318 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002319 public String sendEnvelopeWithStatus(int subId, String content) {
2320 enforceModifyPermissionOrCarrierPrivilege(subId);
Evan Charltonc66da362014-05-16 14:06:40 -07002321
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002322 IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId);
Evan Charltonc66da362014-05-16 14:06:40 -07002323 if (response.payload == null) {
2324 return "";
2325 }
2326
2327 // Append the returned status code to the end of the response payload.
2328 String s = Integer.toHexString(
2329 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2330 s = IccUtils.bytesToHexString(response.payload) + s;
2331 return s;
2332 }
2333
Jake Hambye994d462014-02-03 13:10:13 -08002334 /**
2335 * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2336 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2337 *
2338 * @param itemID the ID of the item to read
2339 * @return the NV item as a String, or null on error.
2340 */
2341 @Override
2342 public String nvReadItem(int itemID) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002343 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002344 if (DBG) log("nvReadItem: item " + itemID);
2345 String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
2346 if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
2347 return value;
2348 }
2349
2350 /**
2351 * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2352 * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2353 *
2354 * @param itemID the ID of the item to read
2355 * @param itemValue the value to write, as a String
2356 * @return true on success; false on any failure
2357 */
2358 @Override
2359 public boolean nvWriteItem(int itemID, String itemValue) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002360 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002361 if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
2362 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
2363 new Pair<Integer, String>(itemID, itemValue));
2364 if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
2365 return success;
2366 }
2367
2368 /**
2369 * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
2370 * Used for device configuration by some CDMA operators.
2371 *
2372 * @param preferredRoamingList byte array containing the new PRL
2373 * @return true on success; false on any failure
2374 */
2375 @Override
2376 public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002377 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002378 if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
2379 Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
2380 if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
2381 return success;
2382 }
2383
2384 /**
2385 * Perform the specified type of NV config reset.
2386 * Used for device configuration by some CDMA operators.
2387 *
2388 * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
2389 * @return true on success; false on any failure
2390 */
2391 @Override
2392 public boolean nvResetConfig(int resetType) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002393 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
Jake Hambye994d462014-02-03 13:10:13 -08002394 if (DBG) log("nvResetConfig: type " + resetType);
2395 Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
2396 if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
2397 return success;
2398 }
Jake Hamby7c27be32014-03-03 13:25:59 -08002399
2400 /**
Wink Saville36469e72014-06-11 15:17:00 -07002401 * {@hide}
2402 * Returns Default sim, 0 in the case of single standby.
2403 */
2404 public int getDefaultSim() {
2405 //TODO Need to get it from Telephony Devcontroller
2406 return 0;
2407 }
2408
Svet Ganovb320e182015-04-16 12:30:10 -07002409 public String[] getPcscfAddress(String apnType, String callingPackage) {
2410 if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
2411 return new String[0];
2412 }
2413
2414
ram87fca6f2014-07-18 18:58:44 +05302415 return mPhone.getPcscfAddress(apnType);
Wink Saville36469e72014-06-11 15:17:00 -07002416 }
2417
2418 public void setImsRegistrationState(boolean registered) {
2419 enforceModifyPermission();
2420 mPhone.setImsRegistrationState(registered);
2421 }
2422
2423 /**
Stuart Scott54788802015-03-30 13:18:01 -07002424 * Set the network selection mode to automatic.
2425 *
2426 */
2427 @Override
2428 public void setNetworkSelectionModeAutomatic(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002429 enforceModifyPermissionOrCarrierPrivilege(subId);
Stuart Scott54788802015-03-30 13:18:01 -07002430 if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
2431 sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
2432 }
2433
2434 /**
Shishir Agrawal302c8692015-06-19 13:49:39 -07002435 * Set the network selection mode to manual with the selected carrier.
2436 */
2437 @Override
Shishir Agrawal77ba3172015-09-10 14:50:19 -07002438 public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
2439 boolean persistSelection) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002440 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002441 if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
Shishir Agrawal77ba3172015-09-10 14:50:19 -07002442 ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
2443 persistSelection);
2444 return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002445 }
2446
2447 /**
2448 * Scans for available networks.
2449 */
2450 @Override
2451 public CellNetworkScanResult getCellNetworkScanResults(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002452 enforceModifyPermissionOrCarrierPrivilege(subId);
Shishir Agrawal302c8692015-06-19 13:49:39 -07002453 if (DBG) log("getCellNetworkScanResults: subId " + subId);
2454 CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
2455 CMD_PERFORM_NETWORK_SCAN, null, subId);
2456 return result;
2457 }
2458
2459 /**
Junda Liu84d15a22014-07-02 11:21:04 -07002460 * Get the calculated preferred network type.
2461 * Used for debugging incorrect network type.
2462 *
2463 * @return the preferred network type, defined in RILConstants.java.
2464 */
2465 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002466 public int getCalculatedPreferredNetworkType(String callingPackage) {
2467 if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
2468 return RILConstants.PREFERRED_NETWORK_MODE;
2469 }
2470
Amit Mahajan43330e02014-11-18 11:54:45 -08002471 return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
Junda Liu84d15a22014-07-02 11:21:04 -07002472 }
2473
2474 /**
Jake Hamby7c27be32014-03-03 13:25:59 -08002475 * Get the preferred network type.
2476 * Used for device configuration by some CDMA operators.
2477 *
2478 * @return the preferred network type, defined in RILConstants.java.
2479 */
2480 @Override
Stuart Scott54788802015-03-30 13:18:01 -07002481 public int getPreferredNetworkType(int subId) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002482 enforceModifyPermissionOrCarrierPrivilege(subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002483 if (DBG) log("getPreferredNetworkType");
Stuart Scott54788802015-03-30 13:18:01 -07002484 int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002485 int networkType = (result != null ? result[0] : -1);
2486 if (DBG) log("getPreferredNetworkType: " + networkType);
2487 return networkType;
2488 }
2489
2490 /**
2491 * Set the preferred network type.
2492 * Used for device configuration by some CDMA operators.
2493 *
2494 * @param networkType the preferred network type, defined in RILConstants.java.
2495 * @return true on success; false on any failure.
2496 */
2497 @Override
Stuart Scott54788802015-03-30 13:18:01 -07002498 public boolean setPreferredNetworkType(int subId, int networkType) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002499 enforceModifyPermissionOrCarrierPrivilege(subId);
Stuart Scott54788802015-03-30 13:18:01 -07002500 if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
2501 Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
Jake Hamby7c27be32014-03-03 13:25:59 -08002502 if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
Junda Liu80bc0d12014-07-14 16:36:44 -07002503 if (success) {
2504 Settings.Global.putInt(mPhone.getContext().getContentResolver(),
Stuart Scott54788802015-03-30 13:18:01 -07002505 Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
Junda Liu80bc0d12014-07-14 16:36:44 -07002506 }
Jake Hamby7c27be32014-03-03 13:25:59 -08002507 return success;
2508 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002509
2510 /**
Junda Liu475951f2014-11-07 16:45:03 -08002511 * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
2512 * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
2513 * tethering.
2514 *
2515 * @return 0: Not required. 1: required. 2: Not set.
2516 * @hide
2517 */
2518 @Override
2519 public int getTetherApnRequired() {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002520 enforceModifyPermission();
Junda Liu475951f2014-11-07 16:45:03 -08002521 int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2522 Settings.Global.TETHER_DUN_REQUIRED, 2);
2523 // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2524 // config_tether_apndata.
2525 if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2526 dunRequired = 1;
2527 }
2528 return dunRequired;
2529 }
2530
2531 /**
Robert Greenwalted86e582014-05-21 20:03:20 -07002532 * Set mobile data enabled
2533 * Used by the user through settings etc to turn on/off mobile data
2534 *
2535 * @param enable {@code true} turn turn data on, else {@code false}
2536 */
2537 @Override
Wink Savillee7353bb2014-12-05 14:21:41 -08002538 public void setDataEnabled(int subId, boolean enable) {
Jeff Davidsona1920712016-11-18 17:05:56 -08002539 enforceModifyPermissionOrCarrierPrivilege(subId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002540 int phoneId = mSubscriptionController.getPhoneId(subId);
Joe Onoratoa601dd22016-02-23 13:03:53 -08002541 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002542 Phone phone = PhoneFactory.getPhone(phoneId);
2543 if (phone != null) {
Joe Onoratoa601dd22016-02-23 13:03:53 -08002544 if (DBG) log("setDataEnabled: subId=" + subId + " enable=" + enable);
Wink Savillee7353bb2014-12-05 14:21:41 -08002545 phone.setDataEnabled(enable);
2546 } else {
2547 loge("setDataEnabled: no phone for subId=" + subId);
2548 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002549 }
2550
2551 /**
Robert Greenwalt646120a2014-05-23 11:54:03 -07002552 * Get whether mobile data is enabled.
2553 *
Jeff Davidsona1920712016-11-18 17:05:56 -08002554 * Accepts either ACCESS_NETWORK_STATE, MODIFY_PHONE_STATE or carrier privileges.
Robert Greenwalted86e582014-05-21 20:03:20 -07002555 *
2556 * @return {@code true} if data is enabled else {@code false}
2557 */
2558 @Override
Wink Savillee7353bb2014-12-05 14:21:41 -08002559 public boolean getDataEnabled(int subId) {
Robert Greenwalt646120a2014-05-23 11:54:03 -07002560 try {
2561 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2562 null);
2563 } catch (Exception e) {
Jeff Davidsona1920712016-11-18 17:05:56 -08002564 enforceModifyPermissionOrCarrierPrivilege(subId);
Robert Greenwalt646120a2014-05-23 11:54:03 -07002565 }
Wink Savillee7353bb2014-12-05 14:21:41 -08002566 int phoneId = mSubscriptionController.getPhoneId(subId);
Joe Onoratoa601dd22016-02-23 13:03:53 -08002567 if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Wink Savillee7353bb2014-12-05 14:21:41 -08002568 Phone phone = PhoneFactory.getPhone(phoneId);
2569 if (phone != null) {
2570 boolean retVal = phone.getDataEnabled();
Joe Onoratoa601dd22016-02-23 13:03:53 -08002571 if (DBG) log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
Wink Savillee7353bb2014-12-05 14:21:41 -08002572 return retVal;
2573 } else {
Joe Onoratoa601dd22016-02-23 13:03:53 -08002574 if (DBG) loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
Wink Savillee7353bb2014-12-05 14:21:41 -08002575 return false;
2576 }
Robert Greenwalted86e582014-05-21 20:03:20 -07002577 }
Shishir Agrawal60f9c952014-06-23 12:00:43 -07002578
2579 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002580 public int getCarrierPrivilegeStatus(int subId) {
2581 final Phone phone = getPhone(subId);
2582 if (phone == null) {
2583 loge("getCarrierPrivilegeStatus: Invalid subId");
2584 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2585 }
2586 UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002587 if (card == null) {
Shishir Agrawal5e5becd2014-11-18 11:38:23 -08002588 loge("getCarrierPrivilegeStatus: No UICC");
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002589 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2590 }
2591 return card.getCarrierPrivilegeStatusForCurrentTransaction(
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002592 phone.getContext().getPackageManager());
Shishir Agrawal60f9c952014-06-23 12:00:43 -07002593 }
Junda Liu29340342014-07-10 15:23:27 -07002594
2595 @Override
Zach Johnson50ecba32015-05-19 00:24:21 -07002596 public int checkCarrierPrivilegesForPackage(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08002597 if (TextUtils.isEmpty(pkgName))
2598 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Shishir Agrawal21409252015-01-15 23:33:50 -08002599 UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
Shishir Agrawaleb8771e2014-07-22 11:24:08 -07002600 if (card == null) {
2601 loge("checkCarrierPrivilegesForPackage: No UICC");
2602 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2603 }
Zach Johnson50ecba32015-05-19 00:24:21 -07002604 return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
2605 }
2606
2607 @Override
2608 public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
Junda Liu317d70b2016-03-08 09:33:53 -08002609 if (TextUtils.isEmpty(pkgName))
2610 return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
Zach Johnson50ecba32015-05-19 00:24:21 -07002611 int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2612 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2613 UiccCard card = UiccController.getInstance().getUiccCard(i);
2614 if (card == null) {
Jonathan Basseri7d320df2015-06-16 12:17:08 -07002615 // No UICC in that slot.
Zach Johnson50ecba32015-05-19 00:24:21 -07002616 continue;
2617 }
2618
2619 result = card.getCarrierPrivilegeStatus(
2620 mPhone.getContext().getPackageManager(), pkgName);
2621 if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2622 break;
2623 }
2624 }
2625
2626 return result;
Junda Liu29340342014-07-10 15:23:27 -07002627 }
Derek Tan89e89d42014-07-08 17:00:10 -07002628
2629 @Override
Junda Liue64de782015-04-16 17:19:16 -07002630 public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2631 if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2632 loge("phoneId " + phoneId + " is not valid.");
2633 return null;
2634 }
2635 UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002636 if (card == null) {
Diego Pontorieroaf74c862014-08-28 11:51:16 -07002637 loge("getCarrierPackageNamesForIntent: No UICC");
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002638 return null ;
2639 }
Diego Pontorieroaf74c862014-08-28 11:51:16 -07002640 return card.getCarrierPackageNamesForIntent(
Svetoslav483aff72015-04-21 14:16:07 -07002641 mPhone.getContext().getPackageManager(), intent);
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002642 }
2643
Amith Yamasani6e118872016-02-19 12:53:51 -08002644 @Override
2645 public List<String> getPackagesWithCarrierPrivileges() {
2646 PackageManager pm = mPhone.getContext().getPackageManager();
2647 List<String> privilegedPackages = new ArrayList<>();
2648 List<PackageInfo> packages = null;
2649 for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2650 UiccCard card = UiccController.getInstance().getUiccCard(i);
2651 if (card == null) {
2652 // No UICC in that slot.
2653 continue;
2654 }
2655 if (card.hasCarrierPrivilegeRules()) {
2656 if (packages == null) {
2657 // Only check packages in user 0 for now
2658 packages = pm.getInstalledPackagesAsUser(
2659 PackageManager.MATCH_DISABLED_COMPONENTS
2660 | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
2661 | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
2662 }
2663 for (int p = packages.size() - 1; p >= 0; p--) {
2664 PackageInfo pkgInfo = packages.get(p);
2665 if (pkgInfo != null && pkgInfo.packageName != null
2666 && card.getCarrierPrivilegeStatus(pkgInfo)
2667 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2668 privilegedPackages.add(pkgInfo.packageName);
2669 }
2670 }
2671 }
2672 }
2673 return privilegedPackages;
2674 }
2675
Wink Savilleb564aae2014-10-23 10:18:09 -07002676 private String getIccId(int subId) {
Sanket Padawe356d7632015-06-22 14:03:32 -07002677 final Phone phone = getPhone(subId);
2678 UiccCard card = phone == null ? null : phone.getUiccCard();
Derek Tan97ebb422014-09-05 16:55:38 -07002679 if (card == null) {
2680 loge("getIccId: No UICC");
2681 return null;
2682 }
2683 String iccId = card.getIccId();
2684 if (TextUtils.isEmpty(iccId)) {
2685 loge("getIccId: ICC ID is null or empty.");
2686 return null;
2687 }
2688 return iccId;
2689 }
2690
Shishir Agrawaleb6439a2014-07-21 13:19:38 -07002691 @Override
Jeff Sharkey85190e62014-12-05 09:40:12 -08002692 public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
2693 String number) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002694 enforceCarrierPrivilege(subId);
Derek Tan97ebb422014-09-05 16:55:38 -07002695
Jeff Sharkey85190e62014-12-05 09:40:12 -08002696 final String iccId = getIccId(subId);
Sanket Padawe356d7632015-06-22 14:03:32 -07002697 final Phone phone = getPhone(subId);
2698 if (phone == null) {
2699 return false;
2700 }
2701 final String subscriberId = phone.getSubscriberId();
Jeff Sharkey85190e62014-12-05 09:40:12 -08002702
2703 if (DBG_MERGE) {
2704 Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
2705 + subscriberId + " to " + number);
2706 }
2707
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002708 if (TextUtils.isEmpty(iccId)) {
2709 return false;
Derek Tan97ebb422014-09-05 16:55:38 -07002710 }
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002711
Jeff Sharkey85190e62014-12-05 09:40:12 -08002712 final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2713
2714 final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002715 if (alphaTag == null) {
2716 editor.remove(alphaTagPrefKey);
2717 } else {
2718 editor.putString(alphaTagPrefKey, alphaTag);
2719 }
2720
Jeff Sharkey85190e62014-12-05 09:40:12 -08002721 // Record both the line number and IMSI for this ICCID, since we need to
2722 // track all merged IMSIs based on line number
2723 final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2724 final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002725 if (number == null) {
2726 editor.remove(numberPrefKey);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002727 editor.remove(subscriberPrefKey);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002728 } else {
2729 editor.putString(numberPrefKey, number);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002730 editor.putString(subscriberPrefKey, subscriberId);
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002731 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08002732
Shishir Agrawal495d7e12014-12-01 11:50:28 -08002733 editor.commit();
2734 return true;
Derek Tan7226c842014-07-02 17:42:23 -07002735 }
2736
2737 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002738 public String getLine1NumberForDisplay(int subId, String callingPackage) {
Makoto Onukifee69342015-06-29 14:44:50 -07002739 // This is open to apps with WRITE_SMS.
2740 if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
Amit Mahajan9cf11512015-11-09 11:40:48 -08002741 if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
Svet Ganovb320e182015-04-16 12:30:10 -07002742 return null;
2743 }
Derek Tan97ebb422014-09-05 16:55:38 -07002744
2745 String iccId = getIccId(subId);
2746 if (iccId != null) {
2747 String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
Amit Mahajan9cf11512015-11-09 11:40:48 -08002748 if (DBG_MERGE) {
2749 log("getLine1NumberForDisplay returning " +
2750 mTelephonySharedPreferences.getString(numberPrefKey, null));
2751 }
Andrew Leedf14ead2014-10-17 14:22:52 -07002752 return mTelephonySharedPreferences.getString(numberPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002753 }
Amit Mahajan9cf11512015-11-09 11:40:48 -08002754 if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
Derek Tan97ebb422014-09-05 16:55:38 -07002755 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002756 }
2757
2758 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002759 public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2760 if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2761 return null;
2762 }
Derek Tan97ebb422014-09-05 16:55:38 -07002763
2764 String iccId = getIccId(subId);
2765 if (iccId != null) {
2766 String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
Andrew Leedf14ead2014-10-17 14:22:52 -07002767 return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
Derek Tan7226c842014-07-02 17:42:23 -07002768 }
Derek Tan97ebb422014-09-05 16:55:38 -07002769 return null;
Derek Tan7226c842014-07-02 17:42:23 -07002770 }
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002771
2772 @Override
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07002773 public String[] getMergedSubscriberIds(String callingPackage) {
2774 if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
2775 return null;
2776 }
Jeff Sharkey85190e62014-12-05 09:40:12 -08002777 final Context context = mPhone.getContext();
2778 final TelephonyManager tele = TelephonyManager.from(context);
2779 final SubscriptionManager sub = SubscriptionManager.from(context);
2780
2781 // Figure out what subscribers are currently active
2782 final ArraySet<String> activeSubscriberIds = new ArraySet<>();
Fyodor Kupolov8e53b0b2015-06-17 13:17:50 -07002783 // Clear calling identity, when calling TelephonyManager, because callerUid must be
2784 // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail.
2785 final long identity = Binder.clearCallingIdentity();
2786 try {
2787 final int[] subIds = sub.getActiveSubscriptionIdList();
2788 for (int subId : subIds) {
2789 activeSubscriberIds.add(tele.getSubscriberId(subId));
2790 }
2791 } finally {
2792 Binder.restoreCallingIdentity(identity);
Jeff Sharkey85190e62014-12-05 09:40:12 -08002793 }
2794
2795 // First pass, find a number override for an active subscriber
2796 String mergeNumber = null;
2797 final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
2798 for (String key : prefs.keySet()) {
2799 if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
2800 final String subscriberId = (String) prefs.get(key);
2801 if (activeSubscriberIds.contains(subscriberId)) {
2802 final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
2803 final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2804 mergeNumber = (String) prefs.get(numberKey);
2805 if (DBG_MERGE) {
2806 Slog.d(LOG_TAG, "Found line number " + mergeNumber
2807 + " for active subscriber " + subscriberId);
2808 }
2809 if (!TextUtils.isEmpty(mergeNumber)) {
2810 break;
2811 }
2812 }
2813 }
2814 }
2815
2816 // Shortcut when no active merged subscribers
2817 if (TextUtils.isEmpty(mergeNumber)) {
2818 return null;
2819 }
2820
2821 // Second pass, find all subscribers under that line override
2822 final ArraySet<String> result = new ArraySet<>();
2823 for (String key : prefs.keySet()) {
2824 if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
2825 final String number = (String) prefs.get(key);
2826 if (mergeNumber.equals(number)) {
2827 final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
2828 final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2829 final String subscriberId = (String) prefs.get(subscriberKey);
2830 if (!TextUtils.isEmpty(subscriberId)) {
2831 result.add(subscriberId);
2832 }
2833 }
2834 }
2835 }
2836
2837 final String[] resultArray = result.toArray(new String[result.size()]);
2838 Arrays.sort(resultArray);
2839 if (DBG_MERGE) {
2840 Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
2841 }
2842 return resultArray;
2843 }
2844
2845 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002846 public boolean setOperatorBrandOverride(int subId, String brand) {
2847 enforceCarrierPrivilege(subId);
2848 final Phone phone = getPhone(subId);
2849 return phone == null ? false : phone.setOperatorBrandOverride(brand);
Shishir Agrawalb1ebf8c2014-07-17 16:32:41 -07002850 }
Steven Liu4bf01bc2014-07-17 11:05:29 -05002851
2852 @Override
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002853 public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08002854 List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2855 List<String> cdmaNonRoamingList) {
Shishir Agrawalc04d9752016-02-19 10:41:00 -08002856 enforceCarrierPrivilege(subId);
2857 final Phone phone = getPhone(subId);
2858 if (phone == null) {
2859 return false;
2860 }
2861 return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
Shishir Agrawal621a47c2014-12-01 10:25:09 -08002862 cdmaNonRoamingList);
2863 }
2864
2865 @Override
Steven Liu4bf01bc2014-07-17 11:05:29 -05002866 public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2867 enforceModifyPermission();
2868
2869 int returnValue = 0;
2870 try {
2871 AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2872 if(result.exception == null) {
2873 if (result.result != null) {
2874 byte[] responseData = (byte[])(result.result);
2875 if(responseData.length > oemResp.length) {
2876 Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2877 responseData.length + "bytes. Buffer Size is " +
2878 oemResp.length + "bytes.");
2879 }
2880 System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2881 returnValue = responseData.length;
2882 }
2883 } else {
2884 CommandException ex = (CommandException) result.exception;
2885 returnValue = ex.getCommandError().ordinal();
2886 if(returnValue > 0) returnValue *= -1;
2887 }
2888 } catch (RuntimeException e) {
2889 Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2890 returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2891 if(returnValue > 0) returnValue *= -1;
2892 }
2893
2894 return returnValue;
2895 }
Wink Saville5d475dd2014-10-17 15:00:58 -07002896
2897 @Override
2898 public void setRadioCapability(RadioAccessFamily[] rafs) {
2899 try {
2900 ProxyController.getInstance().setRadioCapability(rafs);
2901 } catch (RuntimeException e) {
2902 Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
2903 }
2904 }
2905
2906 @Override
Robert Greenwalt36b23af2015-07-06 17:59:14 -07002907 public int getRadioAccessFamily(int phoneId, String callingPackage) {
2908 if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
2909 return RadioAccessFamily.RAF_UNKNOWN;
2910 }
2911
Wink Saville5d475dd2014-10-17 15:00:58 -07002912 return ProxyController.getInstance().getRadioAccessFamily(phoneId);
2913 }
Andrew Leedf14ead2014-10-17 14:22:52 -07002914
2915 @Override
2916 public void enableVideoCalling(boolean enable) {
2917 enforceModifyPermission();
Tyler Gunnfdd69de2015-12-04 21:24:38 -08002918 ImsManager.setVtSetting(mPhone.getContext(), enable);
Andrew Leedf14ead2014-10-17 14:22:52 -07002919 }
2920
2921 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002922 public boolean isVideoCallingEnabled(String callingPackage) {
2923 if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
2924 return false;
2925 }
2926
Andrew Lee77527ac2014-10-21 16:57:39 -07002927 // Check the user preference and the system-level IMS setting. Even if the user has
2928 // enabled video calling, if IMS is disabled we aren't able to support video calling.
2929 // In the long run, we may instead need to check if there exists a connection service
2930 // which can support video calling.
Andrew Lee312e8172014-10-23 17:01:36 -07002931 return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
2932 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
Tyler Gunnfdd69de2015-12-04 21:24:38 -08002933 && ImsManager.isVtEnabledByUser(mPhone.getContext());
Andrew Leedf14ead2014-10-17 14:22:52 -07002934 }
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06002935
Andrew Leea1239f22015-03-02 17:44:07 -08002936 @Override
2937 public boolean canChangeDtmfToneLength() {
Jonathan Basseri9504c6b2015-06-04 14:23:32 -07002938 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
Andrew Leea1239f22015-03-02 17:44:07 -08002939 }
2940
2941 @Override
2942 public boolean isWorldPhone() {
Jonathan Basseri9504c6b2015-06-04 14:23:32 -07002943 return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
Andrew Leea1239f22015-03-02 17:44:07 -08002944 }
2945
Andrew Lee9431b832015-03-09 18:46:45 -07002946 @Override
2947 public boolean isTtyModeSupported() {
2948 TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
2949 TelephonyManager telephonyManager =
2950 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
Wooki Wu1f82f7a2016-02-15 15:59:58 +08002951 return telecomManager.isTtySupported();
Andrew Lee9431b832015-03-09 18:46:45 -07002952 }
2953
2954 @Override
2955 public boolean isHearingAidCompatibilitySupported() {
2956 return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
2957 }
2958
Sanket Padawe7310cc72015-01-14 09:53:20 -08002959 /**
2960 * Returns the unique device ID of phone, for example, the IMEI for
2961 * GSM and the MEID for CDMA phones. Return null if device ID is not available.
2962 *
2963 * <p>Requires Permission:
2964 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
2965 */
2966 @Override
Svet Ganovb320e182015-04-16 12:30:10 -07002967 public String getDeviceId(String callingPackage) {
2968 if (!canReadPhoneState(callingPackage, "getDeviceId")) {
2969 return null;
2970 }
2971
Sanket Padawe7310cc72015-01-14 09:53:20 -08002972 final Phone phone = PhoneFactory.getPhone(0);
2973 if (phone != null) {
2974 return phone.getDeviceId();
2975 } else {
2976 return null;
2977 }
2978 }
2979
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06002980 /*
2981 * {@hide}
2982 * Returns the IMS Registration Status
2983 */
Santos Cordon7a1885b2015-02-03 11:15:19 -08002984 @Override
Libin.Tang@motorola.comafe82642014-12-18 13:27:53 -06002985 public boolean isImsRegistered() {
2986 return mPhone.isImsRegistered();
2987 }
Santos Cordon7a1885b2015-02-03 11:15:19 -08002988
2989 @Override
2990 public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
2991 return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
2992 }
Nathan Harolddcfc7932015-03-18 10:01:20 -07002993
Nathan Haroldc55097a2015-03-11 18:14:50 -07002994 /*
2995 * {@hide}
2996 * Returns the IMS Registration Status
2997 */
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07002998 public boolean isWifiCallingAvailable() {
Nathan Haroldc55097a2015-03-11 18:14:50 -07002999 return mPhone.isWifiCallingEnabled();
3000 }
3001
3002 /*
3003 * {@hide}
3004 * Returns the IMS Registration Status
3005 */
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003006 public boolean isVolteAvailable() {
Nathan Haroldc55097a2015-03-11 18:14:50 -07003007 return mPhone.isVolteEnabled();
3008 }
Svet Ganovb320e182015-04-16 12:30:10 -07003009
Etan Cohen3b7a1bc2015-05-28 15:57:13 -07003010 /*
3011 * {@hide} Returns the IMS Registration Status
3012 */
3013 public boolean isVideoTelephonyAvailable() {
3014 return mPhone.isVideoEnabled();
3015 }
3016
Svet Ganovb320e182015-04-16 12:30:10 -07003017 private boolean canReadPhoneState(String callingPackage, String message) {
Etan Cohen921655c2015-06-24 13:54:50 -07003018 try {
Amit Mahajan83ea23b2015-07-30 16:05:11 -07003019 mApp.enforceCallingOrSelfPermission(
Etan Cohen921655c2015-06-24 13:54:50 -07003020 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
3021
Amit Mahajan83ea23b2015-07-30 16:05:11 -07003022 // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
Etan Cohen921655c2015-06-24 13:54:50 -07003023 return true;
Amit Mahajan785783f2015-06-29 10:36:50 -07003024 } catch (SecurityException e) {
3025 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
3026 message);
Etan Cohen921655c2015-06-24 13:54:50 -07003027 }
Svet Ganovb320e182015-04-16 12:30:10 -07003028
3029 if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
3030 callingPackage) != AppOpsManager.MODE_ALLOWED) {
3031 return false;
3032 }
3033
3034 return true;
3035 }
Stuart Scott8eef64f2015-04-08 15:13:54 -07003036
Makoto Onukifee69342015-06-29 14:44:50 -07003037 /**
Amit Mahajanb9b49782015-09-15 18:16:32 -07003038 * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
Makoto Onukifee69342015-06-29 14:44:50 -07003039 */
3040 private boolean canReadPhoneNumber(String callingPackage, String message) {
Makoto Onukie4072d12015-08-03 15:12:23 -07003041 // Default SMS app can always read it.
3042 if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
3043 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
3044 return true;
3045 }
Chad Brubaker7a8fba22016-11-10 11:23:18 -08003046
Makoto Onukie4072d12015-08-03 15:12:23 -07003047 try {
3048 return canReadPhoneState(callingPackage, message);
Amit Mahajanb9b49782015-09-15 18:16:32 -07003049 } catch (SecurityException readPhoneStateSecurityException) {
Makoto Onukie4072d12015-08-03 15:12:23 -07003050 }
Chad Brubaker7a8fba22016-11-10 11:23:18 -08003051 // Can be read with READ_SMS too.
3052 try {
3053 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
3054 int opCode = mAppOps.permissionToOpCode(android.Manifest.permission.READ_SMS);
3055 if (opCode != AppOpsManager.OP_NONE) {
3056 return mAppOps.noteOp(opCode, Binder.getCallingUid(), callingPackage)
3057 == AppOpsManager.MODE_ALLOWED;
3058 } else {
3059 return true;
3060 }
3061 } catch (SecurityException readSmsSecurityException) {
3062 }
3063 // Can be read with READ_PHONE_NUMBER too.
3064 try {
3065 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_NUMBER,
3066 message);
3067 int opCode = mAppOps.permissionToOpCode(android.Manifest.permission.READ_PHONE_NUMBER);
3068 if (opCode != AppOpsManager.OP_NONE) {
3069 return mAppOps.noteOp(opCode, Binder.getCallingUid(), callingPackage)
3070 == AppOpsManager.MODE_ALLOWED;
3071 } else {
3072 return true;
3073 }
3074 } catch (SecurityException readPhoneNumberSecurityException) {
3075 }
3076
3077 throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
3078 " nor current process has" + android.Manifest.permission.READ_PHONE_STATE +
3079 ", " + android.Manifest.permission.READ_SMS + ", or " +
3080 android.Manifest.permission.READ_PHONE_NUMBER);
Makoto Onukifee69342015-06-29 14:44:50 -07003081 }
3082
Stuart Scott8eef64f2015-04-08 15:13:54 -07003083 @Override
3084 public void factoryReset(int subId) {
3085 enforceConnectivityInternalPermission();
Stuart Scott981d8582015-04-21 14:09:50 -07003086 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
3087 return;
3088 }
3089
Svet Ganovcc087f82015-05-12 20:35:54 -07003090 final long identity = Binder.clearCallingIdentity();
3091 try {
Stuart Scott981d8582015-04-21 14:09:50 -07003092 if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
3093 UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
Svet Ganovcc087f82015-05-12 20:35:54 -07003094 // Enable data
3095 setDataEnabled(subId, true);
3096 // Set network selection mode to automatic
3097 setNetworkSelectionModeAutomatic(subId);
3098 // Set preferred mobile network type to the best available
3099 setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
3100 // Turn off roaming
3101 SubscriptionManager.from(mApp).setDataRoaming(0, subId);
3102 }
3103 } finally {
3104 Binder.restoreCallingIdentity(identity);
Stuart Scott8eef64f2015-04-08 15:13:54 -07003105 }
3106 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01003107
3108 @Override
3109 public String getLocaleFromDefaultSim() {
3110 // We query all subscriptions instead of just the active ones, because
3111 // this might be called early on in the provisioning flow when the
3112 // subscriptions potentially aren't active yet.
3113 final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
3114 if (slist == null || slist.isEmpty()) {
3115 return null;
3116 }
3117
3118 // This function may be called very early, say, from the setup wizard, at
3119 // which point we won't have a default subscription set. If that's the case
3120 // we just choose the first, which will be valid in "most cases".
3121 final int defaultSubId = getDefaultSubscription();
3122 SubscriptionInfo info = null;
3123 if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
3124 info = slist.get(0);
3125 } else {
3126 for (SubscriptionInfo item : slist) {
3127 if (item.getSubscriptionId() == defaultSubId) {
3128 info = item;
3129 break;
3130 }
3131 }
3132
3133 if (info == null) {
3134 return null;
3135 }
3136 }
3137
3138 // Try and fetch the locale from the carrier properties or from the SIM language
3139 // preferences (EF-PL and EF-LI)...
Tony Hill183b2de2015-06-24 14:53:58 +01003140 final int mcc = info.getMcc();
Narayan Kamath1c496c22015-04-16 14:40:19 +01003141 final Phone defaultPhone = getPhone(info.getSubscriptionId());
Narayan Kamath011676f2015-07-29 12:04:08 +01003142 String simLanguage = null;
Narayan Kamath1c496c22015-04-16 14:40:19 +01003143 if (defaultPhone != null) {
3144 final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
3145 if (localeFromDefaultSim != null) {
Narayan Kamath011676f2015-07-29 12:04:08 +01003146 if (!localeFromDefaultSim.getCountry().isEmpty()) {
Tony Hill183b2de2015-06-24 14:53:58 +01003147 if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim);
3148 return localeFromDefaultSim.toLanguageTag();
Narayan Kamath011676f2015-07-29 12:04:08 +01003149 } else {
3150 simLanguage = localeFromDefaultSim.getLanguage();
Tony Hill183b2de2015-06-24 14:53:58 +01003151 }
Narayan Kamath1c496c22015-04-16 14:40:19 +01003152 }
3153 }
3154
Narayan Kamath011676f2015-07-29 12:04:08 +01003155 // The SIM language preferences only store a language (e.g. fr = French), not an
3156 // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
3157 // the SIM and carrier preferences does not include a country we add the country
3158 // determined from the SIM MCC to provide an exact locale.
3159 final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage);
Tony Hill183b2de2015-06-24 14:53:58 +01003160 if (mccLocale != null) {
3161 if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale);
3162 return mccLocale.toLanguageTag();
Narayan Kamath1c496c22015-04-16 14:40:19 +01003163 }
3164
Tony Hill183b2de2015-06-24 14:53:58 +01003165 if (DBG) log("No locale found - returning null");
Narayan Kamath1c496c22015-04-16 14:40:19 +01003166 return null;
3167 }
3168
3169 private List<SubscriptionInfo> getAllSubscriptionInfoList() {
3170 final long identity = Binder.clearCallingIdentity();
3171 try {
3172 return mSubscriptionController.getAllSubInfoList(
3173 mPhone.getContext().getOpPackageName());
3174 } finally {
3175 Binder.restoreCallingIdentity(identity);
3176 }
3177 }
3178
3179 private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
3180 final long identity = Binder.clearCallingIdentity();
3181 try {
3182 return mSubscriptionController.getActiveSubscriptionInfoList(
3183 mPhone.getContext().getOpPackageName());
3184 } finally {
3185 Binder.restoreCallingIdentity(identity);
3186 }
3187 }
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003188
3189 /**
Adam Lesinski903a54c2016-04-11 14:49:52 -07003190 * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
3191 * representing the state of the modem.
3192 *
3193 * NOTE: This clears the modem state, so there should only every be one caller.
3194 * @hide
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003195 */
3196 @Override
Adam Lesinski903a54c2016-04-11 14:49:52 -07003197 public void requestModemActivityInfo(ResultReceiver result) {
3198 enforceModifyPermission();
3199
3200 ModemActivityInfo info = (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
3201 Bundle bundle = new Bundle();
3202 bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, info);
3203 result.send(0, bundle);
Prerepa Viswanadham7fcff692015-06-03 11:20:55 -07003204 }
Jack Yu85bd38a2015-11-09 11:34:32 -08003205
3206 /**
3207 * {@hide}
3208 * Returns the service state information on specified subscription.
3209 */
3210 @Override
3211 public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
3212
3213 if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
3214 return null;
3215 }
3216
3217 final Phone phone = getPhone(subId);
3218 if (phone == null) {
3219 return null;
3220 }
3221
3222 return phone.getServiceState();
3223 }
Nancy Chen31f9ba12016-01-06 11:42:12 -08003224
3225 /**
3226 * Returns the URI for the per-account voicemail ringtone set in Phone settings.
3227 *
3228 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3229 * voicemail ringtone.
3230 * @return The URI for the ringtone to play when receiving a voicemail from a specific
3231 * PhoneAccount.
3232 */
3233 @Override
3234 public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
3235 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3236 if (phone == null) {
3237 return null;
3238 }
3239
3240 return VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
3241 }
3242
3243 /**
3244 * Returns whether vibration is set for voicemail notification in Phone settings.
3245 *
3246 * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3247 * voicemail vibration setting.
3248 * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
3249 */
3250 @Override
3251 public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
3252 final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3253 if (phone == null) {
3254 return false;
3255 }
3256
3257 return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone);
3258 }
3259
Youhan Wange64578a2016-05-02 15:32:42 -07003260 /**
3261 * Make sure either called from same process as self (phone) or IPC caller has read privilege.
3262 *
3263 * @throws SecurityException if the caller does not have the required permission
3264 */
3265 private void enforceReadPrivilegedPermission() {
3266 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3267 null);
3268 }
3269
3270 /**
Ta-wei Yen30a69c82016-12-27 14:52:32 -08003271 * Make sure either called from same process as self (phone) or IPC caller has send SMS
3272 * permission.
3273 *
3274 * @throws SecurityException if the caller does not have the required permission
3275 */
3276 private void enforceSendSmsPermission() {
3277 mApp.enforceCallingOrSelfPermission(permission.SEND_SMS, null);
3278 }
3279
3280 /**
3281 * Make sure called from the default dialer
3282 *
3283 * @throws SecurityException if the caller is not the default dialer
3284 */
3285 private void enforceDefaultDialer(String callingPackage) {
3286 TelecomManager telecomManager = mPhone.getContext().getSystemService(TelecomManager.class);
3287 if (!callingPackage.equals(telecomManager.getDefaultDialerPackage())) {
3288 throw new SecurityException("Caller not default dialer.");
3289 }
3290 }
3291
3292 /**
Youhan Wange64578a2016-05-02 15:32:42 -07003293 * Return the application ID for the app type.
3294 *
3295 * @param subId the subscription ID that this request applies to.
3296 * @param appType the uicc app type.
3297 * @return Application ID for specificied app type, or null if no uicc.
3298 */
3299 @Override
3300 public String getAidForAppType(int subId, int appType) {
3301 enforceReadPrivilegedPermission();
3302 Phone phone = getPhone(subId);
3303 if (phone == null) {
3304 return null;
3305 }
3306 String aid = null;
3307 try {
3308 aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
3309 .getApplicationByType(appType).getAid();
3310 } catch (Exception e) {
3311 Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
3312 }
3313 return aid;
3314 }
3315
Youhan Wang4001d252016-05-11 10:29:41 -07003316 /**
3317 * Return the Electronic Serial Number.
3318 *
3319 * @param subId the subscription ID that this request applies to.
3320 * @return ESN or null if error.
3321 */
3322 @Override
3323 public String getEsn(int subId) {
3324 enforceReadPrivilegedPermission();
3325 Phone phone = getPhone(subId);
3326 if (phone == null) {
3327 return null;
3328 }
3329 String esn = null;
3330 try {
3331 esn = phone.getEsn();
3332 } catch (Exception e) {
3333 Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
3334 }
3335 return esn;
3336 }
3337
Sanket Padawe99ef1e32016-05-18 16:12:33 -07003338 /**
Youhan Wang66ad5d72016-07-18 17:56:58 -07003339 * Return the Preferred Roaming List Version.
3340 *
3341 * @param subId the subscription ID that this request applies to.
3342 * @return PRLVersion or null if error.
3343 */
3344 @Override
3345 public String getCdmaPrlVersion(int subId) {
3346 enforceReadPrivilegedPermission();
3347 Phone phone = getPhone(subId);
3348 if (phone == null) {
3349 return null;
3350 }
3351 String cdmaPrlVersion = null;
3352 try {
3353 cdmaPrlVersion = phone.getCdmaPrlVersion();
3354 } catch (Exception e) {
3355 Log.e(LOG_TAG, "Not getting PRLVersion", e);
3356 }
3357 return cdmaPrlVersion;
3358 }
3359
3360 /**
Sanket Padawe99ef1e32016-05-18 16:12:33 -07003361 * Get snapshot of Telephony histograms
3362 * @return List of Telephony histograms
3363 * @hide
3364 */
3365 @Override
3366 public List<TelephonyHistogram> getTelephonyHistograms() {
3367 enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
3368 return RIL.getTelephonyRILTimingHistograms();
3369 }
Meng Wang1a7c35a2016-05-05 20:56:15 -07003370
3371 /**
3372 * {@hide}
3373 * Set the allowed carrier list for slotId
3374 * Require system privileges. In the future we may add this to carrier APIs.
3375 *
3376 * @return The number of carriers set successfully, should match length of carriers
3377 */
3378 @Override
3379 public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
3380 enforceModifyPermission();
3381 int subId = SubscriptionManager.getSubId(slotId)[0];
3382 int[] retVal = (int[]) sendRequest(CMD_SET_ALLOWED_CARRIERS, carriers, subId);
3383 return retVal[0];
3384 }
3385
3386 /**
3387 * {@hide}
3388 * Get the allowed carrier list for slotId.
3389 * Require system privileges. In the future we may add this to carrier APIs.
3390 *
3391 * @return List of {@link android.service.telephony.CarrierIdentifier}; empty list
3392 * means all carriers are allowed.
3393 */
3394 @Override
3395 public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
3396 enforceReadPrivilegedPermission();
3397 int subId = SubscriptionManager.getSubId(slotId)[0];
3398 return (List<CarrierIdentifier>) sendRequest(CMD_GET_ALLOWED_CARRIERS, null, subId);
3399 }
3400
fionaxu59545b42016-05-25 15:53:37 -07003401 /**
3402 * Action set from carrier signalling broadcast receivers to enable/disable metered apns
3403 * @param subId the subscription ID that this action applies to.
3404 * @param enabled control enable or disable metered apns.
3405 * {@hide}
3406 */
3407 @Override
3408 public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
3409 enforceModifyPermission();
3410 final Phone phone = getPhone(subId);
3411 if (phone == null) {
3412 loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
3413 return;
3414 }
3415 try {
3416 phone.carrierActionSetMeteredApnsEnabled(enabled);
3417 } catch (Exception e) {
3418 Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
3419 }
3420 }
3421
3422 /**
3423 * Action set from carrier signalling broadcast receivers to enable/disable radio
3424 * @param subId the subscription ID that this action applies to.
3425 * @param enabled control enable or disable radio.
3426 * {@hide}
3427 */
3428 @Override
3429 public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
3430 enforceModifyPermission();
3431 final Phone phone = getPhone(subId);
3432 if (phone == null) {
3433 loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
3434 return;
3435 }
3436 try {
3437 phone.carrierActionSetRadioEnabled(enabled);
3438 } catch (Exception e) {
3439 Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
3440 }
3441 }
3442
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07003443 /**
3444 * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
3445 * bug report is being generated.
3446 */
3447 @Override
Ta-wei Yen99282e02016-06-21 18:19:35 -07003448 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
dcashman22b950d2016-06-27 11:39:02 -07003449 if (mPhone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
3450 != PackageManager.PERMISSION_GRANTED) {
3451 writer.println("Permission Denial: can't dump Phone from pid="
3452 + Binder.getCallingPid()
3453 + ", uid=" + Binder.getCallingUid()
3454 + "without permission "
3455 + android.Manifest.permission.DUMP);
3456 return;
3457 }
Ta-wei Yen99282e02016-06-21 18:19:35 -07003458 DumpsysHandler.dump(mPhone.getContext(), fd, writer, args);
Ta-wei Yenc236d6b2016-06-21 13:33:12 -07003459 }
Jack Yueb89b242016-06-22 13:27:47 -07003460
3461 /**
3462 * Get aggregated video call data usage from all subscriptions since boot.
3463 * @return total data usage in bytes
3464 * {@hide}
3465 */
3466 @Override
3467 public long getVtDataUsage() {
3468 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
3469 null);
3470
3471 // NetworkStatsService keeps tracking the active network interface and identity. It will
3472 // record the delta with the corresponding network identity. What we need to do here is
3473 // returning total video call data usage from all subscriptions since boot.
3474
3475 // TODO: Add sub id support in the future. We'll need it when we support DSDA and
3476 // simultaneous VT calls.
3477 final Phone[] phones = PhoneFactory.getPhones();
3478 long total = 0;
3479 for (Phone phone : phones) {
3480 total += phone.getVtDataUsage();
3481 }
3482 return total;
3483 }
Jack Yu75ab2952016-07-08 14:29:33 -07003484
3485 /**
3486 * Policy control of data connection. Usually used when data limit is passed.
3487 * @param enabled True if enabling the data, otherwise disabling.
3488 * @param subId Subscription index
3489 * {@hide}
3490 */
3491 @Override
3492 public void setPolicyDataEnabled(boolean enabled, int subId) {
3493 enforceModifyPermission();
3494 Phone phone = getPhone(subId);
3495 if (phone != null) {
3496 phone.setPolicyDataEnabled(enabled);
3497 }
3498 }
Sooraj Sasindran9a909312016-07-18 11:57:25 -07003499
3500 /**
3501 * Get Client request stats
3502 * @return List of Client Request Stats
3503 * @hide
3504 */
3505 @Override
3506 public List<ClientRequestStats> getClientRequestStats(String callingPackage, int subId) {
3507 if (!canReadPhoneState(callingPackage, "getClientRequestStats")) {
3508 return null;
3509 }
3510
3511 Phone phone = getPhone(subId);
3512 if (phone != null) {
3513 return phone.getClientRequestStats();
3514 }
3515
3516 return null;
3517 }
3518
3519 private WorkSource getWorkSource(WorkSource workSource, int uid) {
3520 if (workSource != null) {
3521 return workSource;
3522 }
3523
3524 String packageName = mPhone.getContext().getPackageManager().getNameForUid(uid);
3525 workSource = new WorkSource(uid, packageName);
3526 return workSource;
3527 }
Santos Cordon7d4ddf62013-07-10 11:58:08 -07003528}