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