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