1 /*
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 
17 package com.android.phone;
18 
19 import android.app.ActivityManager;
20 import android.app.AppOpsManager;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.SharedPreferences;
25 import android.content.pm.PackageInfo;
26 import android.content.pm.PackageManager;
27 import android.net.Uri;
28 import android.os.AsyncResult;
29 import android.os.Binder;
30 import android.os.Bundle;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.os.Message;
34 import android.os.Process;
35 import android.os.ResultReceiver;
36 import android.os.ServiceManager;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.preference.PreferenceManager;
40 import android.provider.Settings;
41 import android.telecom.PhoneAccount;
42 import android.telecom.PhoneAccountHandle;
43 import android.telecom.TelecomManager;
44 import android.telephony.CarrierConfigManager;
45 import android.telephony.CellInfo;
46 import android.telephony.IccOpenLogicalChannelResponse;
47 import android.telephony.NeighboringCellInfo;
48 import android.telephony.RadioAccessFamily;
49 import android.telephony.ServiceState;
50 import android.telephony.SubscriptionInfo;
51 import android.telephony.SubscriptionManager;
52 import android.telephony.TelephonyManager;
53 import android.telephony.ModemActivityInfo;
54 import android.text.TextUtils;
55 import android.util.ArraySet;
56 import android.util.Log;
57 import android.util.Pair;
58 import android.util.Slog;
59 
60 import com.android.ims.ImsManager;
61 import com.android.internal.telephony.CallManager;
62 import com.android.internal.telephony.CellNetworkScanResult;
63 import com.android.internal.telephony.CommandException;
64 import com.android.internal.telephony.DefaultPhoneNotifier;
65 import com.android.internal.telephony.ITelephony;
66 import com.android.internal.telephony.IccCard;
67 import com.android.internal.telephony.MccTable;
68 import com.android.internal.telephony.OperatorInfo;
69 import com.android.internal.telephony.Phone;
70 import com.android.internal.telephony.PhoneFactory;
71 import com.android.internal.telephony.ProxyController;
72 import com.android.internal.telephony.PhoneConstants;
73 import com.android.internal.telephony.RILConstants;
74 import com.android.internal.telephony.SubscriptionController;
75 import com.android.internal.telephony.uicc.IccIoResult;
76 import com.android.internal.telephony.uicc.IccUtils;
77 import com.android.internal.telephony.uicc.UiccCard;
78 import com.android.internal.telephony.uicc.UiccController;
79 import com.android.internal.util.HexDump;
80 import com.android.phone.settings.VoicemailNotificationSettingsUtil;
81 
82 import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
83 
84 import java.util.ArrayList;
85 import java.util.Arrays;
86 import java.util.List;
87 import java.util.Locale;
88 import java.util.Map;
89 
90 /**
91  * Implementation of the ITelephony interface.
92  */
93 public class PhoneInterfaceManager extends ITelephony.Stub {
94     private static final String LOG_TAG = "PhoneInterfaceManager";
95     private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
96     private static final boolean DBG_LOC = false;
97     private static final boolean DBG_MERGE = false;
98 
99     // Message codes used with mMainThreadHandler
100     private static final int CMD_HANDLE_PIN_MMI = 1;
101     private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
102     private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
103     private static final int CMD_ANSWER_RINGING_CALL = 4;
104     private static final int CMD_END_CALL = 5;  // not used yet
105     private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
106     private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
107     private static final int CMD_OPEN_CHANNEL = 9;
108     private static final int EVENT_OPEN_CHANNEL_DONE = 10;
109     private static final int CMD_CLOSE_CHANNEL = 11;
110     private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
111     private static final int CMD_NV_READ_ITEM = 13;
112     private static final int EVENT_NV_READ_ITEM_DONE = 14;
113     private static final int CMD_NV_WRITE_ITEM = 15;
114     private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
115     private static final int CMD_NV_WRITE_CDMA_PRL = 17;
116     private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
117     private static final int CMD_NV_RESET_CONFIG = 19;
118     private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
119     private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
120     private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
121     private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
122     private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
123     private static final int CMD_SEND_ENVELOPE = 25;
124     private static final int EVENT_SEND_ENVELOPE_DONE = 26;
125     private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
126     private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
127     private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
128     private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
129     private static final int CMD_EXCHANGE_SIM_IO = 31;
130     private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
131     private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
132     private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
133     private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
134     private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
135     private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
136     private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
137     private static final int CMD_PERFORM_NETWORK_SCAN = 39;
138     private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
139     private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
140     private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
141 
142     /** The singleton instance. */
143     private static PhoneInterfaceManager sInstance;
144 
145     private PhoneGlobals mApp;
146     private Phone mPhone;
147     private CallManager mCM;
148     private UserManager mUserManager;
149     private AppOpsManager mAppOps;
150     private MainThreadHandler mMainThreadHandler;
151     private SubscriptionController mSubscriptionController;
152     private SharedPreferences mTelephonySharedPreferences;
153 
154     private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
155     private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
156     private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
157 
158     /**
159      * A request object to use for transmitting data to an ICC.
160      */
161     private static final class IccAPDUArgument {
162         public int channel, cla, command, p1, p2, p3;
163         public String data;
164 
IccAPDUArgument(int channel, int cla, int command, int p1, int p2, int p3, String data)165         public IccAPDUArgument(int channel, int cla, int command,
166                 int p1, int p2, int p3, String data) {
167             this.channel = channel;
168             this.cla = cla;
169             this.command = command;
170             this.p1 = p1;
171             this.p2 = p2;
172             this.p3 = p3;
173             this.data = data;
174         }
175     }
176 
177     /**
178      * A request object to use for transmitting data to an ICC.
179      */
180     private static final class ManualNetworkSelectionArgument {
181         public OperatorInfo operatorInfo;
182         public boolean persistSelection;
183 
ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection)184         public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
185             this.operatorInfo = operatorInfo;
186             this.persistSelection = persistSelection;
187         }
188     }
189 
190     /**
191      * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
192      * request after sending. The main thread will notify the request when it is complete.
193      */
194     private static final class MainThreadRequest {
195         /** The argument to use for the request */
196         public Object argument;
197         /** The result of the request that is run on the main thread */
198         public Object result;
199         // The subscriber id that this request applies to. Defaults to
200         // SubscriptionManager.INVALID_SUBSCRIPTION_ID
201         public Integer subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
202 
MainThreadRequest(Object argument)203         public MainThreadRequest(Object argument) {
204             this.argument = argument;
205         }
206 
MainThreadRequest(Object argument, Integer subId)207         public MainThreadRequest(Object argument, Integer subId) {
208             this.argument = argument;
209             if (subId != null) {
210                 this.subId = subId;
211             }
212         }
213     }
214 
215     private static final class IncomingThirdPartyCallArgs {
216         public final ComponentName component;
217         public final String callId;
218         public final String callerDisplayName;
219 
IncomingThirdPartyCallArgs(ComponentName component, String callId, String callerDisplayName)220         public IncomingThirdPartyCallArgs(ComponentName component, String callId,
221                 String callerDisplayName) {
222             this.component = component;
223             this.callId = callId;
224             this.callerDisplayName = callerDisplayName;
225         }
226     }
227 
228     /**
229      * A handler that processes messages on the main thread in the phone process. Since many
230      * of the Phone calls are not thread safe this is needed to shuttle the requests from the
231      * inbound binder threads to the main thread in the phone process.  The Binder thread
232      * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
233      * on, which will be notified when the operation completes and will contain the result of the
234      * request.
235      *
236      * <p>If a MainThreadRequest object is provided in the msg.obj field,
237      * note that request.result must be set to something non-null for the calling thread to
238      * unblock.
239      */
240     private final class MainThreadHandler extends Handler {
241         @Override
handleMessage(Message msg)242         public void handleMessage(Message msg) {
243             MainThreadRequest request;
244             Message onCompleted;
245             AsyncResult ar;
246             UiccCard uiccCard;
247             IccAPDUArgument iccArgument;
248 
249             switch (msg.what) {
250                 case CMD_HANDLE_PIN_MMI: {
251                     request = (MainThreadRequest) msg.obj;
252                     final Phone phone = getPhoneFromRequest(request);
253                     request.result = phone != null ?
254                             getPhoneFromRequest(request).handlePinMmi((String) request.argument)
255                             : false;
256                     // Wake up the requesting thread
257                     synchronized (request) {
258                         request.notifyAll();
259                     }
260                     break;
261                 }
262 
263                 case CMD_HANDLE_NEIGHBORING_CELL:
264                     request = (MainThreadRequest) msg.obj;
265                     onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
266                             request);
267                     mPhone.getNeighboringCids(onCompleted);
268                     break;
269 
270                 case EVENT_NEIGHBORING_CELL_DONE:
271                     ar = (AsyncResult) msg.obj;
272                     request = (MainThreadRequest) ar.userObj;
273                     if (ar.exception == null && ar.result != null) {
274                         request.result = ar.result;
275                     } else {
276                         // create an empty list to notify the waiting thread
277                         request.result = new ArrayList<NeighboringCellInfo>(0);
278                     }
279                     // Wake up the requesting thread
280                     synchronized (request) {
281                         request.notifyAll();
282                     }
283                     break;
284 
285                 case CMD_ANSWER_RINGING_CALL:
286                     request = (MainThreadRequest) msg.obj;
287                     int answer_subId = request.subId;
288                     answerRingingCallInternal(answer_subId);
289                     break;
290 
291                 case CMD_END_CALL:
292                     request = (MainThreadRequest) msg.obj;
293                     int end_subId = request.subId;
294                     final boolean hungUp;
295                     Phone phone = getPhone(end_subId);
296                     if (phone == null) {
297                         if (DBG) log("CMD_END_CALL: no phone for id: " + end_subId);
298                         break;
299                     }
300                     int phoneType = phone.getPhoneType();
301                     if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
302                         // CDMA: If the user presses the Power button we treat it as
303                         // ending the complete call session
304                         hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
305                     } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
306                         // GSM: End the call as per the Phone state
307                         hungUp = PhoneUtils.hangup(mCM);
308                     } else {
309                         throw new IllegalStateException("Unexpected phone type: " + phoneType);
310                     }
311                     if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
312                     request.result = hungUp;
313                     // Wake up the requesting thread
314                     synchronized (request) {
315                         request.notifyAll();
316                     }
317                     break;
318 
319                 case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
320                     request = (MainThreadRequest) msg.obj;
321                     iccArgument = (IccAPDUArgument) request.argument;
322                     uiccCard = getUiccCardFromRequest(request);
323                     if (uiccCard == null) {
324                         loge("iccTransmitApduLogicalChannel: No UICC");
325                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
326                         synchronized (request) {
327                             request.notifyAll();
328                         }
329                     } else {
330                         onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
331                             request);
332                         uiccCard.iccTransmitApduLogicalChannel(
333                             iccArgument.channel, iccArgument.cla, iccArgument.command,
334                             iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
335                             onCompleted);
336                     }
337                     break;
338 
339                 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
340                     ar = (AsyncResult) msg.obj;
341                     request = (MainThreadRequest) ar.userObj;
342                     if (ar.exception == null && ar.result != null) {
343                         request.result = ar.result;
344                     } else {
345                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
346                         if (ar.result == null) {
347                             loge("iccTransmitApduLogicalChannel: Empty response");
348                         } else if (ar.exception instanceof CommandException) {
349                             loge("iccTransmitApduLogicalChannel: CommandException: " +
350                                     ar.exception);
351                         } else {
352                             loge("iccTransmitApduLogicalChannel: Unknown exception");
353                         }
354                     }
355                     synchronized (request) {
356                         request.notifyAll();
357                     }
358                     break;
359 
360                 case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
361                     request = (MainThreadRequest) msg.obj;
362                     iccArgument = (IccAPDUArgument) request.argument;
363                     uiccCard = getUiccCardFromRequest(request);
364                     if (uiccCard == null) {
365                         loge("iccTransmitApduBasicChannel: No UICC");
366                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
367                         synchronized (request) {
368                             request.notifyAll();
369                         }
370                     } else {
371                         onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
372                             request);
373                         uiccCard.iccTransmitApduBasicChannel(
374                             iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
375                             iccArgument.p3, iccArgument.data, onCompleted);
376                     }
377                     break;
378 
379                 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
380                     ar = (AsyncResult) msg.obj;
381                     request = (MainThreadRequest) ar.userObj;
382                     if (ar.exception == null && ar.result != null) {
383                         request.result = ar.result;
384                     } else {
385                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
386                         if (ar.result == null) {
387                             loge("iccTransmitApduBasicChannel: Empty response");
388                         } else if (ar.exception instanceof CommandException) {
389                             loge("iccTransmitApduBasicChannel: CommandException: " +
390                                     ar.exception);
391                         } else {
392                             loge("iccTransmitApduBasicChannel: Unknown exception");
393                         }
394                     }
395                     synchronized (request) {
396                         request.notifyAll();
397                     }
398                     break;
399 
400                 case CMD_EXCHANGE_SIM_IO:
401                     request = (MainThreadRequest) msg.obj;
402                     iccArgument = (IccAPDUArgument) request.argument;
403                     uiccCard = getUiccCardFromRequest(request);
404                     if (uiccCard == null) {
405                         loge("iccExchangeSimIO: No UICC");
406                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
407                         synchronized (request) {
408                             request.notifyAll();
409                         }
410                     } else {
411                         onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
412                                 request);
413                         uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
414                                 iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
415                                 iccArgument.data, onCompleted);
416                     }
417                     break;
418 
419                 case EVENT_EXCHANGE_SIM_IO_DONE:
420                     ar = (AsyncResult) msg.obj;
421                     request = (MainThreadRequest) ar.userObj;
422                     if (ar.exception == null && ar.result != null) {
423                         request.result = ar.result;
424                     } else {
425                         request.result = new IccIoResult(0x6f, 0, (byte[])null);
426                     }
427                     synchronized (request) {
428                         request.notifyAll();
429                     }
430                     break;
431 
432                 case CMD_SEND_ENVELOPE:
433                     request = (MainThreadRequest) msg.obj;
434                     uiccCard = getUiccCardFromRequest(request);
435                     if (uiccCard == null) {
436                         loge("sendEnvelopeWithStatus: No UICC");
437                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
438                         synchronized (request) {
439                             request.notifyAll();
440                         }
441                     } else {
442                         onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
443                         uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
444                     }
445                     break;
446 
447                 case EVENT_SEND_ENVELOPE_DONE:
448                     ar = (AsyncResult) msg.obj;
449                     request = (MainThreadRequest) ar.userObj;
450                     if (ar.exception == null && ar.result != null) {
451                         request.result = ar.result;
452                     } else {
453                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
454                         if (ar.result == null) {
455                             loge("sendEnvelopeWithStatus: Empty response");
456                         } else if (ar.exception instanceof CommandException) {
457                             loge("sendEnvelopeWithStatus: CommandException: " +
458                                     ar.exception);
459                         } else {
460                             loge("sendEnvelopeWithStatus: exception:" + ar.exception);
461                         }
462                     }
463                     synchronized (request) {
464                         request.notifyAll();
465                     }
466                     break;
467 
468                 case CMD_OPEN_CHANNEL:
469                     request = (MainThreadRequest) msg.obj;
470                     uiccCard = getUiccCardFromRequest(request);
471                     if (uiccCard == null) {
472                         loge("iccOpenLogicalChannel: No UICC");
473                         request.result = new IccOpenLogicalChannelResponse(-1,
474                             IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE, null);
475                         synchronized (request) {
476                             request.notifyAll();
477                         }
478                     } else {
479                         onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
480                         uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
481                     }
482                     break;
483 
484                 case EVENT_OPEN_CHANNEL_DONE:
485                     ar = (AsyncResult) msg.obj;
486                     request = (MainThreadRequest) ar.userObj;
487                     IccOpenLogicalChannelResponse openChannelResp;
488                     if (ar.exception == null && ar.result != null) {
489                         int[] result = (int[]) ar.result;
490                         int channelId = result[0];
491                         byte[] selectResponse = null;
492                         if (result.length > 1) {
493                             selectResponse = new byte[result.length - 1];
494                             for (int i = 1; i < result.length; ++i) {
495                                 selectResponse[i - 1] = (byte) result[i];
496                             }
497                         }
498                         openChannelResp = new IccOpenLogicalChannelResponse(channelId,
499                             IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
500                     } else {
501                         if (ar.result == null) {
502                             loge("iccOpenLogicalChannel: Empty response");
503                         }
504                         if (ar.exception != null) {
505                             loge("iccOpenLogicalChannel: Exception: " + ar.exception);
506                         }
507 
508                         int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
509                         if (ar.exception instanceof CommandException) {
510                             CommandException.Error error =
511                                 ((CommandException) (ar.exception)).getCommandError();
512                             if (error == CommandException.Error.MISSING_RESOURCE) {
513                                 errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
514                             } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
515                                 errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
516                             }
517                         }
518                         openChannelResp = new IccOpenLogicalChannelResponse(
519                             IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
520                     }
521                     request.result = openChannelResp;
522                     synchronized (request) {
523                         request.notifyAll();
524                     }
525                     break;
526 
527                 case CMD_CLOSE_CHANNEL:
528                     request = (MainThreadRequest) msg.obj;
529                     uiccCard = getUiccCardFromRequest(request);
530                     if (uiccCard == null) {
531                         loge("iccCloseLogicalChannel: No UICC");
532                         request.result = new IccIoResult(0x6F, 0, (byte[])null);
533                         synchronized (request) {
534                             request.notifyAll();
535                         }
536                     } else {
537                         onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
538                         uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
539                     }
540                     break;
541 
542                 case EVENT_CLOSE_CHANNEL_DONE:
543                     handleNullReturnEvent(msg, "iccCloseLogicalChannel");
544                     break;
545 
546                 case CMD_NV_READ_ITEM:
547                     request = (MainThreadRequest) msg.obj;
548                     onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
549                     mPhone.nvReadItem((Integer) request.argument, onCompleted);
550                     break;
551 
552                 case EVENT_NV_READ_ITEM_DONE:
553                     ar = (AsyncResult) msg.obj;
554                     request = (MainThreadRequest) ar.userObj;
555                     if (ar.exception == null && ar.result != null) {
556                         request.result = ar.result;     // String
557                     } else {
558                         request.result = "";
559                         if (ar.result == null) {
560                             loge("nvReadItem: Empty response");
561                         } else if (ar.exception instanceof CommandException) {
562                             loge("nvReadItem: CommandException: " +
563                                     ar.exception);
564                         } else {
565                             loge("nvReadItem: Unknown exception");
566                         }
567                     }
568                     synchronized (request) {
569                         request.notifyAll();
570                     }
571                     break;
572 
573                 case CMD_NV_WRITE_ITEM:
574                     request = (MainThreadRequest) msg.obj;
575                     onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
576                     Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
577                     mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
578                     break;
579 
580                 case EVENT_NV_WRITE_ITEM_DONE:
581                     handleNullReturnEvent(msg, "nvWriteItem");
582                     break;
583 
584                 case CMD_NV_WRITE_CDMA_PRL:
585                     request = (MainThreadRequest) msg.obj;
586                     onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
587                     mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
588                     break;
589 
590                 case EVENT_NV_WRITE_CDMA_PRL_DONE:
591                     handleNullReturnEvent(msg, "nvWriteCdmaPrl");
592                     break;
593 
594                 case CMD_NV_RESET_CONFIG:
595                     request = (MainThreadRequest) msg.obj;
596                     onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
597                     mPhone.nvResetConfig((Integer) request.argument, onCompleted);
598                     break;
599 
600                 case EVENT_NV_RESET_CONFIG_DONE:
601                     handleNullReturnEvent(msg, "nvResetConfig");
602                     break;
603 
604                 case CMD_GET_PREFERRED_NETWORK_TYPE:
605                     request = (MainThreadRequest) msg.obj;
606                     onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
607                     getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
608                     break;
609 
610                 case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
611                     ar = (AsyncResult) msg.obj;
612                     request = (MainThreadRequest) ar.userObj;
613                     if (ar.exception == null && ar.result != null) {
614                         request.result = ar.result;     // Integer
615                     } else {
616                         request.result = null;
617                         if (ar.result == null) {
618                             loge("getPreferredNetworkType: Empty response");
619                         } else if (ar.exception instanceof CommandException) {
620                             loge("getPreferredNetworkType: CommandException: " +
621                                     ar.exception);
622                         } else {
623                             loge("getPreferredNetworkType: Unknown exception");
624                         }
625                     }
626                     synchronized (request) {
627                         request.notifyAll();
628                     }
629                     break;
630 
631                 case CMD_SET_PREFERRED_NETWORK_TYPE:
632                     request = (MainThreadRequest) msg.obj;
633                     onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
634                     int networkType = (Integer) request.argument;
635                     getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
636                     break;
637 
638                 case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
639                     handleNullReturnEvent(msg, "setPreferredNetworkType");
640                     break;
641 
642                 case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
643                     request = (MainThreadRequest)msg.obj;
644                     onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
645                     mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
646                     break;
647 
648                 case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
649                     ar = (AsyncResult)msg.obj;
650                     request = (MainThreadRequest)ar.userObj;
651                     request.result = ar;
652                     synchronized (request) {
653                         request.notifyAll();
654                     }
655                     break;
656 
657                 case CMD_SET_VOICEMAIL_NUMBER:
658                     request = (MainThreadRequest) msg.obj;
659                     onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
660                     Pair<String, String> tagNum = (Pair<String, String>) request.argument;
661                     getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
662                             onCompleted);
663                     break;
664 
665                 case EVENT_SET_VOICEMAIL_NUMBER_DONE:
666                     handleNullReturnEvent(msg, "setVoicemailNumber");
667                     break;
668 
669                 case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
670                     request = (MainThreadRequest) msg.obj;
671                     onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
672                             request);
673                     getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
674                     break;
675 
676                 case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
677                     handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
678                     break;
679 
680                 case CMD_PERFORM_NETWORK_SCAN:
681                     request = (MainThreadRequest) msg.obj;
682                     onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
683                     getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
684                     break;
685 
686                 case EVENT_PERFORM_NETWORK_SCAN_DONE:
687                     ar = (AsyncResult) msg.obj;
688                     request = (MainThreadRequest) ar.userObj;
689                     CellNetworkScanResult cellScanResult;
690                     if (ar.exception == null && ar.result != null) {
691                         cellScanResult = new CellNetworkScanResult(
692                                 CellNetworkScanResult.STATUS_SUCCESS,
693                                 (List<OperatorInfo>) ar.result);
694                     } else {
695                         if (ar.result == null) {
696                             loge("getCellNetworkScanResults: Empty response");
697                         }
698                         if (ar.exception != null) {
699                             loge("getCellNetworkScanResults: Exception: " + ar.exception);
700                         }
701                         int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
702                         if (ar.exception instanceof CommandException) {
703                             CommandException.Error error =
704                                 ((CommandException) (ar.exception)).getCommandError();
705                             if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
706                                 errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
707                             } else if (error == CommandException.Error.GENERIC_FAILURE) {
708                                 errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
709                             }
710                         }
711                         cellScanResult = new CellNetworkScanResult(errorCode, null);
712                     }
713                     request.result = cellScanResult;
714                     synchronized (request) {
715                         request.notifyAll();
716                     }
717                     break;
718 
719                 case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
720                     request = (MainThreadRequest) msg.obj;
721                     ManualNetworkSelectionArgument selArg =
722                             (ManualNetworkSelectionArgument) request.argument;
723                     onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
724                             request);
725                     getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
726                             selArg.persistSelection, onCompleted);
727                     break;
728 
729                 case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
730                     handleNullReturnEvent(msg, "setNetworkSelectionModeManual");
731                     break;
732 
733                 case CMD_GET_MODEM_ACTIVITY_INFO:
734                     request = (MainThreadRequest) msg.obj;
735                     onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
736                     mPhone.getModemActivityInfo(onCompleted);
737                     break;
738 
739                 case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
740                     ar = (AsyncResult) msg.obj;
741                     request = (MainThreadRequest) ar.userObj;
742                     if (ar.exception == null && ar.result != null) {
743                         request.result = ar.result;
744                     } else {
745                         if (ar.result == null) {
746                             loge("queryModemActivityInfo: Empty response");
747                         } else if (ar.exception instanceof CommandException) {
748                             loge("queryModemActivityInfo: CommandException: " +
749                                     ar.exception);
750                         } else {
751                             loge("queryModemActivityInfo: Unknown exception");
752                         }
753                     }
754                     // Result cannot be null. Return ModemActivityInfo with all fields set to 0.
755                     if (request.result == null) {
756                         request.result = new ModemActivityInfo(0, 0, 0, null, 0, 0);
757                     }
758                     synchronized (request) {
759                         request.notifyAll();
760                     }
761                     break;
762 
763                 default:
764                     Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
765                     break;
766             }
767         }
768 
handleNullReturnEvent(Message msg, String command)769         private void handleNullReturnEvent(Message msg, String command) {
770             AsyncResult ar = (AsyncResult) msg.obj;
771             MainThreadRequest request = (MainThreadRequest) ar.userObj;
772             if (ar.exception == null) {
773                 request.result = true;
774             } else {
775                 request.result = false;
776                 if (ar.exception instanceof CommandException) {
777                     loge(command + ": CommandException: " + ar.exception);
778                 } else {
779                     loge(command + ": Unknown exception");
780                 }
781             }
782             synchronized (request) {
783                 request.notifyAll();
784             }
785         }
786     }
787 
788     /**
789      * Posts the specified command to be executed on the main thread,
790      * waits for the request to complete, and returns the result.
791      * @see #sendRequestAsync
792      */
sendRequest(int command, Object argument)793     private Object sendRequest(int command, Object argument) {
794         return sendRequest(command, argument, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
795     }
796 
797     /**
798      * Posts the specified command to be executed on the main thread,
799      * waits for the request to complete, and returns the result.
800      * @see #sendRequestAsync
801      */
sendRequest(int command, Object argument, Integer subId)802     private Object sendRequest(int command, Object argument, Integer subId) {
803         if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
804             throw new RuntimeException("This method will deadlock if called from the main thread.");
805         }
806 
807         MainThreadRequest request = new MainThreadRequest(argument, subId);
808         Message msg = mMainThreadHandler.obtainMessage(command, request);
809         msg.sendToTarget();
810 
811         // Wait for the request to complete
812         synchronized (request) {
813             while (request.result == null) {
814                 try {
815                     request.wait();
816                 } catch (InterruptedException e) {
817                     // Do nothing, go back and wait until the request is complete
818                 }
819             }
820         }
821         return request.result;
822     }
823 
824     /**
825      * Asynchronous ("fire and forget") version of sendRequest():
826      * Posts the specified command to be executed on the main thread, and
827      * returns immediately.
828      * @see #sendRequest
829      */
sendRequestAsync(int command)830     private void sendRequestAsync(int command) {
831         mMainThreadHandler.sendEmptyMessage(command);
832     }
833 
834     /**
835      * Same as {@link #sendRequestAsync(int)} except it takes an argument.
836      * @see {@link #sendRequest(int,Object)}
837      */
sendRequestAsync(int command, Object argument)838     private void sendRequestAsync(int command, Object argument) {
839         MainThreadRequest request = new MainThreadRequest(argument);
840         Message msg = mMainThreadHandler.obtainMessage(command, request);
841         msg.sendToTarget();
842     }
843 
844     /**
845      * Initialize the singleton PhoneInterfaceManager instance.
846      * This is only done once, at startup, from PhoneApp.onCreate().
847      */
init(PhoneGlobals app, Phone phone)848     /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
849         synchronized (PhoneInterfaceManager.class) {
850             if (sInstance == null) {
851                 sInstance = new PhoneInterfaceManager(app, phone);
852             } else {
853                 Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
854             }
855             return sInstance;
856         }
857     }
858 
859     /** Private constructor; @see init() */
PhoneInterfaceManager(PhoneGlobals app, Phone phone)860     private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
861         mApp = app;
862         mPhone = phone;
863         mCM = PhoneGlobals.getInstance().mCM;
864         mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
865         mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
866         mMainThreadHandler = new MainThreadHandler();
867         mTelephonySharedPreferences =
868                 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
869         mSubscriptionController = SubscriptionController.getInstance();
870 
871         publish();
872     }
873 
publish()874     private void publish() {
875         if (DBG) log("publish: " + this);
876 
877         ServiceManager.addService("phone", this);
878     }
879 
getPhoneFromRequest(MainThreadRequest request)880     private Phone getPhoneFromRequest(MainThreadRequest request) {
881         return (request.subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID)
882                 ? mPhone : getPhone(request.subId);
883     }
884 
getUiccCardFromRequest(MainThreadRequest request)885     private UiccCard getUiccCardFromRequest(MainThreadRequest request) {
886         Phone phone = getPhoneFromRequest(request);
887         return phone == null ? null :
888                 UiccController.getInstance().getUiccCard(phone.getPhoneId());
889     }
890 
891     // returns phone associated with the subId.
getPhone(int subId)892     private Phone getPhone(int subId) {
893         return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
894     }
895     //
896     // Implementation of the ITelephony interface.
897     //
898 
dial(String number)899     public void dial(String number) {
900         dialForSubscriber(getPreferredVoiceSubscription(), number);
901     }
902 
dialForSubscriber(int subId, String number)903     public void dialForSubscriber(int subId, String number) {
904         if (DBG) log("dial: " + number);
905         // No permission check needed here: This is just a wrapper around the
906         // ACTION_DIAL intent, which is available to any app since it puts up
907         // the UI before it does anything.
908 
909         String url = createTelUrl(number);
910         if (url == null) {
911             return;
912         }
913 
914         // PENDING: should we just silently fail if phone is offhook or ringing?
915         PhoneConstants.State state = mCM.getState(subId);
916         if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
917             Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
918             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
919             mApp.startActivity(intent);
920         }
921     }
922 
call(String callingPackage, String number)923     public void call(String callingPackage, String number) {
924         callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
925     }
926 
callForSubscriber(int subId, String callingPackage, String number)927     public void callForSubscriber(int subId, String callingPackage, String number) {
928         if (DBG) log("call: " + number);
929 
930         // This is just a wrapper around the ACTION_CALL intent, but we still
931         // need to do a permission check since we're calling startActivity()
932         // from the context of the phone app.
933         enforceCallPermission();
934 
935         if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
936                 != AppOpsManager.MODE_ALLOWED) {
937             return;
938         }
939 
940         String url = createTelUrl(number);
941         if (url == null) {
942             return;
943         }
944 
945         boolean isValid = false;
946         final List<SubscriptionInfo> slist = getActiveSubscriptionInfoList();
947         if (slist != null) {
948             for (SubscriptionInfo subInfoRecord : slist) {
949                 if (subInfoRecord.getSubscriptionId() == subId) {
950                     isValid = true;
951                     break;
952                 }
953             }
954         }
955         if (isValid == false) {
956             return;
957         }
958 
959         Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
960         intent.putExtra(SUBSCRIPTION_KEY, subId);
961         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
962         mApp.startActivity(intent);
963     }
964 
965     /**
966      * End a call based on call state
967      * @return true is a call was ended
968      */
endCall()969     public boolean endCall() {
970         return endCallForSubscriber(getDefaultSubscription());
971     }
972 
973     /**
974      * End a call based on the call state of the subId
975      * @return true is a call was ended
976      */
endCallForSubscriber(int subId)977     public boolean endCallForSubscriber(int subId) {
978         enforceCallPermission();
979         return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId));
980     }
981 
answerRingingCall()982     public void answerRingingCall() {
983         answerRingingCallForSubscriber(getDefaultSubscription());
984     }
985 
answerRingingCallForSubscriber(int subId)986     public void answerRingingCallForSubscriber(int subId) {
987         if (DBG) log("answerRingingCall...");
988         // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
989         // but that can probably wait till the big TelephonyManager API overhaul.
990         // For now, protect this call with the MODIFY_PHONE_STATE permission.
991         enforceModifyPermission();
992         sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId));
993     }
994 
995     /**
996      * Make the actual telephony calls to implement answerRingingCall().
997      * This should only be called from the main thread of the Phone app.
998      * @see #answerRingingCall
999      *
1000      * TODO: it would be nice to return true if we answered the call, or
1001      * false if there wasn't actually a ringing incoming call, or some
1002      * other error occurred.  (In other words, pass back the return value
1003      * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
1004      * But that would require calling this method via sendRequest() rather
1005      * than sendRequestAsync(), and right now we don't actually *need* that
1006      * return value, so let's just return void for now.
1007      */
answerRingingCallInternal(int subId)1008     private void answerRingingCallInternal(int subId) {
1009         final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
1010         if (hasRingingCall) {
1011             final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
1012             final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
1013             if (hasActiveCall && hasHoldingCall) {
1014                 // Both lines are in use!
1015                 // TODO: provide a flag to let the caller specify what
1016                 // policy to use if both lines are in use.  (The current
1017                 // behavior is hardwired to "answer incoming, end ongoing",
1018                 // which is how the CALL button is specced to behave.)
1019                 PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
1020                 return;
1021             } else {
1022                 // answerCall() will automatically hold the current active
1023                 // call, if there is one.
1024                 PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
1025                 return;
1026             }
1027         } else {
1028             // No call was ringing.
1029             return;
1030         }
1031     }
1032 
1033     /**
1034      * This method is no longer used and can be removed once TelephonyManager stops referring to it.
1035      */
silenceRinger()1036     public void silenceRinger() {
1037         Log.e(LOG_TAG, "silenseRinger not supported");
1038     }
1039 
1040     @Override
isOffhook(String callingPackage)1041     public boolean isOffhook(String callingPackage) {
1042         return isOffhookForSubscriber(getDefaultSubscription(), callingPackage);
1043     }
1044 
1045     @Override
isOffhookForSubscriber(int subId, String callingPackage)1046     public boolean isOffhookForSubscriber(int subId, String callingPackage) {
1047         if (!canReadPhoneState(callingPackage, "isOffhookForSubscriber")) {
1048             return false;
1049         }
1050 
1051         final Phone phone = getPhone(subId);
1052         if (phone != null) {
1053             return (phone.getState() == PhoneConstants.State.OFFHOOK);
1054         } else {
1055             return false;
1056         }
1057     }
1058 
1059     @Override
isRinging(String callingPackage)1060     public boolean isRinging(String callingPackage) {
1061         return (isRingingForSubscriber(getDefaultSubscription(), callingPackage));
1062     }
1063 
1064     @Override
isRingingForSubscriber(int subId, String callingPackage)1065     public boolean isRingingForSubscriber(int subId, String callingPackage) {
1066         if (!canReadPhoneState(callingPackage, "isRingingForSubscriber")) {
1067             return false;
1068         }
1069 
1070         final Phone phone = getPhone(subId);
1071         if (phone != null) {
1072             return (phone.getState() == PhoneConstants.State.RINGING);
1073         } else {
1074             return false;
1075         }
1076     }
1077 
1078     @Override
isIdle(String callingPackage)1079     public boolean isIdle(String callingPackage) {
1080         return isIdleForSubscriber(getDefaultSubscription(), callingPackage);
1081     }
1082 
1083     @Override
isIdleForSubscriber(int subId, String callingPackage)1084     public boolean isIdleForSubscriber(int subId, String callingPackage) {
1085         if (!canReadPhoneState(callingPackage, "isIdleForSubscriber")) {
1086             return false;
1087         }
1088 
1089         final Phone phone = getPhone(subId);
1090         if (phone != null) {
1091             return (phone.getState() == PhoneConstants.State.IDLE);
1092         } else {
1093             return false;
1094         }
1095     }
1096 
supplyPin(String pin)1097     public boolean supplyPin(String pin) {
1098         return supplyPinForSubscriber(getDefaultSubscription(), pin);
1099     }
1100 
supplyPinForSubscriber(int subId, String pin)1101     public boolean supplyPinForSubscriber(int subId, String pin) {
1102         int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
1103         return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1104     }
1105 
supplyPuk(String puk, String pin)1106     public boolean supplyPuk(String puk, String pin) {
1107         return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
1108     }
1109 
supplyPukForSubscriber(int subId, String puk, String pin)1110     public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
1111         int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
1112         return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
1113     }
1114 
1115     /** {@hide} */
supplyPinReportResult(String pin)1116     public int[] supplyPinReportResult(String pin) {
1117         return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
1118     }
1119 
supplyPinReportResultForSubscriber(int subId, String pin)1120     public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
1121         enforceModifyPermission();
1122         final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
1123         checkSimPin.start();
1124         return checkSimPin.unlockSim(null, pin);
1125     }
1126 
1127     /** {@hide} */
supplyPukReportResult(String puk, String pin)1128     public int[] supplyPukReportResult(String puk, String pin) {
1129         return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
1130     }
1131 
supplyPukReportResultForSubscriber(int subId, String puk, String pin)1132     public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
1133         enforceModifyPermission();
1134         final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
1135         checkSimPuk.start();
1136         return checkSimPuk.unlockSim(puk, pin);
1137     }
1138 
1139     /**
1140      * Helper thread to turn async call to SimCard#supplyPin into
1141      * a synchronous one.
1142      */
1143     private static class UnlockSim extends Thread {
1144 
1145         private final IccCard mSimCard;
1146 
1147         private boolean mDone = false;
1148         private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1149         private int mRetryCount = -1;
1150 
1151         // For replies from SimCard interface
1152         private Handler mHandler;
1153 
1154         // For async handler to identify request type
1155         private static final int SUPPLY_PIN_COMPLETE = 100;
1156 
UnlockSim(IccCard simCard)1157         public UnlockSim(IccCard simCard) {
1158             mSimCard = simCard;
1159         }
1160 
1161         @Override
run()1162         public void run() {
1163             Looper.prepare();
1164             synchronized (UnlockSim.this) {
1165                 mHandler = new Handler() {
1166                     @Override
1167                     public void handleMessage(Message msg) {
1168                         AsyncResult ar = (AsyncResult) msg.obj;
1169                         switch (msg.what) {
1170                             case SUPPLY_PIN_COMPLETE:
1171                                 Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
1172                                 synchronized (UnlockSim.this) {
1173                                     mRetryCount = msg.arg1;
1174                                     if (ar.exception != null) {
1175                                         if (ar.exception instanceof CommandException &&
1176                                                 ((CommandException)(ar.exception)).getCommandError()
1177                                                 == CommandException.Error.PASSWORD_INCORRECT) {
1178                                             mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
1179                                         } else {
1180                                             mResult = PhoneConstants.PIN_GENERAL_FAILURE;
1181                                         }
1182                                     } else {
1183                                         mResult = PhoneConstants.PIN_RESULT_SUCCESS;
1184                                     }
1185                                     mDone = true;
1186                                     UnlockSim.this.notifyAll();
1187                                 }
1188                                 break;
1189                         }
1190                     }
1191                 };
1192                 UnlockSim.this.notifyAll();
1193             }
1194             Looper.loop();
1195         }
1196 
1197         /*
1198          * Use PIN or PUK to unlock SIM card
1199          *
1200          * If PUK is null, unlock SIM card with PIN
1201          *
1202          * If PUK is not null, unlock SIM card with PUK and set PIN code
1203          */
unlockSim(String puk, String pin)1204         synchronized int[] unlockSim(String puk, String pin) {
1205 
1206             while (mHandler == null) {
1207                 try {
1208                     wait();
1209                 } catch (InterruptedException e) {
1210                     Thread.currentThread().interrupt();
1211                 }
1212             }
1213             Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
1214 
1215             if (puk == null) {
1216                 mSimCard.supplyPin(pin, callback);
1217             } else {
1218                 mSimCard.supplyPuk(puk, pin, callback);
1219             }
1220 
1221             while (!mDone) {
1222                 try {
1223                     Log.d(LOG_TAG, "wait for done");
1224                     wait();
1225                 } catch (InterruptedException e) {
1226                     // Restore the interrupted status
1227                     Thread.currentThread().interrupt();
1228                 }
1229             }
1230             Log.d(LOG_TAG, "done");
1231             int[] resultArray = new int[2];
1232             resultArray[0] = mResult;
1233             resultArray[1] = mRetryCount;
1234             return resultArray;
1235         }
1236     }
1237 
updateServiceLocation()1238     public void updateServiceLocation() {
1239         updateServiceLocationForSubscriber(getDefaultSubscription());
1240 
1241     }
1242 
updateServiceLocationForSubscriber(int subId)1243     public void updateServiceLocationForSubscriber(int subId) {
1244         // No permission check needed here: this call is harmless, and it's
1245         // needed for the ServiceState.requestStateUpdate() call (which is
1246         // already intentionally exposed to 3rd parties.)
1247         final Phone phone = getPhone(subId);
1248         if (phone != null) {
1249             phone.updateServiceLocation();
1250         }
1251     }
1252 
1253     @Override
isRadioOn(String callingPackage)1254     public boolean isRadioOn(String callingPackage) {
1255         return isRadioOnForSubscriber(getDefaultSubscription(), callingPackage);
1256     }
1257 
1258     @Override
isRadioOnForSubscriber(int subId, String callingPackage)1259     public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
1260         if (!canReadPhoneState(callingPackage, "isRadioOnForSubscriber")) {
1261             return false;
1262         }
1263         return isRadioOnForSubscriber(subId);
1264     }
1265 
isRadioOnForSubscriber(int subId)1266     private boolean isRadioOnForSubscriber(int subId) {
1267         final Phone phone = getPhone(subId);
1268         if (phone != null) {
1269             return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1270         } else {
1271             return false;
1272         }
1273     }
1274 
toggleRadioOnOff()1275     public void toggleRadioOnOff() {
1276         toggleRadioOnOffForSubscriber(getDefaultSubscription());
1277 
1278     }
1279 
toggleRadioOnOffForSubscriber(int subId)1280     public void toggleRadioOnOffForSubscriber(int subId) {
1281         enforceModifyPermission();
1282         final Phone phone = getPhone(subId);
1283         if (phone != null) {
1284             phone.setRadioPower(!isRadioOnForSubscriber(subId));
1285         }
1286     }
1287 
setRadio(boolean turnOn)1288     public boolean setRadio(boolean turnOn) {
1289         return setRadioForSubscriber(getDefaultSubscription(), turnOn);
1290     }
1291 
setRadioForSubscriber(int subId, boolean turnOn)1292     public boolean setRadioForSubscriber(int subId, boolean turnOn) {
1293         enforceModifyPermission();
1294         final Phone phone = getPhone(subId);
1295         if (phone == null) {
1296             return false;
1297         }
1298         if ((phone.getServiceState().getState() !=
1299                 ServiceState.STATE_POWER_OFF) != turnOn) {
1300             toggleRadioOnOffForSubscriber(subId);
1301         }
1302         return true;
1303     }
1304 
needMobileRadioShutdown()1305     public boolean needMobileRadioShutdown() {
1306         /*
1307          * If any of the Radios are available, it will need to be
1308          * shutdown. So return true if any Radio is available.
1309          */
1310         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1311             Phone phone = PhoneFactory.getPhone(i);
1312             if (phone != null && phone.isRadioAvailable()) return true;
1313         }
1314         logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
1315         return false;
1316     }
1317 
shutdownMobileRadios()1318     public void shutdownMobileRadios() {
1319         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1320             logv("Shutting down Phone " + i);
1321             shutdownRadioUsingPhoneId(i);
1322         }
1323     }
1324 
shutdownRadioUsingPhoneId(int phoneId)1325     private void shutdownRadioUsingPhoneId(int phoneId) {
1326         enforceModifyPermission();
1327         Phone phone = PhoneFactory.getPhone(phoneId);
1328         if (phone != null && phone.isRadioAvailable()) {
1329             phone.shutdownRadio();
1330         }
1331     }
1332 
setRadioPower(boolean turnOn)1333     public boolean setRadioPower(boolean turnOn) {
1334         return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
1335     }
1336 
setRadioPowerForSubscriber(int subId, boolean turnOn)1337     public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
1338         enforceModifyPermission();
1339         final Phone phone = getPhone(subId);
1340         if (phone != null) {
1341             phone.setRadioPower(turnOn);
1342             return true;
1343         } else {
1344             return false;
1345         }
1346     }
1347 
1348     // FIXME: subId version needed
1349     @Override
enableDataConnectivity()1350     public boolean enableDataConnectivity() {
1351         enforceModifyPermission();
1352         int subId = mSubscriptionController.getDefaultDataSubId();
1353         final Phone phone = getPhone(subId);
1354         if (phone != null) {
1355             phone.setDataEnabled(true);
1356             return true;
1357         } else {
1358             return false;
1359         }
1360     }
1361 
1362     // FIXME: subId version needed
1363     @Override
disableDataConnectivity()1364     public boolean disableDataConnectivity() {
1365         enforceModifyPermission();
1366         int subId = mSubscriptionController.getDefaultDataSubId();
1367         final Phone phone = getPhone(subId);
1368         if (phone != null) {
1369             phone.setDataEnabled(false);
1370             return true;
1371         } else {
1372             return false;
1373         }
1374     }
1375 
1376     // FIXME: subId version needed
1377     @Override
isDataConnectivityPossible()1378     public boolean isDataConnectivityPossible() {
1379         int subId = mSubscriptionController.getDefaultDataSubId();
1380         final Phone phone = getPhone(subId);
1381         if (phone != null) {
1382             return phone.isDataConnectivityPossible();
1383         } else {
1384             return false;
1385         }
1386     }
1387 
handlePinMmi(String dialString)1388     public boolean handlePinMmi(String dialString) {
1389         return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
1390     }
1391 
handlePinMmiForSubscriber(int subId, String dialString)1392     public boolean handlePinMmiForSubscriber(int subId, String dialString) {
1393         enforceModifyPermission();
1394         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1395             return false;
1396         }
1397         return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
1398     }
1399 
getCallState()1400     public int getCallState() {
1401         return getCallStateForSlot(getSlotForDefaultSubscription());
1402     }
1403 
getCallStateForSlot(int slotId)1404     public int getCallStateForSlot(int slotId) {
1405         Phone phone = PhoneFactory.getPhone(slotId);
1406         return phone == null ? TelephonyManager.CALL_STATE_IDLE :
1407             DefaultPhoneNotifier.convertCallState(phone.getState());
1408     }
1409 
1410     @Override
getDataState()1411     public int getDataState() {
1412         Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1413         if (phone != null) {
1414             return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
1415         } else {
1416             return DefaultPhoneNotifier.convertDataState(PhoneConstants.DataState.DISCONNECTED);
1417         }
1418     }
1419 
1420     @Override
getDataActivity()1421     public int getDataActivity() {
1422         Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1423         if (phone != null) {
1424             return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
1425         } else {
1426             return TelephonyManager.DATA_ACTIVITY_NONE;
1427         }
1428     }
1429 
1430     @Override
getCellLocation(String callingPackage)1431     public Bundle getCellLocation(String callingPackage) {
1432         enforceFineOrCoarseLocationPermission("getCellLocation");
1433 
1434         // OP_COARSE_LOCATION controls both fine and coarse location.
1435         if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1436                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1437             log("getCellLocation: returning null; mode != allowed");
1438             return null;
1439         }
1440 
1441         if (checkIfCallerIsSelfOrForegroundUser() ||
1442                 checkCallerInteractAcrossUsersFull()) {
1443             if (DBG_LOC) log("getCellLocation: is active user");
1444             Bundle data = new Bundle();
1445             Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1446             if (phone == null) {
1447                 return null;
1448             }
1449             phone.getCellLocation().fillInNotifierBundle(data);
1450             return data;
1451         } else {
1452             log("getCellLocation: suppress non-active user");
1453             return null;
1454         }
1455     }
1456 
enforceFineOrCoarseLocationPermission(String message)1457     private void enforceFineOrCoarseLocationPermission(String message) {
1458         try {
1459             mApp.enforceCallingOrSelfPermission(
1460                     android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1461         } catch (SecurityException e) {
1462             // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1463             // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1464             // is the weaker precondition
1465             mApp.enforceCallingOrSelfPermission(
1466                     android.Manifest.permission.ACCESS_COARSE_LOCATION, message);
1467         }
1468     }
1469 
1470 
1471     @Override
enableLocationUpdates()1472     public void enableLocationUpdates() {
1473         enableLocationUpdatesForSubscriber(getDefaultSubscription());
1474     }
1475 
1476     @Override
enableLocationUpdatesForSubscriber(int subId)1477     public void enableLocationUpdatesForSubscriber(int subId) {
1478         mApp.enforceCallingOrSelfPermission(
1479                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
1480         final Phone phone = getPhone(subId);
1481         if (phone != null) {
1482             phone.enableLocationUpdates();
1483         }
1484     }
1485 
1486     @Override
disableLocationUpdates()1487     public void disableLocationUpdates() {
1488         disableLocationUpdatesForSubscriber(getDefaultSubscription());
1489     }
1490 
1491     @Override
disableLocationUpdatesForSubscriber(int subId)1492     public void disableLocationUpdatesForSubscriber(int subId) {
1493         mApp.enforceCallingOrSelfPermission(
1494                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
1495         final Phone phone = getPhone(subId);
1496         if (phone != null) {
1497             phone.disableLocationUpdates();
1498         }
1499     }
1500 
1501     @Override
1502     @SuppressWarnings("unchecked")
getNeighboringCellInfo(String callingPackage)1503     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1504         enforceFineOrCoarseLocationPermission("getNeighboringCellInfo");
1505 
1506         // OP_COARSE_LOCATION controls both fine and coarse location.
1507         if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1508                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1509             return null;
1510         }
1511 
1512         if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1513                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1514             return null;
1515         }
1516 
1517         if (checkIfCallerIsSelfOrForegroundUser() ||
1518                 checkCallerInteractAcrossUsersFull()) {
1519             if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1520 
1521             ArrayList<NeighboringCellInfo> cells = null;
1522 
1523             try {
1524                 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
1525                         CMD_HANDLE_NEIGHBORING_CELL, null,
1526                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
1527             } catch (RuntimeException e) {
1528                 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
1529             }
1530             return cells;
1531         } else {
1532             if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1533             return null;
1534         }
1535     }
1536 
1537 
1538     @Override
getAllCellInfo(String callingPackage)1539     public List<CellInfo> getAllCellInfo(String callingPackage) {
1540         enforceFineOrCoarseLocationPermission("getAllCellInfo");
1541 
1542         // OP_COARSE_LOCATION controls both fine and coarse location.
1543         if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1544                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1545             return null;
1546         }
1547 
1548         if (checkIfCallerIsSelfOrForegroundUser() ||
1549                 checkCallerInteractAcrossUsersFull()) {
1550             if (DBG_LOC) log("getAllCellInfo: is active user");
1551             List<CellInfo> cellInfos = new ArrayList<CellInfo>();
1552             for (Phone phone : PhoneFactory.getPhones()) {
1553                 final List<CellInfo> info = phone.getAllCellInfo();
1554                 if (info != null) cellInfos.addAll(phone.getAllCellInfo());
1555             }
1556             return cellInfos;
1557         } else {
1558             if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1559             return null;
1560         }
1561     }
1562 
1563     @Override
setCellInfoListRate(int rateInMillis)1564     public void setCellInfoListRate(int rateInMillis) {
1565         mPhone.setCellInfoListRate(rateInMillis);
1566     }
1567 
1568     @Override
getImeiForSlot(int slotId, String callingPackage)1569     public String getImeiForSlot(int slotId, String callingPackage) {
1570       if (!canReadPhoneState(callingPackage, "getImeiForSlot")) {
1571           return null;
1572       }
1573       Phone phone = PhoneFactory.getPhone(slotId);
1574       return phone == null ? null : phone.getImei();
1575     }
1576 
1577     @Override
getDeviceSoftwareVersionForSlot(int slotId, String callingPackage)1578     public String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage) {
1579       if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) {
1580           return null;
1581       }
1582       Phone phone = PhoneFactory.getPhone(slotId);
1583       return phone == null ? null : phone.getDeviceSvn();
1584     }
1585 
1586     //
1587     // Internal helper methods.
1588     //
1589 
1590     /**
1591      * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL.
1592      */
checkCallerInteractAcrossUsersFull()1593     private boolean checkCallerInteractAcrossUsersFull() {
1594         return mPhone.getContext().checkCallingOrSelfPermission(
1595                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1596                 == PackageManager.PERMISSION_GRANTED;
1597     }
1598 
checkIfCallerIsSelfOrForegroundUser()1599     private static boolean checkIfCallerIsSelfOrForegroundUser() {
1600         boolean ok;
1601 
1602         boolean self = Binder.getCallingUid() == Process.myUid();
1603         if (!self) {
1604             // Get the caller's user id then clear the calling identity
1605             // which will be restored in the finally clause.
1606             int callingUser = UserHandle.getCallingUserId();
1607             long ident = Binder.clearCallingIdentity();
1608 
1609             try {
1610                 // With calling identity cleared the current user is the foreground user.
1611                 int foregroundUser = ActivityManager.getCurrentUser();
1612                 ok = (foregroundUser == callingUser);
1613                 if (DBG_LOC) {
1614                     log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1615                             + " callingUser=" + callingUser + " ok=" + ok);
1616                 }
1617             } catch (Exception ex) {
1618                 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1619                 ok = false;
1620             } finally {
1621                 Binder.restoreCallingIdentity(ident);
1622             }
1623         } else {
1624             if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1625             ok = true;
1626         }
1627         if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1628         return ok;
1629     }
1630 
1631     /**
1632      * Make sure the caller has the MODIFY_PHONE_STATE permission.
1633      *
1634      * @throws SecurityException if the caller does not have the required permission
1635      */
enforceModifyPermission()1636     private void enforceModifyPermission() {
1637         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1638     }
1639 
1640     /**
1641      * Make sure either system app or the caller has carrier privilege.
1642      *
1643      * @throws SecurityException if the caller does not have the required permission/privilege
1644      */
enforceModifyPermissionOrCarrierPrivilege(int subId)1645     private void enforceModifyPermissionOrCarrierPrivilege(int subId) {
1646         int permission = mApp.checkCallingOrSelfPermission(
1647                 android.Manifest.permission.MODIFY_PHONE_STATE);
1648         if (permission == PackageManager.PERMISSION_GRANTED) {
1649             return;
1650         }
1651 
1652         log("No modify permission, check carrier privilege next.");
1653         enforceCarrierPrivilege(subId);
1654     }
1655 
1656     /**
1657      * Make sure the caller has carrier privilege.
1658      *
1659      * @throws SecurityException if the caller does not have the required permission
1660      */
enforceCarrierPrivilege(int subId)1661     private void enforceCarrierPrivilege(int subId) {
1662         if (getCarrierPrivilegeStatus(subId) !=
1663                     TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1664             loge("No Carrier Privilege.");
1665             throw new SecurityException("No Carrier Privilege.");
1666         }
1667     }
1668 
1669     /**
1670      * Make sure the caller has the CALL_PHONE permission.
1671      *
1672      * @throws SecurityException if the caller does not have the required permission
1673      */
enforceCallPermission()1674     private void enforceCallPermission() {
1675         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1676     }
1677 
enforceConnectivityInternalPermission()1678     private void enforceConnectivityInternalPermission() {
1679         mApp.enforceCallingOrSelfPermission(
1680                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1681                 "ConnectivityService");
1682     }
1683 
createTelUrl(String number)1684     private String createTelUrl(String number) {
1685         if (TextUtils.isEmpty(number)) {
1686             return null;
1687         }
1688 
1689         return "tel:" + number;
1690     }
1691 
log(String msg)1692     private static void log(String msg) {
1693         Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1694     }
1695 
logv(String msg)1696     private static void logv(String msg) {
1697         Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1698     }
1699 
loge(String msg)1700     private static void loge(String msg) {
1701         Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1702     }
1703 
1704     @Override
getActivePhoneType()1705     public int getActivePhoneType() {
1706         return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
1707     }
1708 
1709     @Override
getActivePhoneTypeForSlot(int slotId)1710     public int getActivePhoneTypeForSlot(int slotId) {
1711         final Phone phone = PhoneFactory.getPhone(slotId);
1712         if (phone == null) {
1713             return PhoneConstants.PHONE_TYPE_NONE;
1714         } else {
1715             return phone.getPhoneType();
1716         }
1717     }
1718 
1719     /**
1720      * Returns the CDMA ERI icon index to display
1721      */
1722     @Override
getCdmaEriIconIndex(String callingPackage)1723     public int getCdmaEriIconIndex(String callingPackage) {
1724         return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
1725     }
1726 
1727     @Override
getCdmaEriIconIndexForSubscriber(int subId, String callingPackage)1728     public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
1729         if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
1730             return -1;
1731         }
1732         final Phone phone = getPhone(subId);
1733         if (phone != null) {
1734             return phone.getCdmaEriIconIndex();
1735         } else {
1736             return -1;
1737         }
1738     }
1739 
1740     /**
1741      * Returns the CDMA ERI icon mode,
1742      * 0 - ON
1743      * 1 - FLASHING
1744      */
1745     @Override
getCdmaEriIconMode(String callingPackage)1746     public int getCdmaEriIconMode(String callingPackage) {
1747         return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
1748     }
1749 
1750     @Override
getCdmaEriIconModeForSubscriber(int subId, String callingPackage)1751     public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
1752         if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
1753             return -1;
1754         }
1755         final Phone phone = getPhone(subId);
1756         if (phone != null) {
1757             return phone.getCdmaEriIconMode();
1758         } else {
1759             return -1;
1760         }
1761     }
1762 
1763     /**
1764      * Returns the CDMA ERI text,
1765      */
1766     @Override
getCdmaEriText(String callingPackage)1767     public String getCdmaEriText(String callingPackage) {
1768         return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
1769     }
1770 
1771     @Override
getCdmaEriTextForSubscriber(int subId, String callingPackage)1772     public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
1773         if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
1774             return null;
1775         }
1776         final Phone phone = getPhone(subId);
1777         if (phone != null) {
1778             return phone.getCdmaEriText();
1779         } else {
1780             return null;
1781         }
1782     }
1783 
1784     /**
1785      * Returns the CDMA MDN.
1786      */
1787     @Override
getCdmaMdn(int subId)1788     public String getCdmaMdn(int subId) {
1789         enforceModifyPermissionOrCarrierPrivilege(subId);
1790         final Phone phone = getPhone(subId);
1791         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
1792             return phone.getLine1Number();
1793         } else {
1794             return null;
1795         }
1796     }
1797 
1798     /**
1799      * Returns the CDMA MIN.
1800      */
1801     @Override
getCdmaMin(int subId)1802     public String getCdmaMin(int subId) {
1803         enforceModifyPermissionOrCarrierPrivilege(subId);
1804         final Phone phone = getPhone(subId);
1805         if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1806             return phone.getCdmaMin();
1807         } else {
1808             return null;
1809         }
1810     }
1811 
1812     /**
1813      * Returns true if CDMA provisioning needs to run.
1814      */
needsOtaServiceProvisioning()1815     public boolean needsOtaServiceProvisioning() {
1816         return mPhone.needsOtaServiceProvisioning();
1817     }
1818 
1819     /**
1820      * Sets the voice mail number of a given subId.
1821      */
1822     @Override
setVoiceMailNumber(int subId, String alphaTag, String number)1823     public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
1824         enforceCarrierPrivilege(subId);
1825         Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
1826                 new Pair<String, String>(alphaTag, number), new Integer(subId));
1827         return success;
1828     }
1829 
1830     /**
1831      * Returns the unread count of voicemails
1832      */
getVoiceMessageCount()1833     public int getVoiceMessageCount() {
1834         return getVoiceMessageCountForSubscriber(getDefaultSubscription());
1835     }
1836 
1837     /**
1838      * Returns the unread count of voicemails for a subId
1839      */
1840     @Override
getVoiceMessageCountForSubscriber( int subId)1841     public int getVoiceMessageCountForSubscriber( int subId) {
1842         final Phone phone = getPhone(subId);
1843         if (phone != null) {
1844             return phone.getVoiceMessageCount();
1845         } else {
1846             return 0;
1847         }
1848     }
1849 
1850     /**
1851      * Returns the data network type.
1852      * Legacy call, permission-free.
1853      *
1854      * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
1855      */
1856     @Override
getNetworkType()1857     public int getNetworkType() {
1858         final Phone phone = getPhone(getDefaultSubscription());
1859         if (phone != null) {
1860             return phone.getServiceState().getDataNetworkType();
1861         } else {
1862             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1863         }
1864     }
1865 
1866     /**
1867      * Returns the network type for a subId
1868      */
1869     @Override
getNetworkTypeForSubscriber(int subId, String callingPackage)1870     public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
1871         if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
1872             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1873         }
1874 
1875         final Phone phone = getPhone(subId);
1876         if (phone != null) {
1877             return phone.getServiceState().getDataNetworkType();
1878         } else {
1879             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1880         }
1881     }
1882 
1883     /**
1884      * Returns the data network type
1885      */
1886     @Override
getDataNetworkType(String callingPackage)1887     public int getDataNetworkType(String callingPackage) {
1888         return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
1889     }
1890 
1891     /**
1892      * Returns the data network type for a subId
1893      */
1894     @Override
getDataNetworkTypeForSubscriber(int subId, String callingPackage)1895     public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
1896         if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
1897             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1898         }
1899 
1900         final Phone phone = getPhone(subId);
1901         if (phone != null) {
1902             return phone.getServiceState().getDataNetworkType();
1903         } else {
1904             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1905         }
1906     }
1907 
1908     /**
1909      * Returns the Voice network type for a subId
1910      */
1911     @Override
getVoiceNetworkTypeForSubscriber(int subId, String callingPackage)1912     public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
1913         if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
1914             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1915         }
1916 
1917         final Phone phone = getPhone(subId);
1918         if (phone != null) {
1919             return phone.getServiceState().getVoiceNetworkType();
1920         } else {
1921             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1922         }
1923     }
1924 
1925     /**
1926      * @return true if a ICC card is present
1927      */
hasIccCard()1928     public boolean hasIccCard() {
1929         // FIXME Make changes to pass defaultSimId of type int
1930         return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription()));
1931     }
1932 
1933     /**
1934      * @return true if a ICC card is present for a slotId
1935      */
1936     @Override
hasIccCardUsingSlotId(int slotId)1937     public boolean hasIccCardUsingSlotId(int slotId) {
1938         int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId);
1939         final Phone phone = getPhone(subId[0]);
1940         if (subId != null && phone != null) {
1941             return phone.getIccCard().hasIccCard();
1942         } else {
1943             return false;
1944         }
1945     }
1946 
1947     /**
1948      * Return if the current radio is LTE on CDMA. This
1949      * is a tri-state return value as for a period of time
1950      * the mode may be unknown.
1951      *
1952      * @param callingPackage the name of the package making the call.
1953      * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1954      * or {@link Phone#LTE_ON_CDMA_TRUE}
1955      */
1956     @Override
getLteOnCdmaMode(String callingPackage)1957     public int getLteOnCdmaMode(String callingPackage) {
1958         return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
1959     }
1960 
1961     @Override
getLteOnCdmaModeForSubscriber(int subId, String callingPackage)1962     public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
1963         if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
1964             return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
1965         }
1966 
1967         final Phone phone = getPhone(subId);
1968         if (phone == null) {
1969             return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
1970         } else {
1971             return phone.getLteOnCdmaMode();
1972         }
1973     }
1974 
setPhone(Phone phone)1975     public void setPhone(Phone phone) {
1976         mPhone = phone;
1977     }
1978 
1979     /**
1980      * {@hide}
1981      * Returns Default subId, 0 in the case of single standby.
1982      */
getDefaultSubscription()1983     private int getDefaultSubscription() {
1984         return mSubscriptionController.getDefaultSubId();
1985     }
1986 
getSlotForDefaultSubscription()1987     private int getSlotForDefaultSubscription() {
1988         return mSubscriptionController.getPhoneId(getDefaultSubscription());
1989     }
1990 
getPreferredVoiceSubscription()1991     private int getPreferredVoiceSubscription() {
1992         return mSubscriptionController.getDefaultVoiceSubId();
1993     }
1994 
1995     /**
1996      * @see android.telephony.TelephonyManager.WifiCallingChoices
1997      */
getWhenToMakeWifiCalls()1998     public int getWhenToMakeWifiCalls() {
1999         return Settings.System.getInt(mPhone.getContext().getContentResolver(),
2000                 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
2001     }
2002 
2003     /**
2004      * @see android.telephony.TelephonyManager.WifiCallingChoices
2005      */
setWhenToMakeWifiCalls(int preference)2006     public void setWhenToMakeWifiCalls(int preference) {
2007         if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
2008         Settings.System.putInt(mPhone.getContext().getContentResolver(),
2009                 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
2010     }
2011 
getWhenToMakeWifiCallsDefaultPreference()2012     private static int getWhenToMakeWifiCallsDefaultPreference() {
2013         // TODO: Use a build property to choose this value.
2014         return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
2015     }
2016 
2017     @Override
iccOpenLogicalChannel(int subId, String AID)2018     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) {
2019         enforceModifyPermissionOrCarrierPrivilege(subId);
2020 
2021         if (DBG) log("iccOpenLogicalChannel: subId=" + subId + " aid=" + AID);
2022         IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
2023             CMD_OPEN_CHANNEL, AID, subId);
2024         if (DBG) log("iccOpenLogicalChannel: " + response);
2025         return response;
2026     }
2027 
2028     @Override
iccCloseLogicalChannel(int subId, int channel)2029     public boolean iccCloseLogicalChannel(int subId, int channel) {
2030         enforceModifyPermissionOrCarrierPrivilege(subId);
2031 
2032         if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
2033         if (channel < 0) {
2034           return false;
2035         }
2036         Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel, subId);
2037         if (DBG) log("iccCloseLogicalChannel: " + success);
2038         return success;
2039     }
2040 
2041     @Override
iccTransmitApduLogicalChannel(int subId, int channel, int cla, int command, int p1, int p2, int p3, String data)2042     public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
2043             int command, int p1, int p2, int p3, String data) {
2044         enforceModifyPermissionOrCarrierPrivilege(subId);
2045 
2046         if (DBG) {
2047             log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel +
2048                     " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
2049                     " data=" + data);
2050         }
2051 
2052         if (channel < 0) {
2053             return "";
2054         }
2055 
2056         IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
2057                 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId);
2058         if (DBG) log("iccTransmitApduLogicalChannel: " + response);
2059 
2060         // Append the returned status code to the end of the response payload.
2061         String s = Integer.toHexString(
2062                 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2063         if (response.payload != null) {
2064             s = IccUtils.bytesToHexString(response.payload) + s;
2065         }
2066         return s;
2067     }
2068 
2069     @Override
iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2, int p3, String data)2070     public String iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2,
2071                 int p3, String data) {
2072         enforceModifyPermissionOrCarrierPrivilege(subId);
2073 
2074         if (DBG) {
2075             log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd=" + command
2076                     + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
2077         }
2078 
2079         IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
2080                 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId);
2081         if (DBG) log("iccTransmitApduBasicChannel: " + response);
2082 
2083         // Append the returned status code to the end of the response payload.
2084         String s = Integer.toHexString(
2085                 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2086         if (response.payload != null) {
2087             s = IccUtils.bytesToHexString(response.payload) + s;
2088         }
2089         return s;
2090     }
2091 
2092     @Override
iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3, String filePath)2093     public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
2094             String filePath) {
2095         enforceModifyPermissionOrCarrierPrivilege(subId);
2096 
2097         if (DBG) {
2098             log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " +
2099                 p1 + " " + p2 + " " + p3 + ":" + filePath);
2100         }
2101 
2102         IccIoResult response =
2103             (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
2104                     new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
2105                     subId);
2106 
2107         if (DBG) {
2108           log("Exchange SIM_IO [R]" + response);
2109         }
2110 
2111         byte[] result = null;
2112         int length = 2;
2113         if (response.payload != null) {
2114             length = 2 + response.payload.length;
2115             result = new byte[length];
2116             System.arraycopy(response.payload, 0, result, 0, response.payload.length);
2117         } else {
2118             result = new byte[length];
2119         }
2120 
2121         result[length - 1] = (byte) response.sw2;
2122         result[length - 2] = (byte) response.sw1;
2123         return result;
2124     }
2125 
2126     @Override
sendEnvelopeWithStatus(int subId, String content)2127     public String sendEnvelopeWithStatus(int subId, String content) {
2128         enforceModifyPermissionOrCarrierPrivilege(subId);
2129 
2130         IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId);
2131         if (response.payload == null) {
2132           return "";
2133         }
2134 
2135         // Append the returned status code to the end of the response payload.
2136         String s = Integer.toHexString(
2137                 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2138         s = IccUtils.bytesToHexString(response.payload) + s;
2139         return s;
2140     }
2141 
2142     /**
2143      * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2144      * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2145      *
2146      * @param itemID the ID of the item to read
2147      * @return the NV item as a String, or null on error.
2148      */
2149     @Override
nvReadItem(int itemID)2150     public String nvReadItem(int itemID) {
2151         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2152         if (DBG) log("nvReadItem: item " + itemID);
2153         String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
2154         if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
2155         return value;
2156     }
2157 
2158     /**
2159      * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2160      * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2161      *
2162      * @param itemID the ID of the item to read
2163      * @param itemValue the value to write, as a String
2164      * @return true on success; false on any failure
2165      */
2166     @Override
nvWriteItem(int itemID, String itemValue)2167     public boolean nvWriteItem(int itemID, String itemValue) {
2168         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2169         if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
2170         Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
2171                 new Pair<Integer, String>(itemID, itemValue));
2172         if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
2173         return success;
2174     }
2175 
2176     /**
2177      * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
2178      * Used for device configuration by some CDMA operators.
2179      *
2180      * @param preferredRoamingList byte array containing the new PRL
2181      * @return true on success; false on any failure
2182      */
2183     @Override
nvWriteCdmaPrl(byte[] preferredRoamingList)2184     public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
2185         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2186         if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
2187         Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
2188         if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
2189         return success;
2190     }
2191 
2192     /**
2193      * Perform the specified type of NV config reset.
2194      * Used for device configuration by some CDMA operators.
2195      *
2196      * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
2197      * @return true on success; false on any failure
2198      */
2199     @Override
nvResetConfig(int resetType)2200     public boolean nvResetConfig(int resetType) {
2201         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2202         if (DBG) log("nvResetConfig: type " + resetType);
2203         Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
2204         if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
2205         return success;
2206     }
2207 
2208     /**
2209      * {@hide}
2210      * Returns Default sim, 0 in the case of single standby.
2211      */
getDefaultSim()2212     public int getDefaultSim() {
2213         //TODO Need to get it from Telephony Devcontroller
2214         return 0;
2215     }
2216 
getPcscfAddress(String apnType, String callingPackage)2217     public String[] getPcscfAddress(String apnType, String callingPackage) {
2218         if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
2219             return new String[0];
2220         }
2221 
2222 
2223         return mPhone.getPcscfAddress(apnType);
2224     }
2225 
setImsRegistrationState(boolean registered)2226     public void setImsRegistrationState(boolean registered) {
2227         enforceModifyPermission();
2228         mPhone.setImsRegistrationState(registered);
2229     }
2230 
2231     /**
2232      * Set the network selection mode to automatic.
2233      *
2234      */
2235     @Override
setNetworkSelectionModeAutomatic(int subId)2236     public void setNetworkSelectionModeAutomatic(int subId) {
2237         enforceModifyPermissionOrCarrierPrivilege(subId);
2238         if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
2239         sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
2240     }
2241 
2242     /**
2243      * Set the network selection mode to manual with the selected carrier.
2244      */
2245     @Override
setNetworkSelectionModeManual(int subId, OperatorInfo operator, boolean persistSelection)2246     public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
2247             boolean persistSelection) {
2248         enforceModifyPermissionOrCarrierPrivilege(subId);
2249         if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
2250         ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
2251                 persistSelection);
2252         return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
2253     }
2254 
2255     /**
2256      * Scans for available networks.
2257      */
2258     @Override
getCellNetworkScanResults(int subId)2259     public CellNetworkScanResult getCellNetworkScanResults(int subId) {
2260         enforceModifyPermissionOrCarrierPrivilege(subId);
2261         if (DBG) log("getCellNetworkScanResults: subId " + subId);
2262         CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
2263                 CMD_PERFORM_NETWORK_SCAN, null, subId);
2264         return result;
2265     }
2266 
2267     /**
2268      * Get the calculated preferred network type.
2269      * Used for debugging incorrect network type.
2270      *
2271      * @return the preferred network type, defined in RILConstants.java.
2272      */
2273     @Override
getCalculatedPreferredNetworkType(String callingPackage)2274     public int getCalculatedPreferredNetworkType(String callingPackage) {
2275         if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
2276             return RILConstants.PREFERRED_NETWORK_MODE;
2277         }
2278 
2279         return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
2280     }
2281 
2282     /**
2283      * Get the preferred network type.
2284      * Used for device configuration by some CDMA operators.
2285      *
2286      * @return the preferred network type, defined in RILConstants.java.
2287      */
2288     @Override
getPreferredNetworkType(int subId)2289     public int getPreferredNetworkType(int subId) {
2290         enforceModifyPermissionOrCarrierPrivilege(subId);
2291         if (DBG) log("getPreferredNetworkType");
2292         int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
2293         int networkType = (result != null ? result[0] : -1);
2294         if (DBG) log("getPreferredNetworkType: " + networkType);
2295         return networkType;
2296     }
2297 
2298     /**
2299      * Set the preferred network type.
2300      * Used for device configuration by some CDMA operators.
2301      *
2302      * @param networkType the preferred network type, defined in RILConstants.java.
2303      * @return true on success; false on any failure.
2304      */
2305     @Override
setPreferredNetworkType(int subId, int networkType)2306     public boolean setPreferredNetworkType(int subId, int networkType) {
2307         enforceModifyPermissionOrCarrierPrivilege(subId);
2308         if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
2309         Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
2310         if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
2311         if (success) {
2312             Settings.Global.putInt(mPhone.getContext().getContentResolver(),
2313                     Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
2314         }
2315         return success;
2316     }
2317 
2318     /**
2319      * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
2320      * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
2321      * tethering.
2322      *
2323      * @return 0: Not required. 1: required. 2: Not set.
2324      * @hide
2325      */
2326     @Override
getTetherApnRequired()2327     public int getTetherApnRequired() {
2328         enforceModifyPermission();
2329         int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2330                 Settings.Global.TETHER_DUN_REQUIRED, 2);
2331         // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2332         // config_tether_apndata.
2333         if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2334             dunRequired = 1;
2335         }
2336         return dunRequired;
2337     }
2338 
2339     /**
2340      * Set mobile data enabled
2341      * Used by the user through settings etc to turn on/off mobile data
2342      *
2343      * @param enable {@code true} turn turn data on, else {@code false}
2344      */
2345     @Override
setDataEnabled(int subId, boolean enable)2346     public void setDataEnabled(int subId, boolean enable) {
2347         enforceModifyPermission();
2348         int phoneId = mSubscriptionController.getPhoneId(subId);
2349         if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2350         Phone phone = PhoneFactory.getPhone(phoneId);
2351         if (phone != null) {
2352             if (DBG) log("setDataEnabled: subId=" + subId + " enable=" + enable);
2353             phone.setDataEnabled(enable);
2354         } else {
2355             loge("setDataEnabled: no phone for subId=" + subId);
2356         }
2357     }
2358 
2359     /**
2360      * Get whether mobile data is enabled.
2361      *
2362      * Note that this used to be available from ConnectivityService, gated by
2363      * ACCESS_NETWORK_STATE permission, so this will accept either that or
2364      * our MODIFY_PHONE_STATE.
2365      *
2366      * @return {@code true} if data is enabled else {@code false}
2367      */
2368     @Override
getDataEnabled(int subId)2369     public boolean getDataEnabled(int subId) {
2370         try {
2371             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2372                     null);
2373         } catch (Exception e) {
2374             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
2375                     null);
2376         }
2377         int phoneId = mSubscriptionController.getPhoneId(subId);
2378         if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2379         Phone phone = PhoneFactory.getPhone(phoneId);
2380         if (phone != null) {
2381             boolean retVal = phone.getDataEnabled();
2382             if (DBG) log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
2383             return retVal;
2384         } else {
2385             if (DBG) loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
2386             return false;
2387         }
2388     }
2389 
2390     @Override
getCarrierPrivilegeStatus(int subId)2391     public int getCarrierPrivilegeStatus(int subId) {
2392         final Phone phone = getPhone(subId);
2393         if (phone == null) {
2394             loge("getCarrierPrivilegeStatus: Invalid subId");
2395             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2396         }
2397         UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
2398         if (card == null) {
2399             loge("getCarrierPrivilegeStatus: No UICC");
2400             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2401         }
2402         return card.getCarrierPrivilegeStatusForCurrentTransaction(
2403                 phone.getContext().getPackageManager());
2404     }
2405 
2406     @Override
checkCarrierPrivilegesForPackage(String pkgName)2407     public int checkCarrierPrivilegesForPackage(String pkgName) {
2408         if (TextUtils.isEmpty(pkgName))
2409             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2410         UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
2411         if (card == null) {
2412             loge("checkCarrierPrivilegesForPackage: No UICC");
2413             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2414         }
2415         return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
2416     }
2417 
2418     @Override
checkCarrierPrivilegesForPackageAnyPhone(String pkgName)2419     public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
2420         if (TextUtils.isEmpty(pkgName))
2421             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2422         int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2423         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2424             UiccCard card = UiccController.getInstance().getUiccCard(i);
2425             if (card == null) {
2426               // No UICC in that slot.
2427               continue;
2428             }
2429 
2430             result = card.getCarrierPrivilegeStatus(
2431                 mPhone.getContext().getPackageManager(), pkgName);
2432             if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2433                 break;
2434             }
2435         }
2436 
2437         return result;
2438     }
2439 
2440     @Override
getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId)2441     public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2442         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2443             loge("phoneId " + phoneId + " is not valid.");
2444             return null;
2445         }
2446         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
2447         if (card == null) {
2448             loge("getCarrierPackageNamesForIntent: No UICC");
2449             return null ;
2450         }
2451         return card.getCarrierPackageNamesForIntent(
2452                 mPhone.getContext().getPackageManager(), intent);
2453     }
2454 
2455     @Override
getPackagesWithCarrierPrivileges()2456     public List<String> getPackagesWithCarrierPrivileges() {
2457         PackageManager pm = mPhone.getContext().getPackageManager();
2458         List<String> privilegedPackages = new ArrayList<>();
2459         List<PackageInfo> packages = null;
2460         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2461             UiccCard card = UiccController.getInstance().getUiccCard(i);
2462             if (card == null) {
2463                 // No UICC in that slot.
2464                 continue;
2465             }
2466             if (card.hasCarrierPrivilegeRules()) {
2467                 if (packages == null) {
2468                     // Only check packages in user 0 for now
2469                     packages = pm.getInstalledPackagesAsUser(
2470                             PackageManager.MATCH_DISABLED_COMPONENTS
2471                             | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
2472                             | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
2473                 }
2474                 for (int p = packages.size() - 1; p >= 0; p--) {
2475                     PackageInfo pkgInfo = packages.get(p);
2476                     if (pkgInfo != null && pkgInfo.packageName != null
2477                             && card.getCarrierPrivilegeStatus(pkgInfo)
2478                                 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2479                         privilegedPackages.add(pkgInfo.packageName);
2480                     }
2481                 }
2482             }
2483         }
2484         return privilegedPackages;
2485     }
2486 
getIccId(int subId)2487     private String getIccId(int subId) {
2488         final Phone phone = getPhone(subId);
2489         UiccCard card = phone == null ? null : phone.getUiccCard();
2490         if (card == null) {
2491             loge("getIccId: No UICC");
2492             return null;
2493         }
2494         String iccId = card.getIccId();
2495         if (TextUtils.isEmpty(iccId)) {
2496             loge("getIccId: ICC ID is null or empty.");
2497             return null;
2498         }
2499         return iccId;
2500     }
2501 
2502     @Override
setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number)2503     public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
2504             String number) {
2505         enforceCarrierPrivilege(subId);
2506 
2507         final String iccId = getIccId(subId);
2508         final Phone phone = getPhone(subId);
2509         if (phone == null) {
2510             return false;
2511         }
2512         final String subscriberId = phone.getSubscriberId();
2513 
2514         if (DBG_MERGE) {
2515             Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
2516                     + subscriberId + " to " + number);
2517         }
2518 
2519         if (TextUtils.isEmpty(iccId)) {
2520             return false;
2521         }
2522 
2523         final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2524 
2525         final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2526         if (alphaTag == null) {
2527             editor.remove(alphaTagPrefKey);
2528         } else {
2529             editor.putString(alphaTagPrefKey, alphaTag);
2530         }
2531 
2532         // Record both the line number and IMSI for this ICCID, since we need to
2533         // track all merged IMSIs based on line number
2534         final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2535         final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2536         if (number == null) {
2537             editor.remove(numberPrefKey);
2538             editor.remove(subscriberPrefKey);
2539         } else {
2540             editor.putString(numberPrefKey, number);
2541             editor.putString(subscriberPrefKey, subscriberId);
2542         }
2543 
2544         editor.commit();
2545         return true;
2546     }
2547 
2548     @Override
getLine1NumberForDisplay(int subId, String callingPackage)2549     public String getLine1NumberForDisplay(int subId, String callingPackage) {
2550         // This is open to apps with WRITE_SMS.
2551         if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
2552             if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
2553             return null;
2554         }
2555 
2556         String iccId = getIccId(subId);
2557         if (iccId != null) {
2558             String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2559             if (DBG_MERGE) {
2560                 log("getLine1NumberForDisplay returning " +
2561                         mTelephonySharedPreferences.getString(numberPrefKey, null));
2562             }
2563             return mTelephonySharedPreferences.getString(numberPrefKey, null);
2564         }
2565         if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
2566         return null;
2567     }
2568 
2569     @Override
getLine1AlphaTagForDisplay(int subId, String callingPackage)2570     public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2571         if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2572             return null;
2573         }
2574 
2575         String iccId = getIccId(subId);
2576         if (iccId != null) {
2577             String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2578             return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
2579         }
2580         return null;
2581     }
2582 
2583     @Override
getMergedSubscriberIds(String callingPackage)2584     public String[] getMergedSubscriberIds(String callingPackage) {
2585         if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
2586             return null;
2587         }
2588         final Context context = mPhone.getContext();
2589         final TelephonyManager tele = TelephonyManager.from(context);
2590         final SubscriptionManager sub = SubscriptionManager.from(context);
2591 
2592         // Figure out what subscribers are currently active
2593         final ArraySet<String> activeSubscriberIds = new ArraySet<>();
2594         // Clear calling identity, when calling TelephonyManager, because callerUid must be
2595         // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail.
2596         final long identity  = Binder.clearCallingIdentity();
2597         try {
2598             final int[] subIds = sub.getActiveSubscriptionIdList();
2599             for (int subId : subIds) {
2600                 activeSubscriberIds.add(tele.getSubscriberId(subId));
2601             }
2602         } finally {
2603             Binder.restoreCallingIdentity(identity);
2604         }
2605 
2606         // First pass, find a number override for an active subscriber
2607         String mergeNumber = null;
2608         final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
2609         for (String key : prefs.keySet()) {
2610             if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
2611                 final String subscriberId = (String) prefs.get(key);
2612                 if (activeSubscriberIds.contains(subscriberId)) {
2613                     final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
2614                     final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2615                     mergeNumber = (String) prefs.get(numberKey);
2616                     if (DBG_MERGE) {
2617                         Slog.d(LOG_TAG, "Found line number " + mergeNumber
2618                                 + " for active subscriber " + subscriberId);
2619                     }
2620                     if (!TextUtils.isEmpty(mergeNumber)) {
2621                         break;
2622                     }
2623                 }
2624             }
2625         }
2626 
2627         // Shortcut when no active merged subscribers
2628         if (TextUtils.isEmpty(mergeNumber)) {
2629             return null;
2630         }
2631 
2632         // Second pass, find all subscribers under that line override
2633         final ArraySet<String> result = new ArraySet<>();
2634         for (String key : prefs.keySet()) {
2635             if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
2636                 final String number = (String) prefs.get(key);
2637                 if (mergeNumber.equals(number)) {
2638                     final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
2639                     final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2640                     final String subscriberId = (String) prefs.get(subscriberKey);
2641                     if (!TextUtils.isEmpty(subscriberId)) {
2642                         result.add(subscriberId);
2643                     }
2644                 }
2645             }
2646         }
2647 
2648         final String[] resultArray = result.toArray(new String[result.size()]);
2649         Arrays.sort(resultArray);
2650         if (DBG_MERGE) {
2651             Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
2652         }
2653         return resultArray;
2654     }
2655 
2656     @Override
setOperatorBrandOverride(int subId, String brand)2657     public boolean setOperatorBrandOverride(int subId, String brand) {
2658         enforceCarrierPrivilege(subId);
2659         final Phone phone = getPhone(subId);
2660         return phone == null ? false : phone.setOperatorBrandOverride(brand);
2661     }
2662 
2663     @Override
setRoamingOverride(int subId, List<String> gsmRoamingList, List<String> gsmNonRoamingList, List<String> cdmaRoamingList, List<String> cdmaNonRoamingList)2664     public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
2665             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2666             List<String> cdmaNonRoamingList) {
2667         enforceCarrierPrivilege(subId);
2668         final Phone phone = getPhone(subId);
2669         if (phone == null) {
2670             return false;
2671         }
2672         return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
2673                 cdmaNonRoamingList);
2674     }
2675 
2676     @Override
invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp)2677     public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2678         enforceModifyPermission();
2679 
2680         int returnValue = 0;
2681         try {
2682             AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2683             if(result.exception == null) {
2684                 if (result.result != null) {
2685                     byte[] responseData = (byte[])(result.result);
2686                     if(responseData.length > oemResp.length) {
2687                         Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2688                                 responseData.length +  "bytes. Buffer Size is " +
2689                                 oemResp.length + "bytes.");
2690                     }
2691                     System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2692                     returnValue = responseData.length;
2693                 }
2694             } else {
2695                 CommandException ex = (CommandException) result.exception;
2696                 returnValue = ex.getCommandError().ordinal();
2697                 if(returnValue > 0) returnValue *= -1;
2698             }
2699         } catch (RuntimeException e) {
2700             Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2701             returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2702             if(returnValue > 0) returnValue *= -1;
2703         }
2704 
2705         return returnValue;
2706     }
2707 
2708     @Override
setRadioCapability(RadioAccessFamily[] rafs)2709     public void setRadioCapability(RadioAccessFamily[] rafs) {
2710         try {
2711             ProxyController.getInstance().setRadioCapability(rafs);
2712         } catch (RuntimeException e) {
2713             Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
2714         }
2715     }
2716 
2717     @Override
getRadioAccessFamily(int phoneId, String callingPackage)2718     public int getRadioAccessFamily(int phoneId, String callingPackage) {
2719         if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
2720             return RadioAccessFamily.RAF_UNKNOWN;
2721         }
2722 
2723         return ProxyController.getInstance().getRadioAccessFamily(phoneId);
2724     }
2725 
2726     @Override
enableVideoCalling(boolean enable)2727     public void enableVideoCalling(boolean enable) {
2728         enforceModifyPermission();
2729         ImsManager.setVtSetting(mPhone.getContext(), enable);
2730     }
2731 
2732     @Override
isVideoCallingEnabled(String callingPackage)2733     public boolean isVideoCallingEnabled(String callingPackage) {
2734         if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
2735             return false;
2736         }
2737 
2738         // Check the user preference and the  system-level IMS setting. Even if the user has
2739         // enabled video calling, if IMS is disabled we aren't able to support video calling.
2740         // In the long run, we may instead need to check if there exists a connection service
2741         // which can support video calling.
2742         return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
2743                 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
2744                 && ImsManager.isVtEnabledByUser(mPhone.getContext());
2745     }
2746 
2747     @Override
canChangeDtmfToneLength()2748     public boolean canChangeDtmfToneLength() {
2749         return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
2750     }
2751 
2752     @Override
isWorldPhone()2753     public boolean isWorldPhone() {
2754         return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
2755     }
2756 
2757     @Override
isTtyModeSupported()2758     public boolean isTtyModeSupported() {
2759         TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
2760         TelephonyManager telephonyManager =
2761                 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
2762         return !telephonyManager.isMultiSimEnabled() && telecomManager.isTtySupported();
2763     }
2764 
2765     @Override
isHearingAidCompatibilitySupported()2766     public boolean isHearingAidCompatibilitySupported() {
2767         return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
2768     }
2769 
2770     /**
2771      * Returns the unique device ID of phone, for example, the IMEI for
2772      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
2773      *
2774      * <p>Requires Permission:
2775      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
2776      */
2777     @Override
getDeviceId(String callingPackage)2778     public String getDeviceId(String callingPackage) {
2779         if (!canReadPhoneState(callingPackage, "getDeviceId")) {
2780             return null;
2781         }
2782 
2783         final Phone phone = PhoneFactory.getPhone(0);
2784         if (phone != null) {
2785             return phone.getDeviceId();
2786         } else {
2787             return null;
2788         }
2789     }
2790 
2791     /*
2792      * {@hide}
2793      * Returns the IMS Registration Status
2794      */
2795     @Override
isImsRegistered()2796     public boolean isImsRegistered() {
2797         return mPhone.isImsRegistered();
2798     }
2799 
2800     @Override
getSubIdForPhoneAccount(PhoneAccount phoneAccount)2801     public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
2802         return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
2803     }
2804 
2805     /*
2806      * {@hide}
2807      * Returns the IMS Registration Status
2808      */
isWifiCallingAvailable()2809     public boolean isWifiCallingAvailable() {
2810         return mPhone.isWifiCallingEnabled();
2811     }
2812 
2813     /*
2814      * {@hide}
2815      * Returns the IMS Registration Status
2816      */
isVolteAvailable()2817     public boolean isVolteAvailable() {
2818         return mPhone.isVolteEnabled();
2819     }
2820 
2821     /*
2822      * {@hide} Returns the IMS Registration Status
2823      */
isVideoTelephonyAvailable()2824     public boolean isVideoTelephonyAvailable() {
2825         return mPhone.isVideoEnabled();
2826     }
2827 
canReadPhoneState(String callingPackage, String message)2828     private boolean canReadPhoneState(String callingPackage, String message) {
2829         try {
2830             mApp.enforceCallingOrSelfPermission(
2831                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
2832 
2833             // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
2834             return true;
2835         } catch (SecurityException e) {
2836             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
2837                     message);
2838         }
2839 
2840         if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
2841                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
2842             return false;
2843         }
2844 
2845         return true;
2846     }
2847 
2848     /**
2849      * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
2850      */
canReadPhoneNumber(String callingPackage, String message)2851     private boolean canReadPhoneNumber(String callingPackage, String message) {
2852         // Default SMS app can always read it.
2853         if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
2854                 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
2855             return true;
2856         }
2857         try {
2858             return canReadPhoneState(callingPackage, message);
2859         } catch (SecurityException readPhoneStateSecurityException) {
2860             try {
2861                 // Can be read with READ_SMS too.
2862                 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
2863                 return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
2864                         Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
2865             } catch (SecurityException readSmsSecurityException) {
2866                 // Throw exception with message including both READ_PHONE_STATE and READ_SMS
2867                 // permissions
2868                 throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
2869                         " nor current process has " + android.Manifest.permission.READ_PHONE_STATE +
2870                         " or " + android.Manifest.permission.READ_SMS + ".");
2871             }
2872         }
2873     }
2874 
2875     @Override
factoryReset(int subId)2876     public void factoryReset(int subId) {
2877         enforceConnectivityInternalPermission();
2878         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
2879             return;
2880         }
2881 
2882         final long identity = Binder.clearCallingIdentity();
2883         try {
2884             if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
2885                     UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
2886                 // Enable data
2887                 setDataEnabled(subId, true);
2888                 // Set network selection mode to automatic
2889                 setNetworkSelectionModeAutomatic(subId);
2890                 // Set preferred mobile network type to the best available
2891                 setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
2892                 // Turn off roaming
2893                 SubscriptionManager.from(mApp).setDataRoaming(0, subId);
2894             }
2895         } finally {
2896             Binder.restoreCallingIdentity(identity);
2897         }
2898     }
2899 
2900     @Override
getLocaleFromDefaultSim()2901     public String getLocaleFromDefaultSim() {
2902         // We query all subscriptions instead of just the active ones, because
2903         // this might be called early on in the provisioning flow when the
2904         // subscriptions potentially aren't active yet.
2905         final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
2906         if (slist == null || slist.isEmpty()) {
2907             return null;
2908         }
2909 
2910         // This function may be called very early, say, from the setup wizard, at
2911         // which point we won't have a default subscription set. If that's the case
2912         // we just choose the first, which will be valid in "most cases".
2913         final int defaultSubId = getDefaultSubscription();
2914         SubscriptionInfo info = null;
2915         if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2916             info = slist.get(0);
2917         } else {
2918             for (SubscriptionInfo item : slist) {
2919                 if (item.getSubscriptionId() == defaultSubId) {
2920                     info = item;
2921                     break;
2922                 }
2923             }
2924 
2925             if (info == null) {
2926                 return null;
2927             }
2928         }
2929 
2930         // Try and fetch the locale from the carrier properties or from the SIM language
2931         // preferences (EF-PL and EF-LI)...
2932         final int mcc = info.getMcc();
2933         final Phone defaultPhone = getPhone(info.getSubscriptionId());
2934         String simLanguage = null;
2935         if (defaultPhone != null) {
2936             final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
2937             if (localeFromDefaultSim != null) {
2938                 if (!localeFromDefaultSim.getCountry().isEmpty()) {
2939                     if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim);
2940                     return localeFromDefaultSim.toLanguageTag();
2941                 } else {
2942                     simLanguage = localeFromDefaultSim.getLanguage();
2943                 }
2944             }
2945         }
2946 
2947         // The SIM language preferences only store a language (e.g. fr = French), not an
2948         // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
2949         // the SIM and carrier preferences does not include a country we add the country
2950         // determined from the SIM MCC to provide an exact locale.
2951         final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage);
2952         if (mccLocale != null) {
2953             if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale);
2954             return mccLocale.toLanguageTag();
2955         }
2956 
2957         if (DBG) log("No locale found - returning null");
2958         return null;
2959     }
2960 
getAllSubscriptionInfoList()2961     private List<SubscriptionInfo> getAllSubscriptionInfoList() {
2962         final long identity = Binder.clearCallingIdentity();
2963         try {
2964             return mSubscriptionController.getAllSubInfoList(
2965                     mPhone.getContext().getOpPackageName());
2966         } finally {
2967             Binder.restoreCallingIdentity(identity);
2968         }
2969     }
2970 
getActiveSubscriptionInfoList()2971     private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
2972         final long identity = Binder.clearCallingIdentity();
2973         try {
2974             return mSubscriptionController.getActiveSubscriptionInfoList(
2975                     mPhone.getContext().getOpPackageName());
2976         } finally {
2977             Binder.restoreCallingIdentity(identity);
2978         }
2979     }
2980 
2981     /**
2982      * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
2983      * representing the state of the modem.
2984      *
2985      * NOTE: This clears the modem state, so there should only every be one caller.
2986      * @hide
2987      */
2988     @Override
requestModemActivityInfo(ResultReceiver result)2989     public void requestModemActivityInfo(ResultReceiver result) {
2990         enforceModifyPermission();
2991 
2992         ModemActivityInfo info = (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
2993         Bundle bundle = new Bundle();
2994         bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, info);
2995         result.send(0, bundle);
2996     }
2997 
2998     /**
2999      * {@hide}
3000      * Returns the service state information on specified subscription.
3001      */
3002     @Override
getServiceStateForSubscriber(int subId, String callingPackage)3003     public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
3004 
3005         if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
3006             return null;
3007         }
3008 
3009         final Phone phone = getPhone(subId);
3010         if (phone == null) {
3011             return null;
3012         }
3013 
3014         return phone.getServiceState();
3015     }
3016 
3017     /**
3018      * Returns the URI for the per-account voicemail ringtone set in Phone settings.
3019      *
3020      * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3021      * voicemail ringtone.
3022      * @return The URI for the ringtone to play when receiving a voicemail from a specific
3023      * PhoneAccount.
3024      */
3025     @Override
getVoicemailRingtoneUri(PhoneAccountHandle accountHandle)3026     public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
3027         final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3028         if (phone == null) {
3029             return null;
3030         }
3031 
3032         return VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
3033     }
3034 
3035     /**
3036      * Returns whether vibration is set for voicemail notification in Phone settings.
3037      *
3038      * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3039      * voicemail vibration setting.
3040      * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
3041      */
3042     @Override
isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle)3043     public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
3044         final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3045         if (phone == null) {
3046             return false;
3047         }
3048 
3049         return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone);
3050     }
3051 
3052 }
3053