• 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         final Phone defaultPhone = PhoneFactory.getDefaultPhone();
1406         if (defaultPhone != null) {
1407             defaultPhone.setRadioPower(turnOn);
1408             return true;
1409         } else {
1410             loge("There's no default phone.");
1411             return false;
1412         }
1413     }
1414 
setRadioPowerForSubscriber(int subId, boolean turnOn)1415     public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
1416         enforceModifyPermission();
1417         final Phone phone = getPhone(subId);
1418         if (phone != null) {
1419             phone.setRadioPower(turnOn);
1420             return true;
1421         } else {
1422             return false;
1423         }
1424     }
1425 
1426     // FIXME: subId version needed
1427     @Override
enableDataConnectivity()1428     public boolean enableDataConnectivity() {
1429         enforceModifyPermission();
1430         int subId = mSubscriptionController.getDefaultDataSubId();
1431         final Phone phone = getPhone(subId);
1432         if (phone != null) {
1433             phone.setDataEnabled(true);
1434             return true;
1435         } else {
1436             return false;
1437         }
1438     }
1439 
1440     // FIXME: subId version needed
1441     @Override
disableDataConnectivity()1442     public boolean disableDataConnectivity() {
1443         enforceModifyPermission();
1444         int subId = mSubscriptionController.getDefaultDataSubId();
1445         final Phone phone = getPhone(subId);
1446         if (phone != null) {
1447             phone.setDataEnabled(false);
1448             return true;
1449         } else {
1450             return false;
1451         }
1452     }
1453 
1454     // FIXME: subId version needed
1455     @Override
isDataConnectivityPossible()1456     public boolean isDataConnectivityPossible() {
1457         int subId = mSubscriptionController.getDefaultDataSubId();
1458         final Phone phone = getPhone(subId);
1459         if (phone != null) {
1460             return phone.isDataConnectivityPossible();
1461         } else {
1462             return false;
1463         }
1464     }
1465 
handlePinMmi(String dialString)1466     public boolean handlePinMmi(String dialString) {
1467         return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
1468     }
1469 
handlePinMmiForSubscriber(int subId, String dialString)1470     public boolean handlePinMmiForSubscriber(int subId, String dialString) {
1471         enforceModifyPermission();
1472         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1473             return false;
1474         }
1475         return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
1476     }
1477 
getCallState()1478     public int getCallState() {
1479         return getCallStateForSlot(getSlotForDefaultSubscription());
1480     }
1481 
getCallStateForSlot(int slotId)1482     public int getCallStateForSlot(int slotId) {
1483         Phone phone = PhoneFactory.getPhone(slotId);
1484         return phone == null ? TelephonyManager.CALL_STATE_IDLE :
1485             DefaultPhoneNotifier.convertCallState(phone.getState());
1486     }
1487 
1488     @Override
getDataState()1489     public int getDataState() {
1490         Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1491         if (phone != null) {
1492             return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
1493         } else {
1494             return DefaultPhoneNotifier.convertDataState(PhoneConstants.DataState.DISCONNECTED);
1495         }
1496     }
1497 
1498     @Override
getDataActivity()1499     public int getDataActivity() {
1500         Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1501         if (phone != null) {
1502             return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
1503         } else {
1504             return TelephonyManager.DATA_ACTIVITY_NONE;
1505         }
1506     }
1507 
1508     @Override
getCellLocation(String callingPackage)1509     public Bundle getCellLocation(String callingPackage) {
1510         enforceFineOrCoarseLocationPermission("getCellLocation");
1511 
1512         // OP_COARSE_LOCATION controls both fine and coarse location.
1513         if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1514                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1515             log("getCellLocation: returning null; mode != allowed");
1516             return null;
1517         }
1518 
1519         if (checkIfCallerIsSelfOrForegroundUser() ||
1520                 checkCallerInteractAcrossUsersFull()) {
1521             if (DBG_LOC) log("getCellLocation: is active user");
1522             Bundle data = new Bundle();
1523             Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1524             if (phone == null) {
1525                 return null;
1526             }
1527             phone.getCellLocation().fillInNotifierBundle(data);
1528             return data;
1529         } else {
1530             log("getCellLocation: suppress non-active user");
1531             return null;
1532         }
1533     }
1534 
enforceFineOrCoarseLocationPermission(String message)1535     private void enforceFineOrCoarseLocationPermission(String message) {
1536         try {
1537             mApp.enforceCallingOrSelfPermission(
1538                     android.Manifest.permission.ACCESS_FINE_LOCATION, null);
1539         } catch (SecurityException e) {
1540             // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
1541             // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
1542             // is the weaker precondition
1543             mApp.enforceCallingOrSelfPermission(
1544                     android.Manifest.permission.ACCESS_COARSE_LOCATION, message);
1545         }
1546     }
1547 
1548 
1549     @Override
enableLocationUpdates()1550     public void enableLocationUpdates() {
1551         enableLocationUpdatesForSubscriber(getDefaultSubscription());
1552     }
1553 
1554     @Override
enableLocationUpdatesForSubscriber(int subId)1555     public void enableLocationUpdatesForSubscriber(int subId) {
1556         mApp.enforceCallingOrSelfPermission(
1557                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
1558         final Phone phone = getPhone(subId);
1559         if (phone != null) {
1560             phone.enableLocationUpdates();
1561         }
1562     }
1563 
1564     @Override
disableLocationUpdates()1565     public void disableLocationUpdates() {
1566         disableLocationUpdatesForSubscriber(getDefaultSubscription());
1567     }
1568 
1569     @Override
disableLocationUpdatesForSubscriber(int subId)1570     public void disableLocationUpdatesForSubscriber(int subId) {
1571         mApp.enforceCallingOrSelfPermission(
1572                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
1573         final Phone phone = getPhone(subId);
1574         if (phone != null) {
1575             phone.disableLocationUpdates();
1576         }
1577     }
1578 
1579     @Override
1580     @SuppressWarnings("unchecked")
getNeighboringCellInfo(String callingPackage)1581     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
1582         enforceFineOrCoarseLocationPermission("getNeighboringCellInfo");
1583 
1584         // OP_COARSE_LOCATION controls both fine and coarse location.
1585         if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1586                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1587             return null;
1588         }
1589 
1590         if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
1591                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1592             return null;
1593         }
1594 
1595         if (checkIfCallerIsSelfOrForegroundUser() ||
1596                 checkCallerInteractAcrossUsersFull()) {
1597             if (DBG_LOC) log("getNeighboringCellInfo: is active user");
1598 
1599             ArrayList<NeighboringCellInfo> cells = null;
1600 
1601             try {
1602                 cells = (ArrayList<NeighboringCellInfo>) sendRequest(
1603                         CMD_HANDLE_NEIGHBORING_CELL, null,
1604                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
1605             } catch (RuntimeException e) {
1606                 Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
1607             }
1608             return cells;
1609         } else {
1610             if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
1611             return null;
1612         }
1613     }
1614 
1615 
1616     @Override
getAllCellInfo(String callingPackage)1617     public List<CellInfo> getAllCellInfo(String callingPackage) {
1618         enforceFineOrCoarseLocationPermission("getAllCellInfo");
1619 
1620         // OP_COARSE_LOCATION controls both fine and coarse location.
1621         if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
1622                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
1623             return null;
1624         }
1625 
1626         if (checkIfCallerIsSelfOrForegroundUser() ||
1627                 checkCallerInteractAcrossUsersFull()) {
1628             if (DBG_LOC) log("getAllCellInfo: is active user");
1629             List<CellInfo> cellInfos = new ArrayList<CellInfo>();
1630             for (Phone phone : PhoneFactory.getPhones()) {
1631                 final List<CellInfo> info = phone.getAllCellInfo();
1632                 if (info != null) cellInfos.addAll(phone.getAllCellInfo());
1633             }
1634             return cellInfos;
1635         } else {
1636             if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
1637             return null;
1638         }
1639     }
1640 
1641     @Override
setCellInfoListRate(int rateInMillis)1642     public void setCellInfoListRate(int rateInMillis) {
1643         enforceModifyPermission();
1644         mPhone.setCellInfoListRate(rateInMillis);
1645     }
1646 
1647     @Override
getImeiForSlot(int slotId, String callingPackage)1648     public String getImeiForSlot(int slotId, String callingPackage) {
1649       if (!canReadPhoneState(callingPackage, "getImeiForSlot")) {
1650           return null;
1651       }
1652       Phone phone = PhoneFactory.getPhone(slotId);
1653       return phone == null ? null : phone.getImei();
1654     }
1655 
1656     @Override
getDeviceSoftwareVersionForSlot(int slotId, String callingPackage)1657     public String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage) {
1658       if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) {
1659           return null;
1660       }
1661       Phone phone = PhoneFactory.getPhone(slotId);
1662       return phone == null ? null : phone.getDeviceSvn();
1663     }
1664 
1665     //
1666     // Internal helper methods.
1667     //
1668 
1669     /**
1670      * Returns true if the caller holds INTERACT_ACROSS_USERS_FULL.
1671      */
checkCallerInteractAcrossUsersFull()1672     private boolean checkCallerInteractAcrossUsersFull() {
1673         return mPhone.getContext().checkCallingOrSelfPermission(
1674                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1675                 == PackageManager.PERMISSION_GRANTED;
1676     }
1677 
checkIfCallerIsSelfOrForegroundUser()1678     private static boolean checkIfCallerIsSelfOrForegroundUser() {
1679         boolean ok;
1680 
1681         boolean self = Binder.getCallingUid() == Process.myUid();
1682         if (!self) {
1683             // Get the caller's user id then clear the calling identity
1684             // which will be restored in the finally clause.
1685             int callingUser = UserHandle.getCallingUserId();
1686             long ident = Binder.clearCallingIdentity();
1687 
1688             try {
1689                 // With calling identity cleared the current user is the foreground user.
1690                 int foregroundUser = ActivityManager.getCurrentUser();
1691                 ok = (foregroundUser == callingUser);
1692                 if (DBG_LOC) {
1693                     log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
1694                             + " callingUser=" + callingUser + " ok=" + ok);
1695                 }
1696             } catch (Exception ex) {
1697                 if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
1698                 ok = false;
1699             } finally {
1700                 Binder.restoreCallingIdentity(ident);
1701             }
1702         } else {
1703             if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
1704             ok = true;
1705         }
1706         if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
1707         return ok;
1708     }
1709 
1710     /**
1711      * Make sure the caller has the MODIFY_PHONE_STATE permission.
1712      *
1713      * @throws SecurityException if the caller does not have the required permission
1714      */
enforceModifyPermission()1715     private void enforceModifyPermission() {
1716         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
1717     }
1718 
1719     /**
1720      * Make sure either system app or the caller has carrier privilege.
1721      *
1722      * @throws SecurityException if the caller does not have the required permission/privilege
1723      */
enforceModifyPermissionOrCarrierPrivilege(int subId)1724     private void enforceModifyPermissionOrCarrierPrivilege(int subId) {
1725         int permission = mApp.checkCallingOrSelfPermission(
1726                 android.Manifest.permission.MODIFY_PHONE_STATE);
1727         if (permission == PackageManager.PERMISSION_GRANTED) {
1728             return;
1729         }
1730 
1731         log("No modify permission, check carrier privilege next.");
1732         enforceCarrierPrivilege(subId);
1733     }
1734 
1735     /**
1736      * Make sure the caller has carrier privilege.
1737      *
1738      * @throws SecurityException if the caller does not have the required permission
1739      */
enforceCarrierPrivilege(int subId)1740     private void enforceCarrierPrivilege(int subId) {
1741         if (getCarrierPrivilegeStatus(subId) !=
1742                     TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1743             loge("No Carrier Privilege.");
1744             throw new SecurityException("No Carrier Privilege.");
1745         }
1746     }
1747 
1748     /**
1749      * Make sure the caller has the CALL_PHONE permission.
1750      *
1751      * @throws SecurityException if the caller does not have the required permission
1752      */
enforceCallPermission()1753     private void enforceCallPermission() {
1754         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
1755     }
1756 
enforceConnectivityInternalPermission()1757     private void enforceConnectivityInternalPermission() {
1758         mApp.enforceCallingOrSelfPermission(
1759                 android.Manifest.permission.CONNECTIVITY_INTERNAL,
1760                 "ConnectivityService");
1761     }
1762 
createTelUrl(String number)1763     private String createTelUrl(String number) {
1764         if (TextUtils.isEmpty(number)) {
1765             return null;
1766         }
1767 
1768         return "tel:" + number;
1769     }
1770 
log(String msg)1771     private static void log(String msg) {
1772         Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
1773     }
1774 
logv(String msg)1775     private static void logv(String msg) {
1776         Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
1777     }
1778 
loge(String msg)1779     private static void loge(String msg) {
1780         Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
1781     }
1782 
1783     @Override
getActivePhoneType()1784     public int getActivePhoneType() {
1785         return getActivePhoneTypeForSlot(getSlotForDefaultSubscription());
1786     }
1787 
1788     @Override
getActivePhoneTypeForSlot(int slotId)1789     public int getActivePhoneTypeForSlot(int slotId) {
1790         final Phone phone = PhoneFactory.getPhone(slotId);
1791         if (phone == null) {
1792             return PhoneConstants.PHONE_TYPE_NONE;
1793         } else {
1794             return phone.getPhoneType();
1795         }
1796     }
1797 
1798     /**
1799      * Returns the CDMA ERI icon index to display
1800      */
1801     @Override
getCdmaEriIconIndex(String callingPackage)1802     public int getCdmaEriIconIndex(String callingPackage) {
1803         return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
1804     }
1805 
1806     @Override
getCdmaEriIconIndexForSubscriber(int subId, String callingPackage)1807     public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
1808         if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
1809             return -1;
1810         }
1811         final Phone phone = getPhone(subId);
1812         if (phone != null) {
1813             return phone.getCdmaEriIconIndex();
1814         } else {
1815             return -1;
1816         }
1817     }
1818 
1819     /**
1820      * Returns the CDMA ERI icon mode,
1821      * 0 - ON
1822      * 1 - FLASHING
1823      */
1824     @Override
getCdmaEriIconMode(String callingPackage)1825     public int getCdmaEriIconMode(String callingPackage) {
1826         return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
1827     }
1828 
1829     @Override
getCdmaEriIconModeForSubscriber(int subId, String callingPackage)1830     public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
1831         if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
1832             return -1;
1833         }
1834         final Phone phone = getPhone(subId);
1835         if (phone != null) {
1836             return phone.getCdmaEriIconMode();
1837         } else {
1838             return -1;
1839         }
1840     }
1841 
1842     /**
1843      * Returns the CDMA ERI text,
1844      */
1845     @Override
getCdmaEriText(String callingPackage)1846     public String getCdmaEriText(String callingPackage) {
1847         return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
1848     }
1849 
1850     @Override
getCdmaEriTextForSubscriber(int subId, String callingPackage)1851     public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
1852         if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
1853             return null;
1854         }
1855         final Phone phone = getPhone(subId);
1856         if (phone != null) {
1857             return phone.getCdmaEriText();
1858         } else {
1859             return null;
1860         }
1861     }
1862 
1863     /**
1864      * Returns the CDMA MDN.
1865      */
1866     @Override
getCdmaMdn(int subId)1867     public String getCdmaMdn(int subId) {
1868         enforceModifyPermissionOrCarrierPrivilege(subId);
1869         final Phone phone = getPhone(subId);
1870         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
1871             return phone.getLine1Number();
1872         } else {
1873             return null;
1874         }
1875     }
1876 
1877     /**
1878      * Returns the CDMA MIN.
1879      */
1880     @Override
getCdmaMin(int subId)1881     public String getCdmaMin(int subId) {
1882         enforceModifyPermissionOrCarrierPrivilege(subId);
1883         final Phone phone = getPhone(subId);
1884         if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1885             return phone.getCdmaMin();
1886         } else {
1887             return null;
1888         }
1889     }
1890 
1891     /**
1892      * Returns true if CDMA provisioning needs to run.
1893      */
needsOtaServiceProvisioning()1894     public boolean needsOtaServiceProvisioning() {
1895         return mPhone.needsOtaServiceProvisioning();
1896     }
1897 
1898     /**
1899      * Sets the voice mail number of a given subId.
1900      */
1901     @Override
setVoiceMailNumber(int subId, String alphaTag, String number)1902     public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
1903         enforceCarrierPrivilege(subId);
1904         Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
1905                 new Pair<String, String>(alphaTag, number), new Integer(subId));
1906         return success;
1907     }
1908 
1909     @Override
setVisualVoicemailEnabled(String callingPackage, PhoneAccountHandle phoneAccountHandle, boolean enabled)1910     public void setVisualVoicemailEnabled(String callingPackage,
1911             PhoneAccountHandle phoneAccountHandle, boolean enabled) {
1912         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1913         if (!TextUtils.equals(callingPackage,
1914                 TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
1915             enforceModifyPermissionOrCarrierPrivilege(
1916                     PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
1917         }
1918         VisualVoicemailSettingsUtil.setEnabled(mPhone.getContext(), phoneAccountHandle, enabled);
1919     }
1920 
1921     @Override
isVisualVoicemailEnabled(String callingPackage, PhoneAccountHandle phoneAccountHandle)1922     public boolean isVisualVoicemailEnabled(String callingPackage,
1923             PhoneAccountHandle phoneAccountHandle) {
1924         if (!canReadPhoneState(callingPackage, "isVisualVoicemailEnabled")) {
1925             return false;
1926         }
1927         return VisualVoicemailSettingsUtil.isEnabled(mPhone.getContext(), phoneAccountHandle);
1928     }
1929 
1930     @Override
enableVisualVoicemailSmsFilter(String callingPackage, int subId, VisualVoicemailSmsFilterSettings settings)1931     public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
1932             VisualVoicemailSmsFilterSettings settings) {
1933         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1934         VisualVoicemailSmsFilterConfig
1935                 .enableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId,
1936                         settings);
1937     }
1938 
1939     @Override
disableVisualVoicemailSmsFilter(String callingPackage, int subId)1940     public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
1941         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1942         VisualVoicemailSmsFilterConfig
1943                 .disableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId);
1944     }
1945 
1946     @Override
getVisualVoicemailSmsFilterSettings( String callingPackage, int subId)1947     public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
1948             String callingPackage, int subId) {
1949         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
1950         return VisualVoicemailSmsFilterConfig
1951                 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), callingPackage, subId);
1952     }
1953 
1954     @Override
getSystemVisualVoicemailSmsFilterSettings( String packageName, int subId)1955     public VisualVoicemailSmsFilterSettings getSystemVisualVoicemailSmsFilterSettings(
1956             String packageName, int subId) {
1957         enforceReadPrivilegedPermission();
1958         return VisualVoicemailSmsFilterConfig
1959                 .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), packageName, subId);
1960     }
1961     /**
1962      * Returns the unread count of voicemails
1963      */
getVoiceMessageCount()1964     public int getVoiceMessageCount() {
1965         return getVoiceMessageCountForSubscriber(getDefaultSubscription());
1966     }
1967 
1968     /**
1969      * Returns the unread count of voicemails for a subId
1970      */
1971     @Override
getVoiceMessageCountForSubscriber( int subId)1972     public int getVoiceMessageCountForSubscriber( int subId) {
1973         final Phone phone = getPhone(subId);
1974         if (phone != null) {
1975             return phone.getVoiceMessageCount();
1976         } else {
1977             return 0;
1978         }
1979     }
1980 
1981     /**
1982      * Returns the data network type.
1983      * Legacy call, permission-free.
1984      *
1985      * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
1986      */
1987     @Override
getNetworkType()1988     public int getNetworkType() {
1989         final Phone phone = getPhone(getDefaultSubscription());
1990         if (phone != null) {
1991             return phone.getServiceState().getDataNetworkType();
1992         } else {
1993             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1994         }
1995     }
1996 
1997     /**
1998      * Returns the network type for a subId
1999      */
2000     @Override
getNetworkTypeForSubscriber(int subId, String callingPackage)2001     public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
2002         if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
2003             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2004         }
2005 
2006         final Phone phone = getPhone(subId);
2007         if (phone != null) {
2008             return phone.getServiceState().getDataNetworkType();
2009         } else {
2010             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2011         }
2012     }
2013 
2014     /**
2015      * Returns the data network type
2016      */
2017     @Override
getDataNetworkType(String callingPackage)2018     public int getDataNetworkType(String callingPackage) {
2019         return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
2020     }
2021 
2022     /**
2023      * Returns the data network type for a subId
2024      */
2025     @Override
getDataNetworkTypeForSubscriber(int subId, String callingPackage)2026     public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
2027         if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2028             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2029         }
2030 
2031         final Phone phone = getPhone(subId);
2032         if (phone != null) {
2033             return phone.getServiceState().getDataNetworkType();
2034         } else {
2035             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2036         }
2037     }
2038 
2039     /**
2040      * Returns the Voice network type for a subId
2041      */
2042     @Override
getVoiceNetworkTypeForSubscriber(int subId, String callingPackage)2043     public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
2044         if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
2045             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2046         }
2047 
2048         final Phone phone = getPhone(subId);
2049         if (phone != null) {
2050             return phone.getServiceState().getVoiceNetworkType();
2051         } else {
2052             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
2053         }
2054     }
2055 
2056     /**
2057      * @return true if a ICC card is present
2058      */
hasIccCard()2059     public boolean hasIccCard() {
2060         // FIXME Make changes to pass defaultSimId of type int
2061         return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription()));
2062     }
2063 
2064     /**
2065      * @return true if a ICC card is present for a slotId
2066      */
2067     @Override
hasIccCardUsingSlotId(int slotId)2068     public boolean hasIccCardUsingSlotId(int slotId) {
2069         int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId);
2070         final Phone phone = getPhone(subId[0]);
2071         if (subId != null && phone != null) {
2072             return phone.getIccCard().hasIccCard();
2073         } else {
2074             return false;
2075         }
2076     }
2077 
2078     /**
2079      * Return if the current radio is LTE on CDMA. This
2080      * is a tri-state return value as for a period of time
2081      * the mode may be unknown.
2082      *
2083      * @param callingPackage the name of the package making the call.
2084      * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
2085      * or {@link Phone#LTE_ON_CDMA_TRUE}
2086      */
2087     @Override
getLteOnCdmaMode(String callingPackage)2088     public int getLteOnCdmaMode(String callingPackage) {
2089         return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
2090     }
2091 
2092     @Override
getLteOnCdmaModeForSubscriber(int subId, String callingPackage)2093     public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
2094         if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
2095             return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2096         }
2097 
2098         final Phone phone = getPhone(subId);
2099         if (phone == null) {
2100             return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
2101         } else {
2102             return phone.getLteOnCdmaMode();
2103         }
2104     }
2105 
setPhone(Phone phone)2106     public void setPhone(Phone phone) {
2107         mPhone = phone;
2108     }
2109 
2110     /**
2111      * {@hide}
2112      * Returns Default subId, 0 in the case of single standby.
2113      */
getDefaultSubscription()2114     private int getDefaultSubscription() {
2115         return mSubscriptionController.getDefaultSubId();
2116     }
2117 
getSlotForDefaultSubscription()2118     private int getSlotForDefaultSubscription() {
2119         return mSubscriptionController.getPhoneId(getDefaultSubscription());
2120     }
2121 
getPreferredVoiceSubscription()2122     private int getPreferredVoiceSubscription() {
2123         return mSubscriptionController.getDefaultVoiceSubId();
2124     }
2125 
2126     /**
2127      * @see android.telephony.TelephonyManager.WifiCallingChoices
2128      */
getWhenToMakeWifiCalls()2129     public int getWhenToMakeWifiCalls() {
2130         return Settings.System.getInt(mPhone.getContext().getContentResolver(),
2131                 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
2132     }
2133 
2134     /**
2135      * @see android.telephony.TelephonyManager.WifiCallingChoices
2136      */
setWhenToMakeWifiCalls(int preference)2137     public void setWhenToMakeWifiCalls(int preference) {
2138         if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
2139         Settings.System.putInt(mPhone.getContext().getContentResolver(),
2140                 Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
2141     }
2142 
getWhenToMakeWifiCallsDefaultPreference()2143     private static int getWhenToMakeWifiCallsDefaultPreference() {
2144         // TODO: Use a build property to choose this value.
2145         return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
2146     }
2147 
2148     @Override
iccOpenLogicalChannel(int subId, String AID)2149     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID) {
2150         enforceModifyPermissionOrCarrierPrivilege(subId);
2151 
2152         if (DBG) log("iccOpenLogicalChannel: subId=" + subId + " aid=" + AID);
2153         IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
2154             CMD_OPEN_CHANNEL, AID, subId);
2155         if (DBG) log("iccOpenLogicalChannel: " + response);
2156         return response;
2157     }
2158 
2159     @Override
iccCloseLogicalChannel(int subId, int channel)2160     public boolean iccCloseLogicalChannel(int subId, int channel) {
2161         enforceModifyPermissionOrCarrierPrivilege(subId);
2162 
2163         if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
2164         if (channel < 0) {
2165           return false;
2166         }
2167         Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel, subId);
2168         if (DBG) log("iccCloseLogicalChannel: " + success);
2169         return success;
2170     }
2171 
2172     @Override
iccTransmitApduLogicalChannel(int subId, int channel, int cla, int command, int p1, int p2, int p3, String data)2173     public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
2174             int command, int p1, int p2, int p3, String data) {
2175         enforceModifyPermissionOrCarrierPrivilege(subId);
2176 
2177         if (DBG) {
2178             log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel +
2179                     " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
2180                     " data=" + data);
2181         }
2182 
2183         if (channel < 0) {
2184             return "";
2185         }
2186 
2187         IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
2188                 new IccAPDUArgument(channel, cla, command, p1, p2, p3, data), subId);
2189         if (DBG) log("iccTransmitApduLogicalChannel: " + response);
2190 
2191         // Append the returned status code to the end of the response payload.
2192         String s = Integer.toHexString(
2193                 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2194         if (response.payload != null) {
2195             s = IccUtils.bytesToHexString(response.payload) + s;
2196         }
2197         return s;
2198     }
2199 
2200     @Override
iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2, int p3, String data)2201     public String iccTransmitApduBasicChannel(int subId, int cla, int command, int p1, int p2,
2202                 int p3, String data) {
2203         enforceModifyPermissionOrCarrierPrivilege(subId);
2204 
2205         if (DBG) {
2206             log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd=" + command
2207                     + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
2208         }
2209 
2210         IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
2211                 new IccAPDUArgument(0, cla, command, p1, p2, p3, data), subId);
2212         if (DBG) log("iccTransmitApduBasicChannel: " + response);
2213 
2214         // Append the returned status code to the end of the response payload.
2215         String s = Integer.toHexString(
2216                 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2217         if (response.payload != null) {
2218             s = IccUtils.bytesToHexString(response.payload) + s;
2219         }
2220         return s;
2221     }
2222 
2223     @Override
iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3, String filePath)2224     public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
2225             String filePath) {
2226         enforceModifyPermissionOrCarrierPrivilege(subId);
2227 
2228         if (DBG) {
2229             log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " +
2230                 p1 + " " + p2 + " " + p3 + ":" + filePath);
2231         }
2232 
2233         IccIoResult response =
2234             (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
2235                     new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath),
2236                     subId);
2237 
2238         if (DBG) {
2239           log("Exchange SIM_IO [R]" + response);
2240         }
2241 
2242         byte[] result = null;
2243         int length = 2;
2244         if (response.payload != null) {
2245             length = 2 + response.payload.length;
2246             result = new byte[length];
2247             System.arraycopy(response.payload, 0, result, 0, response.payload.length);
2248         } else {
2249             result = new byte[length];
2250         }
2251 
2252         result[length - 1] = (byte) response.sw2;
2253         result[length - 2] = (byte) response.sw1;
2254         return result;
2255     }
2256 
2257     @Override
sendEnvelopeWithStatus(int subId, String content)2258     public String sendEnvelopeWithStatus(int subId, String content) {
2259         enforceModifyPermissionOrCarrierPrivilege(subId);
2260 
2261         IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId);
2262         if (response.payload == null) {
2263           return "";
2264         }
2265 
2266         // Append the returned status code to the end of the response payload.
2267         String s = Integer.toHexString(
2268                 (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2269         s = IccUtils.bytesToHexString(response.payload) + s;
2270         return s;
2271     }
2272 
2273     /**
2274      * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2275      * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2276      *
2277      * @param itemID the ID of the item to read
2278      * @return the NV item as a String, or null on error.
2279      */
2280     @Override
nvReadItem(int itemID)2281     public String nvReadItem(int itemID) {
2282         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2283         if (DBG) log("nvReadItem: item " + itemID);
2284         String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
2285         if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
2286         return value;
2287     }
2288 
2289     /**
2290      * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2291      * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2292      *
2293      * @param itemID the ID of the item to read
2294      * @param itemValue the value to write, as a String
2295      * @return true on success; false on any failure
2296      */
2297     @Override
nvWriteItem(int itemID, String itemValue)2298     public boolean nvWriteItem(int itemID, String itemValue) {
2299         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2300         if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
2301         Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
2302                 new Pair<Integer, String>(itemID, itemValue));
2303         if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
2304         return success;
2305     }
2306 
2307     /**
2308      * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
2309      * Used for device configuration by some CDMA operators.
2310      *
2311      * @param preferredRoamingList byte array containing the new PRL
2312      * @return true on success; false on any failure
2313      */
2314     @Override
nvWriteCdmaPrl(byte[] preferredRoamingList)2315     public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
2316         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2317         if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
2318         Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
2319         if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
2320         return success;
2321     }
2322 
2323     /**
2324      * Perform the specified type of NV config reset.
2325      * Used for device configuration by some CDMA operators.
2326      *
2327      * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
2328      * @return true on success; false on any failure
2329      */
2330     @Override
nvResetConfig(int resetType)2331     public boolean nvResetConfig(int resetType) {
2332         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
2333         if (DBG) log("nvResetConfig: type " + resetType);
2334         Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
2335         if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
2336         return success;
2337     }
2338 
2339     /**
2340      * {@hide}
2341      * Returns Default sim, 0 in the case of single standby.
2342      */
getDefaultSim()2343     public int getDefaultSim() {
2344         //TODO Need to get it from Telephony Devcontroller
2345         return 0;
2346     }
2347 
getPcscfAddress(String apnType, String callingPackage)2348     public String[] getPcscfAddress(String apnType, String callingPackage) {
2349         if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
2350             return new String[0];
2351         }
2352 
2353 
2354         return mPhone.getPcscfAddress(apnType);
2355     }
2356 
setImsRegistrationState(boolean registered)2357     public void setImsRegistrationState(boolean registered) {
2358         enforceModifyPermission();
2359         mPhone.setImsRegistrationState(registered);
2360     }
2361 
2362     /**
2363      * Set the network selection mode to automatic.
2364      *
2365      */
2366     @Override
setNetworkSelectionModeAutomatic(int subId)2367     public void setNetworkSelectionModeAutomatic(int subId) {
2368         enforceModifyPermissionOrCarrierPrivilege(subId);
2369         if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
2370         sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
2371     }
2372 
2373     /**
2374      * Set the network selection mode to manual with the selected carrier.
2375      */
2376     @Override
setNetworkSelectionModeManual(int subId, OperatorInfo operator, boolean persistSelection)2377     public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
2378             boolean persistSelection) {
2379         enforceModifyPermissionOrCarrierPrivilege(subId);
2380         if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
2381         ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
2382                 persistSelection);
2383         return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
2384     }
2385 
2386     /**
2387      * Scans for available networks.
2388      */
2389     @Override
getCellNetworkScanResults(int subId)2390     public CellNetworkScanResult getCellNetworkScanResults(int subId) {
2391         enforceModifyPermissionOrCarrierPrivilege(subId);
2392         if (DBG) log("getCellNetworkScanResults: subId " + subId);
2393         CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
2394                 CMD_PERFORM_NETWORK_SCAN, null, subId);
2395         return result;
2396     }
2397 
2398     /**
2399      * Get the calculated preferred network type.
2400      * Used for debugging incorrect network type.
2401      *
2402      * @return the preferred network type, defined in RILConstants.java.
2403      */
2404     @Override
getCalculatedPreferredNetworkType(String callingPackage)2405     public int getCalculatedPreferredNetworkType(String callingPackage) {
2406         if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
2407             return RILConstants.PREFERRED_NETWORK_MODE;
2408         }
2409 
2410         return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
2411     }
2412 
2413     /**
2414      * Get the preferred network type.
2415      * Used for device configuration by some CDMA operators.
2416      *
2417      * @return the preferred network type, defined in RILConstants.java.
2418      */
2419     @Override
getPreferredNetworkType(int subId)2420     public int getPreferredNetworkType(int subId) {
2421         enforceModifyPermissionOrCarrierPrivilege(subId);
2422         if (DBG) log("getPreferredNetworkType");
2423         int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
2424         int networkType = (result != null ? result[0] : -1);
2425         if (DBG) log("getPreferredNetworkType: " + networkType);
2426         return networkType;
2427     }
2428 
2429     /**
2430      * Set the preferred network type.
2431      * Used for device configuration by some CDMA operators.
2432      *
2433      * @param networkType the preferred network type, defined in RILConstants.java.
2434      * @return true on success; false on any failure.
2435      */
2436     @Override
setPreferredNetworkType(int subId, int networkType)2437     public boolean setPreferredNetworkType(int subId, int networkType) {
2438         enforceModifyPermissionOrCarrierPrivilege(subId);
2439         if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
2440         Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
2441         if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
2442         if (success) {
2443             Settings.Global.putInt(mPhone.getContext().getContentResolver(),
2444                     Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
2445         }
2446         return success;
2447     }
2448 
2449     /**
2450      * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
2451      * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
2452      * tethering.
2453      *
2454      * @return 0: Not required. 1: required. 2: Not set.
2455      * @hide
2456      */
2457     @Override
getTetherApnRequired()2458     public int getTetherApnRequired() {
2459         enforceModifyPermission();
2460         int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2461                 Settings.Global.TETHER_DUN_REQUIRED, 2);
2462         // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2463         // config_tether_apndata.
2464         if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2465             dunRequired = 1;
2466         }
2467         return dunRequired;
2468     }
2469 
2470     /**
2471      * Set mobile data enabled
2472      * Used by the user through settings etc to turn on/off mobile data
2473      *
2474      * @param enable {@code true} turn turn data on, else {@code false}
2475      */
2476     @Override
setDataEnabled(int subId, boolean enable)2477     public void setDataEnabled(int subId, boolean enable) {
2478         enforceModifyPermission();
2479         int phoneId = mSubscriptionController.getPhoneId(subId);
2480         if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2481         Phone phone = PhoneFactory.getPhone(phoneId);
2482         if (phone != null) {
2483             if (DBG) log("setDataEnabled: subId=" + subId + " enable=" + enable);
2484             phone.setDataEnabled(enable);
2485         } else {
2486             loge("setDataEnabled: no phone for subId=" + subId);
2487         }
2488     }
2489 
2490     /**
2491      * Get whether mobile data is enabled.
2492      *
2493      * Note that this used to be available from ConnectivityService, gated by
2494      * ACCESS_NETWORK_STATE permission, so this will accept either that or
2495      * our MODIFY_PHONE_STATE.
2496      *
2497      * @return {@code true} if data is enabled else {@code false}
2498      */
2499     @Override
getDataEnabled(int subId)2500     public boolean getDataEnabled(int subId) {
2501         try {
2502             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2503                     null);
2504         } catch (Exception e) {
2505             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
2506                     null);
2507         }
2508         int phoneId = mSubscriptionController.getPhoneId(subId);
2509         if (DBG) log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2510         Phone phone = PhoneFactory.getPhone(phoneId);
2511         if (phone != null) {
2512             boolean retVal = phone.getDataEnabled();
2513             if (DBG) log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
2514             return retVal;
2515         } else {
2516             if (DBG) loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
2517             return false;
2518         }
2519     }
2520 
2521     @Override
getCarrierPrivilegeStatus(int subId)2522     public int getCarrierPrivilegeStatus(int subId) {
2523         final Phone phone = getPhone(subId);
2524         if (phone == null) {
2525             loge("getCarrierPrivilegeStatus: Invalid subId");
2526             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2527         }
2528         UiccCard card = UiccController.getInstance().getUiccCard(phone.getPhoneId());
2529         if (card == null) {
2530             loge("getCarrierPrivilegeStatus: No UICC");
2531             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2532         }
2533         return card.getCarrierPrivilegeStatusForCurrentTransaction(
2534                 phone.getContext().getPackageManager());
2535     }
2536 
2537     @Override
checkCarrierPrivilegesForPackage(String pkgName)2538     public int checkCarrierPrivilegesForPackage(String pkgName) {
2539         if (TextUtils.isEmpty(pkgName))
2540             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2541         UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
2542         if (card == null) {
2543             loge("checkCarrierPrivilegesForPackage: No UICC");
2544             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2545         }
2546         return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
2547     }
2548 
2549     @Override
checkCarrierPrivilegesForPackageAnyPhone(String pkgName)2550     public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
2551         if (TextUtils.isEmpty(pkgName))
2552             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2553         int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2554         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2555             UiccCard card = UiccController.getInstance().getUiccCard(i);
2556             if (card == null) {
2557               // No UICC in that slot.
2558               continue;
2559             }
2560 
2561             result = card.getCarrierPrivilegeStatus(
2562                 mPhone.getContext().getPackageManager(), pkgName);
2563             if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2564                 break;
2565             }
2566         }
2567 
2568         return result;
2569     }
2570 
2571     @Override
getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId)2572     public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2573         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2574             loge("phoneId " + phoneId + " is not valid.");
2575             return null;
2576         }
2577         UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
2578         if (card == null) {
2579             loge("getCarrierPackageNamesForIntent: No UICC");
2580             return null ;
2581         }
2582         return card.getCarrierPackageNamesForIntent(
2583                 mPhone.getContext().getPackageManager(), intent);
2584     }
2585 
2586     @Override
getPackagesWithCarrierPrivileges()2587     public List<String> getPackagesWithCarrierPrivileges() {
2588         PackageManager pm = mPhone.getContext().getPackageManager();
2589         List<String> privilegedPackages = new ArrayList<>();
2590         List<PackageInfo> packages = null;
2591         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
2592             UiccCard card = UiccController.getInstance().getUiccCard(i);
2593             if (card == null) {
2594                 // No UICC in that slot.
2595                 continue;
2596             }
2597             if (card.hasCarrierPrivilegeRules()) {
2598                 if (packages == null) {
2599                     // Only check packages in user 0 for now
2600                     packages = pm.getInstalledPackagesAsUser(
2601                             PackageManager.MATCH_DISABLED_COMPONENTS
2602                             | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
2603                             | PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
2604                 }
2605                 for (int p = packages.size() - 1; p >= 0; p--) {
2606                     PackageInfo pkgInfo = packages.get(p);
2607                     if (pkgInfo != null && pkgInfo.packageName != null
2608                             && card.getCarrierPrivilegeStatus(pkgInfo)
2609                                 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
2610                         privilegedPackages.add(pkgInfo.packageName);
2611                     }
2612                 }
2613             }
2614         }
2615         return privilegedPackages;
2616     }
2617 
getIccId(int subId)2618     private String getIccId(int subId) {
2619         final Phone phone = getPhone(subId);
2620         UiccCard card = phone == null ? null : phone.getUiccCard();
2621         if (card == null) {
2622             loge("getIccId: No UICC");
2623             return null;
2624         }
2625         String iccId = card.getIccId();
2626         if (TextUtils.isEmpty(iccId)) {
2627             loge("getIccId: ICC ID is null or empty.");
2628             return null;
2629         }
2630         return iccId;
2631     }
2632 
2633     @Override
setLine1NumberForDisplayForSubscriber(int subId, String alphaTag, String number)2634     public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
2635             String number) {
2636         enforceCarrierPrivilege(subId);
2637 
2638         final String iccId = getIccId(subId);
2639         final Phone phone = getPhone(subId);
2640         if (phone == null) {
2641             return false;
2642         }
2643         final String subscriberId = phone.getSubscriberId();
2644 
2645         if (DBG_MERGE) {
2646             Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
2647                     + subscriberId + " to " + number);
2648         }
2649 
2650         if (TextUtils.isEmpty(iccId)) {
2651             return false;
2652         }
2653 
2654         final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2655 
2656         final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2657         if (alphaTag == null) {
2658             editor.remove(alphaTagPrefKey);
2659         } else {
2660             editor.putString(alphaTagPrefKey, alphaTag);
2661         }
2662 
2663         // Record both the line number and IMSI for this ICCID, since we need to
2664         // track all merged IMSIs based on line number
2665         final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2666         final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2667         if (number == null) {
2668             editor.remove(numberPrefKey);
2669             editor.remove(subscriberPrefKey);
2670         } else {
2671             editor.putString(numberPrefKey, number);
2672             editor.putString(subscriberPrefKey, subscriberId);
2673         }
2674 
2675         editor.commit();
2676         return true;
2677     }
2678 
2679     @Override
getLine1NumberForDisplay(int subId, String callingPackage)2680     public String getLine1NumberForDisplay(int subId, String callingPackage) {
2681         // This is open to apps with WRITE_SMS.
2682         if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
2683             if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
2684             return null;
2685         }
2686 
2687         String iccId = getIccId(subId);
2688         if (iccId != null) {
2689             String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2690             if (DBG_MERGE) {
2691                 log("getLine1NumberForDisplay returning " +
2692                         mTelephonySharedPreferences.getString(numberPrefKey, null));
2693             }
2694             return mTelephonySharedPreferences.getString(numberPrefKey, null);
2695         }
2696         if (DBG_MERGE) log("getLine1NumberForDisplay returning null as iccId is null");
2697         return null;
2698     }
2699 
2700     @Override
getLine1AlphaTagForDisplay(int subId, String callingPackage)2701     public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2702         if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2703             return null;
2704         }
2705 
2706         String iccId = getIccId(subId);
2707         if (iccId != null) {
2708             String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2709             return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
2710         }
2711         return null;
2712     }
2713 
2714     @Override
getMergedSubscriberIds(String callingPackage)2715     public String[] getMergedSubscriberIds(String callingPackage) {
2716         if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
2717             return null;
2718         }
2719         final Context context = mPhone.getContext();
2720         final TelephonyManager tele = TelephonyManager.from(context);
2721         final SubscriptionManager sub = SubscriptionManager.from(context);
2722 
2723         // Figure out what subscribers are currently active
2724         final ArraySet<String> activeSubscriberIds = new ArraySet<>();
2725         // Clear calling identity, when calling TelephonyManager, because callerUid must be
2726         // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail.
2727         final long identity  = Binder.clearCallingIdentity();
2728         try {
2729             final int[] subIds = sub.getActiveSubscriptionIdList();
2730             for (int subId : subIds) {
2731                 activeSubscriberIds.add(tele.getSubscriberId(subId));
2732             }
2733         } finally {
2734             Binder.restoreCallingIdentity(identity);
2735         }
2736 
2737         // First pass, find a number override for an active subscriber
2738         String mergeNumber = null;
2739         final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
2740         for (String key : prefs.keySet()) {
2741             if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
2742                 final String subscriberId = (String) prefs.get(key);
2743                 if (activeSubscriberIds.contains(subscriberId)) {
2744                     final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
2745                     final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2746                     mergeNumber = (String) prefs.get(numberKey);
2747                     if (DBG_MERGE) {
2748                         Slog.d(LOG_TAG, "Found line number " + mergeNumber
2749                                 + " for active subscriber " + subscriberId);
2750                     }
2751                     if (!TextUtils.isEmpty(mergeNumber)) {
2752                         break;
2753                     }
2754                 }
2755             }
2756         }
2757 
2758         // Shortcut when no active merged subscribers
2759         if (TextUtils.isEmpty(mergeNumber)) {
2760             return null;
2761         }
2762 
2763         // Second pass, find all subscribers under that line override
2764         final ArraySet<String> result = new ArraySet<>();
2765         for (String key : prefs.keySet()) {
2766             if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
2767                 final String number = (String) prefs.get(key);
2768                 if (mergeNumber.equals(number)) {
2769                     final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
2770                     final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2771                     final String subscriberId = (String) prefs.get(subscriberKey);
2772                     if (!TextUtils.isEmpty(subscriberId)) {
2773                         result.add(subscriberId);
2774                     }
2775                 }
2776             }
2777         }
2778 
2779         final String[] resultArray = result.toArray(new String[result.size()]);
2780         Arrays.sort(resultArray);
2781         if (DBG_MERGE) {
2782             Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
2783         }
2784         return resultArray;
2785     }
2786 
2787     @Override
setOperatorBrandOverride(int subId, String brand)2788     public boolean setOperatorBrandOverride(int subId, String brand) {
2789         enforceCarrierPrivilege(subId);
2790         final Phone phone = getPhone(subId);
2791         return phone == null ? false : phone.setOperatorBrandOverride(brand);
2792     }
2793 
2794     @Override
setRoamingOverride(int subId, List<String> gsmRoamingList, List<String> gsmNonRoamingList, List<String> cdmaRoamingList, List<String> cdmaNonRoamingList)2795     public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
2796             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2797             List<String> cdmaNonRoamingList) {
2798         enforceCarrierPrivilege(subId);
2799         final Phone phone = getPhone(subId);
2800         if (phone == null) {
2801             return false;
2802         }
2803         return phone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
2804                 cdmaNonRoamingList);
2805     }
2806 
2807     @Override
invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp)2808     public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
2809         enforceModifyPermission();
2810 
2811         int returnValue = 0;
2812         try {
2813             AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
2814             if(result.exception == null) {
2815                 if (result.result != null) {
2816                     byte[] responseData = (byte[])(result.result);
2817                     if(responseData.length > oemResp.length) {
2818                         Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
2819                                 responseData.length +  "bytes. Buffer Size is " +
2820                                 oemResp.length + "bytes.");
2821                     }
2822                     System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
2823                     returnValue = responseData.length;
2824                 }
2825             } else {
2826                 CommandException ex = (CommandException) result.exception;
2827                 returnValue = ex.getCommandError().ordinal();
2828                 if(returnValue > 0) returnValue *= -1;
2829             }
2830         } catch (RuntimeException e) {
2831             Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
2832             returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
2833             if(returnValue > 0) returnValue *= -1;
2834         }
2835 
2836         return returnValue;
2837     }
2838 
2839     @Override
setRadioCapability(RadioAccessFamily[] rafs)2840     public void setRadioCapability(RadioAccessFamily[] rafs) {
2841         try {
2842             ProxyController.getInstance().setRadioCapability(rafs);
2843         } catch (RuntimeException e) {
2844             Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
2845         }
2846     }
2847 
2848     @Override
getRadioAccessFamily(int phoneId, String callingPackage)2849     public int getRadioAccessFamily(int phoneId, String callingPackage) {
2850         if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
2851             return RadioAccessFamily.RAF_UNKNOWN;
2852         }
2853 
2854         return ProxyController.getInstance().getRadioAccessFamily(phoneId);
2855     }
2856 
2857     @Override
enableVideoCalling(boolean enable)2858     public void enableVideoCalling(boolean enable) {
2859         enforceModifyPermission();
2860         ImsManager.setVtSetting(mPhone.getContext(), enable);
2861     }
2862 
2863     @Override
isVideoCallingEnabled(String callingPackage)2864     public boolean isVideoCallingEnabled(String callingPackage) {
2865         if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
2866             return false;
2867         }
2868 
2869         // Check the user preference and the  system-level IMS setting. Even if the user has
2870         // enabled video calling, if IMS is disabled we aren't able to support video calling.
2871         // In the long run, we may instead need to check if there exists a connection service
2872         // which can support video calling.
2873         return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
2874                 && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
2875                 && ImsManager.isVtEnabledByUser(mPhone.getContext());
2876     }
2877 
2878     @Override
canChangeDtmfToneLength()2879     public boolean canChangeDtmfToneLength() {
2880         return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
2881     }
2882 
2883     @Override
isWorldPhone()2884     public boolean isWorldPhone() {
2885         return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
2886     }
2887 
2888     @Override
isTtyModeSupported()2889     public boolean isTtyModeSupported() {
2890         TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
2891         TelephonyManager telephonyManager =
2892                 (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
2893         return telecomManager.isTtySupported();
2894     }
2895 
2896     @Override
isHearingAidCompatibilitySupported()2897     public boolean isHearingAidCompatibilitySupported() {
2898         return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
2899     }
2900 
2901     /**
2902      * Returns the unique device ID of phone, for example, the IMEI for
2903      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
2904      *
2905      * <p>Requires Permission:
2906      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
2907      */
2908     @Override
getDeviceId(String callingPackage)2909     public String getDeviceId(String callingPackage) {
2910         if (!canReadPhoneState(callingPackage, "getDeviceId")) {
2911             return null;
2912         }
2913 
2914         final Phone phone = PhoneFactory.getPhone(0);
2915         if (phone != null) {
2916             return phone.getDeviceId();
2917         } else {
2918             return null;
2919         }
2920     }
2921 
2922     /*
2923      * {@hide}
2924      * Returns the IMS Registration Status
2925      */
2926     @Override
isImsRegistered()2927     public boolean isImsRegistered() {
2928         return mPhone.isImsRegistered();
2929     }
2930 
2931     @Override
getSubIdForPhoneAccount(PhoneAccount phoneAccount)2932     public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
2933         return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
2934     }
2935 
2936     /*
2937      * {@hide}
2938      * Returns the IMS Registration Status
2939      */
isWifiCallingAvailable()2940     public boolean isWifiCallingAvailable() {
2941         return mPhone.isWifiCallingEnabled();
2942     }
2943 
2944     /*
2945      * {@hide}
2946      * Returns the IMS Registration Status
2947      */
isVolteAvailable()2948     public boolean isVolteAvailable() {
2949         return mPhone.isVolteEnabled();
2950     }
2951 
2952     /*
2953      * {@hide} Returns the IMS Registration Status
2954      */
isVideoTelephonyAvailable()2955     public boolean isVideoTelephonyAvailable() {
2956         return mPhone.isVideoEnabled();
2957     }
2958 
canReadPhoneState(String callingPackage, String message)2959     private boolean canReadPhoneState(String callingPackage, String message) {
2960         try {
2961             mApp.enforceCallingOrSelfPermission(
2962                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
2963 
2964             // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
2965             return true;
2966         } catch (SecurityException e) {
2967             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
2968                     message);
2969         }
2970 
2971         if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
2972                 callingPackage) != AppOpsManager.MODE_ALLOWED) {
2973             return false;
2974         }
2975 
2976         return true;
2977     }
2978 
2979     /**
2980      * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
2981      */
canReadPhoneNumber(String callingPackage, String message)2982     private boolean canReadPhoneNumber(String callingPackage, String message) {
2983         // Default SMS app can always read it.
2984         if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
2985                 Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
2986             return true;
2987         }
2988         try {
2989             return canReadPhoneState(callingPackage, message);
2990         } catch (SecurityException readPhoneStateSecurityException) {
2991             try {
2992                 // Can be read with READ_SMS too.
2993                 mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
2994                 return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
2995                         Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
2996             } catch (SecurityException readSmsSecurityException) {
2997                 // Throw exception with message including both READ_PHONE_STATE and READ_SMS
2998                 // permissions
2999                 throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
3000                         " nor current process has " + android.Manifest.permission.READ_PHONE_STATE +
3001                         " or " + android.Manifest.permission.READ_SMS + ".");
3002             }
3003         }
3004     }
3005 
3006     @Override
factoryReset(int subId)3007     public void factoryReset(int subId) {
3008         enforceConnectivityInternalPermission();
3009         if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
3010             return;
3011         }
3012 
3013         final long identity = Binder.clearCallingIdentity();
3014         try {
3015             if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
3016                     UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
3017                 // Enable data
3018                 setDataEnabled(subId, true);
3019                 // Set network selection mode to automatic
3020                 setNetworkSelectionModeAutomatic(subId);
3021                 // Set preferred mobile network type to the best available
3022                 setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
3023                 // Turn off roaming
3024                 SubscriptionManager.from(mApp).setDataRoaming(0, subId);
3025             }
3026         } finally {
3027             Binder.restoreCallingIdentity(identity);
3028         }
3029     }
3030 
3031     @Override
getLocaleFromDefaultSim()3032     public String getLocaleFromDefaultSim() {
3033         // We query all subscriptions instead of just the active ones, because
3034         // this might be called early on in the provisioning flow when the
3035         // subscriptions potentially aren't active yet.
3036         final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
3037         if (slist == null || slist.isEmpty()) {
3038             return null;
3039         }
3040 
3041         // This function may be called very early, say, from the setup wizard, at
3042         // which point we won't have a default subscription set. If that's the case
3043         // we just choose the first, which will be valid in "most cases".
3044         final int defaultSubId = getDefaultSubscription();
3045         SubscriptionInfo info = null;
3046         if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
3047             info = slist.get(0);
3048         } else {
3049             for (SubscriptionInfo item : slist) {
3050                 if (item.getSubscriptionId() == defaultSubId) {
3051                     info = item;
3052                     break;
3053                 }
3054             }
3055 
3056             if (info == null) {
3057                 return null;
3058             }
3059         }
3060 
3061         // Try and fetch the locale from the carrier properties or from the SIM language
3062         // preferences (EF-PL and EF-LI)...
3063         final int mcc = info.getMcc();
3064         final Phone defaultPhone = getPhone(info.getSubscriptionId());
3065         String simLanguage = null;
3066         if (defaultPhone != null) {
3067             final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
3068             if (localeFromDefaultSim != null) {
3069                 if (!localeFromDefaultSim.getCountry().isEmpty()) {
3070                     if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim);
3071                     return localeFromDefaultSim.toLanguageTag();
3072                 } else {
3073                     simLanguage = localeFromDefaultSim.getLanguage();
3074                 }
3075             }
3076         }
3077 
3078         // The SIM language preferences only store a language (e.g. fr = French), not an
3079         // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
3080         // the SIM and carrier preferences does not include a country we add the country
3081         // determined from the SIM MCC to provide an exact locale.
3082         final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage);
3083         if (mccLocale != null) {
3084             if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale);
3085             return mccLocale.toLanguageTag();
3086         }
3087 
3088         if (DBG) log("No locale found - returning null");
3089         return null;
3090     }
3091 
getAllSubscriptionInfoList()3092     private List<SubscriptionInfo> getAllSubscriptionInfoList() {
3093         final long identity = Binder.clearCallingIdentity();
3094         try {
3095             return mSubscriptionController.getAllSubInfoList(
3096                     mPhone.getContext().getOpPackageName());
3097         } finally {
3098             Binder.restoreCallingIdentity(identity);
3099         }
3100     }
3101 
getActiveSubscriptionInfoList()3102     private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
3103         final long identity = Binder.clearCallingIdentity();
3104         try {
3105             return mSubscriptionController.getActiveSubscriptionInfoList(
3106                     mPhone.getContext().getOpPackageName());
3107         } finally {
3108             Binder.restoreCallingIdentity(identity);
3109         }
3110     }
3111 
3112     /**
3113      * Responds to the ResultReceiver with the {@link android.telephony.ModemActivityInfo} object
3114      * representing the state of the modem.
3115      *
3116      * NOTE: This clears the modem state, so there should only every be one caller.
3117      * @hide
3118      */
3119     @Override
requestModemActivityInfo(ResultReceiver result)3120     public void requestModemActivityInfo(ResultReceiver result) {
3121         enforceModifyPermission();
3122 
3123         ModemActivityInfo info = (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
3124         Bundle bundle = new Bundle();
3125         bundle.putParcelable(TelephonyManager.MODEM_ACTIVITY_RESULT_KEY, info);
3126         result.send(0, bundle);
3127     }
3128 
3129     /**
3130      * {@hide}
3131      * Returns the service state information on specified subscription.
3132      */
3133     @Override
getServiceStateForSubscriber(int subId, String callingPackage)3134     public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
3135 
3136         if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
3137             return null;
3138         }
3139 
3140         final Phone phone = getPhone(subId);
3141         if (phone == null) {
3142             return null;
3143         }
3144 
3145         return phone.getServiceState();
3146     }
3147 
3148     /**
3149      * Returns the URI for the per-account voicemail ringtone set in Phone settings.
3150      *
3151      * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3152      * voicemail ringtone.
3153      * @return The URI for the ringtone to play when receiving a voicemail from a specific
3154      * PhoneAccount.
3155      */
3156     @Override
getVoicemailRingtoneUri(PhoneAccountHandle accountHandle)3157     public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
3158         final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3159         if (phone == null) {
3160             return null;
3161         }
3162 
3163         return VoicemailNotificationSettingsUtil.getRingtoneUri(phone);
3164     }
3165 
3166     /**
3167      * Returns whether vibration is set for voicemail notification in Phone settings.
3168      *
3169      * @param accountHandle The handle for the {@link PhoneAccount} for which to retrieve the
3170      * voicemail vibration setting.
3171      * @return {@code true} if the vibration is set for this PhoneAccount, {@code false} otherwise.
3172      */
3173     @Override
isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle)3174     public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
3175         final Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
3176         if (phone == null) {
3177             return false;
3178         }
3179 
3180         return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone);
3181     }
3182 
3183     /**
3184      * Make sure either called from same process as self (phone) or IPC caller has read privilege.
3185      *
3186      * @throws SecurityException if the caller does not have the required permission
3187      */
enforceReadPrivilegedPermission()3188     private void enforceReadPrivilegedPermission() {
3189         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
3190                 null);
3191     }
3192 
3193     /**
3194      * Return the application ID for the app type.
3195      *
3196      * @param subId the subscription ID that this request applies to.
3197      * @param appType the uicc app type.
3198      * @return Application ID for specificied app type, or null if no uicc.
3199      */
3200     @Override
getAidForAppType(int subId, int appType)3201     public String getAidForAppType(int subId, int appType) {
3202         enforceReadPrivilegedPermission();
3203         Phone phone = getPhone(subId);
3204         if (phone == null) {
3205             return null;
3206         }
3207         String aid = null;
3208         try {
3209             aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
3210                     .getApplicationByType(appType).getAid();
3211         } catch (Exception e) {
3212             Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
3213         }
3214         return aid;
3215     }
3216 
3217     /**
3218      * Return the Electronic Serial Number.
3219      *
3220      * @param subId the subscription ID that this request applies to.
3221      * @return ESN or null if error.
3222      */
3223     @Override
getEsn(int subId)3224     public String getEsn(int subId) {
3225         enforceReadPrivilegedPermission();
3226         Phone phone = getPhone(subId);
3227         if (phone == null) {
3228             return null;
3229         }
3230         String esn = null;
3231         try {
3232             esn = phone.getEsn();
3233         } catch (Exception e) {
3234             Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
3235         }
3236         return esn;
3237     }
3238 
3239     /**
3240      * Return the Preferred Roaming List Version.
3241      *
3242      * @param subId the subscription ID that this request applies to.
3243      * @return PRLVersion or null if error.
3244      */
3245     @Override
getCdmaPrlVersion(int subId)3246     public String getCdmaPrlVersion(int subId) {
3247         enforceReadPrivilegedPermission();
3248         Phone phone = getPhone(subId);
3249         if (phone == null) {
3250             return null;
3251         }
3252         String cdmaPrlVersion = null;
3253         try {
3254             cdmaPrlVersion = phone.getCdmaPrlVersion();
3255         } catch (Exception e) {
3256             Log.e(LOG_TAG, "Not getting PRLVersion", e);
3257         }
3258         return cdmaPrlVersion;
3259     }
3260 
3261     /**
3262      * Get snapshot of Telephony histograms
3263      * @return List of Telephony histograms
3264      * @hide
3265      */
3266     @Override
getTelephonyHistograms()3267     public List<TelephonyHistogram> getTelephonyHistograms() {
3268         enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
3269         return RIL.getTelephonyRILTimingHistograms();
3270     }
3271 
3272     /**
3273      * {@hide}
3274      * Set the allowed carrier list for slotId
3275      * Require system privileges. In the future we may add this to carrier APIs.
3276      *
3277      * @return The number of carriers set successfully, should match length of carriers
3278      */
3279     @Override
setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers)3280     public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
3281         enforceModifyPermission();
3282         int subId = SubscriptionManager.getSubId(slotId)[0];
3283         int[] retVal = (int[]) sendRequest(CMD_SET_ALLOWED_CARRIERS, carriers, subId);
3284         return retVal[0];
3285     }
3286 
3287     /**
3288      * {@hide}
3289      * Get the allowed carrier list for slotId.
3290      * Require system privileges. In the future we may add this to carrier APIs.
3291      *
3292      * @return List of {@link android.service.telephony.CarrierIdentifier}; empty list
3293      * means all carriers are allowed.
3294      */
3295     @Override
getAllowedCarriers(int slotId)3296     public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
3297         enforceReadPrivilegedPermission();
3298         int subId = SubscriptionManager.getSubId(slotId)[0];
3299         return (List<CarrierIdentifier>) sendRequest(CMD_GET_ALLOWED_CARRIERS, null, subId);
3300     }
3301 
3302     /**
3303      * Action set from carrier signalling broadcast receivers to enable/disable metered apns
3304      * @param subId the subscription ID that this action applies to.
3305      * @param enabled control enable or disable metered apns.
3306      * {@hide}
3307      */
3308     @Override
carrierActionSetMeteredApnsEnabled(int subId, boolean enabled)3309     public void carrierActionSetMeteredApnsEnabled(int subId, boolean enabled) {
3310         enforceModifyPermission();
3311         final Phone phone = getPhone(subId);
3312         if (phone == null) {
3313             loge("carrierAction: SetMeteredApnsEnabled fails with invalid subId: " + subId);
3314             return;
3315         }
3316         try {
3317             phone.carrierActionSetMeteredApnsEnabled(enabled);
3318         } catch (Exception e) {
3319             Log.e(LOG_TAG, "carrierAction: SetMeteredApnsEnabled fails. Exception ex=" + e);
3320         }
3321     }
3322 
3323     /**
3324      * Action set from carrier signalling broadcast receivers to enable/disable radio
3325      * @param subId the subscription ID that this action applies to.
3326      * @param enabled control enable or disable radio.
3327      * {@hide}
3328      */
3329     @Override
carrierActionSetRadioEnabled(int subId, boolean enabled)3330     public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
3331         enforceModifyPermission();
3332         final Phone phone = getPhone(subId);
3333         if (phone == null) {
3334             loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
3335             return;
3336         }
3337         try {
3338             phone.carrierActionSetRadioEnabled(enabled);
3339         } catch (Exception e) {
3340             Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
3341         }
3342     }
3343 
3344     /**
3345      * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
3346      * bug report is being generated.
3347      */
3348     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)3349     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
3350         if (mPhone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
3351                 != PackageManager.PERMISSION_GRANTED) {
3352             writer.println("Permission Denial: can't dump Phone from pid="
3353                     + Binder.getCallingPid()
3354                     + ", uid=" + Binder.getCallingUid()
3355                     + "without permission "
3356                     + android.Manifest.permission.DUMP);
3357             return;
3358         }
3359         DumpsysHandler.dump(mPhone.getContext(), fd, writer, args);
3360     }
3361 
3362     /**
3363      * Get aggregated video call data usage from all subscriptions since boot.
3364      * @return total data usage in bytes
3365      * {@hide}
3366      */
3367     @Override
getVtDataUsage()3368     public long getVtDataUsage() {
3369         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
3370                 null);
3371 
3372         // NetworkStatsService keeps tracking the active network interface and identity. It will
3373         // record the delta with the corresponding network identity. What we need to do here is
3374         // returning total video call data usage from all subscriptions since boot.
3375 
3376         // TODO: Add sub id support in the future. We'll need it when we support DSDA and
3377         // simultaneous VT calls.
3378         final Phone[] phones = PhoneFactory.getPhones();
3379         long total = 0;
3380         for (Phone phone : phones) {
3381             total += phone.getVtDataUsage();
3382         }
3383         return total;
3384     }
3385 
3386     /**
3387      * Policy control of data connection. Usually used when data limit is passed.
3388      * @param enabled True if enabling the data, otherwise disabling.
3389      * @param subId Subscription index
3390      * {@hide}
3391      */
3392     @Override
setPolicyDataEnabled(boolean enabled, int subId)3393     public void setPolicyDataEnabled(boolean enabled, int subId) {
3394         enforceModifyPermission();
3395         Phone phone = getPhone(subId);
3396         if (phone != null) {
3397             phone.setPolicyDataEnabled(enabled);
3398         }
3399     }
3400 }
3401