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