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