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