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