PhoneInterfaceManager.java revision d9eb7da8777390662732098edae8930fda567953
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
17package com.android.phone;
18
19import android.app.ActivityManager;
20import android.app.AppOpsManager;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.SharedPreferences;
25import android.content.pm.PackageManager;
26import android.net.Uri;
27import android.os.AsyncResult;
28import android.os.Binder;
29import android.os.Bundle;
30import android.os.Handler;
31import android.os.Looper;
32import android.os.Message;
33import android.os.Process;
34import android.os.ServiceManager;
35import android.os.UserHandle;
36import android.os.UserManager;
37import android.preference.PreferenceManager;
38import android.provider.Settings;
39import android.telecom.PhoneAccount;
40import android.telecom.TelecomManager;
41import android.telephony.CarrierConfigManager;
42import android.telephony.CellInfo;
43import android.telephony.IccOpenLogicalChannelResponse;
44import android.telephony.NeighboringCellInfo;
45import android.telephony.RadioAccessFamily;
46import android.telephony.ServiceState;
47import android.telephony.SubscriptionInfo;
48import android.telephony.SubscriptionManager;
49import android.telephony.TelephonyManager;
50import android.telephony.ModemActivityInfo;
51import android.text.TextUtils;
52import android.util.ArrayMap;
53import android.util.ArraySet;
54import android.util.Log;
55import android.util.Pair;
56import android.util.Slog;
57
58import com.android.ims.ImsManager;
59import com.android.internal.telephony.CallManager;
60import com.android.internal.telephony.CellNetworkScanResult;
61import com.android.internal.telephony.CommandException;
62import com.android.internal.telephony.DefaultPhoneNotifier;
63import com.android.internal.telephony.ITelephony;
64import com.android.internal.telephony.IccCard;
65import com.android.internal.telephony.MccTable;
66import com.android.internal.telephony.OperatorInfo;
67import com.android.internal.telephony.Phone;
68import com.android.internal.telephony.PhoneFactory;
69import com.android.internal.telephony.ProxyController;
70import com.android.internal.telephony.PhoneConstants;
71import com.android.internal.telephony.RILConstants;
72import com.android.internal.telephony.SubscriptionController;
73import com.android.internal.telephony.uicc.IccIoResult;
74import com.android.internal.telephony.uicc.IccUtils;
75import com.android.internal.telephony.uicc.UiccCard;
76import com.android.internal.telephony.uicc.UiccController;
77import com.android.internal.util.HexDump;
78
79import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
80
81import java.util.ArrayList;
82import java.util.Arrays;
83import java.util.HashMap;
84import java.util.Iterator;
85import java.util.List;
86import java.util.Locale;
87import java.util.Map;
88import java.util.Objects;
89
90/**
91 * Implementation of the ITelephony interface.
92 */
93public 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