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