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