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