PhoneInterfaceManager.java revision 646120a5b2c016a4528dab5372db94e027233fb3
17d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/*
27d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Copyright (C) 2006 The Android Open Source Project
37d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
47d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
57d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * you may not use this file except in compliance with the License.
67d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * You may obtain a copy of the License at
77d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
87d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
97d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Unless required by applicable law or agreed to in writing, software
117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * See the License for the specific language governing permissions and
147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * limitations under the License.
157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpackage com.android.phone;
187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.ActivityManager;
207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.AppOpsManager;
21bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepalimport android.content.ComponentName;
227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Context;
237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Intent;
247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.net.Uri;
257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Binder;
277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Bundle;
287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
2936ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.IBinder;
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Looper;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Process;
3336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.RemoteException;
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.ServiceManager;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.UserHandle;
36f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.provider.Settings;
377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.CellInfo;
38e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.telephony.NeighboringCellInfo;
397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.ServiceState;
40f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.telephony.TelephonyManager;
417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
43e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.util.Pair;
447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
45566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CallManager;
46566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CommandException;
4736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport com.android.internal.telephony.Connection;
487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.DefaultPhoneNotifier;
497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.ITelephony;
50e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.telephony.IccCard;
517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneConstants;
53566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccIoResult;
54566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
55566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
56e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.util.HexDump;
5736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport com.android.services.telephony.common.Call;
587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
6036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.HashMap;
6136ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Iterator;
62e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport java.util.List;
6336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Map;
647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Implementation of the ITelephony interface.
677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
68117fee7467c140dccdc66972f60031dae2d55b35Santos Cordonpublic class PhoneInterfaceManager extends ITelephony.Stub {
697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "PhoneInterfaceManager";
707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG_LOC = false;
727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message codes used with mMainThreadHandler
747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_PIN_MMI = 1;
757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_ANSWER_RINGING_CALL = 4;
787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_END_CALL = 5;  // not used yet
797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_SILENCE_RINGER = 6;
80566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_TRANSMIT_APDU = 7;
81566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_DONE = 8;
82566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_OPEN_CHANNEL = 9;
83566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_OPEN_CHANNEL_DONE = 10;
84566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_CLOSE_CHANNEL = 11;
85566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
86e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_READ_ITEM = 13;
87e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_READ_ITEM_DONE = 14;
88e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_ITEM = 15;
89e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
90e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_CDMA_PRL = 17;
91e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
92e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_RESET_CONFIG = 19;
93e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
947c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
957c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
967c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
977c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
9835b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int CMD_SEND_ENVELOPE = 25;
9935b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int EVENT_SEND_ENVELOPE_DONE = 26;
1007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The singleton instance. */
1027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static PhoneInterfaceManager sInstance;
1037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    PhoneGlobals mApp;
1057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    Phone mPhone;
1067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    CallManager mCM;
1077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    AppOpsManager mAppOps;
1087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    MainThreadHandler mMainThreadHandler;
109406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon    CallHandlerServiceProxy mCallHandlerService;
1107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
112566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * A request object to use for transmitting data to an ICC.
113566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
114566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final class IccAPDUArgument {
115566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public int channel, cla, command, p1, p2, p3;
116566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public String data;
117566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
118566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public IccAPDUArgument(int channel, int cla, int command,
119566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                int p1, int p2, int p3, String data) {
120566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.channel = channel;
121566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.cla = cla;
122566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.command = command;
123566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p1 = p1;
124566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p2 = p2;
125566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p3 = p3;
126566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.data = data;
127566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
128566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
129566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
130566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
1317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
1327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request after sending. The main thread will notify the request when it is complete.
1337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final class MainThreadRequest {
1357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The argument to use for the request */
1367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object argument;
1377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The result of the request that is run on the main thread */
1387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object result;
1397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public MainThreadRequest(Object argument) {
1417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            this.argument = argument;
1427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
145cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    private static final class IncomingThirdPartyCallArgs {
146cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final ComponentName component;
147cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callId;
148cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callerDisplayName;
149cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
150cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public IncomingThirdPartyCallArgs(ComponentName component, String callId,
151cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal                String callerDisplayName) {
152cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.component = component;
153cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callId = callId;
154cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callerDisplayName = callerDisplayName;
155cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        }
156cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    }
157cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
1587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A handler that processes messages on the main thread in the phone process. Since many
1607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
1617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * inbound binder threads to the main thread in the phone process.  The Binder thread
1627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * on, which will be notified when the operation completes and will contain the result of the
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request.
1657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
1667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * <p>If a MainThreadRequest object is provided in the msg.obj field,
1677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * note that request.result must be set to something non-null for the calling thread to
1687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * unblock.
1697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final class MainThreadHandler extends Handler {
1717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
1727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
1737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            MainThreadRequest request;
1747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message onCompleted;
1757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar;
1767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
1787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_PIN_MMI:
1797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
180e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request.result = mPhone.handlePinMmi((String) request.argument);
1817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
1827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
1837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
1847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
1857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
1867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_NEIGHBORING_CELL:
1887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
1897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
1907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            request);
1917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mPhone.getNeighboringCids(onCompleted);
1927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NEIGHBORING_CELL_DONE:
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    ar = (AsyncResult) msg.obj;
1967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) ar.userObj;
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (ar.exception == null && ar.result != null) {
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.result = ar.result;
1997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // create an empty list to notify the waiting thread
201e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = new ArrayList<NeighboringCellInfo>(0);
2027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_ANSWER_RINGING_CALL:
2107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    answerRingingCallInternal();
2117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_SILENCE_RINGER:
2147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    silenceRingerInternal();
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_END_CALL:
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
219e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    boolean hungUp;
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    int phoneType = mPhone.getPhoneType();
2217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
2227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // CDMA: If the user presses the Power button we treat it as
2237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // ending the complete call session
2247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
2257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
2267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // GSM: End the call as per the Phone state
2277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangup(mCM);
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
2327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.result = hungUp;
2337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
239566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_TRANSMIT_APDU:
240566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
241566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    IccAPDUArgument argument = (IccAPDUArgument) request.argument;
242566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_DONE, request);
243566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    UiccController.getInstance().getUiccCard().iccTransmitApduLogicalChannel(
244566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            argument.channel, argument.cla, argument.command,
245566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            argument.p1, argument.p2, argument.p3, argument.data,
246566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
247566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
248566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
249566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_TRANSMIT_APDU_DONE:
250566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
251566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
252566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
253566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = ar.result;
254566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
255566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
256566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
257566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Empty response");
258e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
259566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: CommandException: " +
260e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
261566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
262566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Unknown exception");
263566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
264566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
265566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
266566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
267566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
268566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
269566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
2704d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case CMD_SEND_ENVELOPE:
2714d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) msg.obj;
2724d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
2739f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    UiccController.getInstance().getUiccCard().sendEnvelopeWithStatus(
2744d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                            (String)request.argument, onCompleted);
2754d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
2764d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
2774d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case EVENT_SEND_ENVELOPE_DONE:
2784d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    ar = (AsyncResult) msg.obj;
2794d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) ar.userObj;
2809f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    if (ar.exception == null && ar.result != null) {
2819f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = ar.result;
2824d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    } else {
2839f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
2849f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        if (ar.result == null) {
2859f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: Empty response");
2869f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else if (ar.exception instanceof CommandException) {
2879f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: CommandException: " +
2889f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                                    ar.exception);
2899f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else {
2909f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: exception:" + ar.exception);
2919f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        }
2924d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
2934d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    synchronized (request) {
2944d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                        request.notifyAll();
2954d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
2964d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
2974d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
298566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_OPEN_CHANNEL:
299566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
300566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
301566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    UiccController.getInstance().getUiccCard().iccOpenLogicalChannel(
302566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            (String)request.argument, onCompleted);
303566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
304566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
305566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_OPEN_CHANNEL_DONE:
306566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
307566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
308566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
309e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ((int[]) ar.result)[0];
310566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
311e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = -1;
312566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
313566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Empty response");
314e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
315566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: CommandException: " +
316e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
317566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
318566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Unknown exception");
319566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
320566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
321566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
322566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
323566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
324566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
325566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
326566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_CLOSE_CHANNEL:
327566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
328566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE,
329566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            request);
330566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    UiccController.getInstance().getUiccCard().iccCloseLogicalChannel(
331e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            (Integer) request.argument,
332566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
333566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
334566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
335566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_CLOSE_CHANNEL_DONE:
336e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "iccCloseLogicalChannel");
337e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
338e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
339e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_READ_ITEM:
340e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
341e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
342e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvReadItem((Integer) request.argument, onCompleted);
343e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
344e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
345e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_READ_ITEM_DONE:
346566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
347566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
348e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    if (ar.exception == null && ar.result != null) {
349e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ar.result;     // String
350566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
351e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = "";
352e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        if (ar.result == null) {
353e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Empty response");
354e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
355e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: CommandException: " +
356e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
357566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
358e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Unknown exception");
359566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
360566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
361566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
362566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
363566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
364566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
365566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
366e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_ITEM:
367e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
368e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
369e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
370e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
371e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
372e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
373e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_ITEM_DONE:
374e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteItem");
375e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
376e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
377e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_CDMA_PRL:
378e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
379e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
380e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
381e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
382e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
383e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_CDMA_PRL_DONE:
384e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteCdmaPrl");
385e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
386e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
387e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_RESET_CONFIG:
388e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
389e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
390e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
391e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
392e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
393e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_RESET_CONFIG_DONE:
394e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvResetConfig");
395e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
396e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
3977c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_GET_PREFERRED_NETWORK_TYPE:
3987c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
3997c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
4007c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.getPreferredNetworkType(onCompleted);
4017c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4027c27be317e8757948178815426d3a329c852b9eeJake Hamby
4037c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
4047c27be317e8757948178815426d3a329c852b9eeJake Hamby                    ar = (AsyncResult) msg.obj;
4057c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) ar.userObj;
4067c27be317e8757948178815426d3a329c852b9eeJake Hamby                    if (ar.exception == null && ar.result != null) {
4077c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = ar.result;     // Integer
4087c27be317e8757948178815426d3a329c852b9eeJake Hamby                    } else {
4097c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = -1;
4107c27be317e8757948178815426d3a329c852b9eeJake Hamby                        if (ar.result == null) {
4117c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Empty response");
4127c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else if (ar.exception instanceof CommandException) {
4137c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: CommandException: " +
4147c27be317e8757948178815426d3a329c852b9eeJake Hamby                                    ar.exception);
4157c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else {
4167c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Unknown exception");
4177c27be317e8757948178815426d3a329c852b9eeJake Hamby                        }
4187c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
4197c27be317e8757948178815426d3a329c852b9eeJake Hamby                    synchronized (request) {
4207c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.notifyAll();
4217c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
4227c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4237c27be317e8757948178815426d3a329c852b9eeJake Hamby
4247c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_SET_PREFERRED_NETWORK_TYPE:
4257c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
4267c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
4277c27be317e8757948178815426d3a329c852b9eeJake Hamby                    int networkType = (Integer) request.argument;
4287c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.setPreferredNetworkType(networkType, onCompleted);
4297c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4307c27be317e8757948178815426d3a329c852b9eeJake Hamby
4317c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
4327c27be317e8757948178815426d3a329c852b9eeJake Hamby                    handleNullReturnEvent(msg, "setPreferredNetworkType");
4337c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4347c27be317e8757948178815426d3a329c852b9eeJake Hamby
4357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                default:
4367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
4377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
4387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
4397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
440e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
441e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        private void handleNullReturnEvent(Message msg, String command) {
442e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            AsyncResult ar = (AsyncResult) msg.obj;
443e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            MainThreadRequest request = (MainThreadRequest) ar.userObj;
444e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            if (ar.exception == null) {
445e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = true;
446e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            } else {
447e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = false;
448e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                if (ar.exception instanceof CommandException) {
449e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": CommandException: " + ar.exception);
450e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                } else {
451e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": Unknown exception");
452e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                }
453e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
454e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            synchronized (request) {
455e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.notifyAll();
456e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
457e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        }
4587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
4597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
4617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread,
4627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * waits for the request to complete, and returns the result.
4637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequestAsync
4647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
4657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Object sendRequest(int command, Object argument) {
4667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
4677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            throw new RuntimeException("This method will deadlock if called from the main thread.");
4687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
4697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        MainThreadRequest request = new MainThreadRequest(argument);
4717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Message msg = mMainThreadHandler.obtainMessage(command, request);
4727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        msg.sendToTarget();
4737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Wait for the request to complete
4757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (request) {
4767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (request.result == null) {
4777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
4787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.wait();
4797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
4807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Do nothing, go back and wait until the request is complete
4817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
4827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
4837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
4847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return request.result;
4857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
4867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
4887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Asynchronous ("fire and forget") version of sendRequest():
4897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread, and
4907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * returns immediately.
4917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequest
4927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
4937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void sendRequestAsync(int command) {
4947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler.sendEmptyMessage(command);
4957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
4967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
4977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
498bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * Same as {@link #sendRequestAsync(int)} except it takes an argument.
499bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * @see {@link #sendRequest(int,Object)}
500bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     */
501bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    private void sendRequestAsync(int command, Object argument) {
502bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        MainThreadRequest request = new MainThreadRequest(argument);
503bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        Message msg = mMainThreadHandler.obtainMessage(command, request);
504bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        msg.sendToTarget();
505bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    }
506bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal
507bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    /**
5087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton PhoneInterfaceManager instance.
5097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
5107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
511406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone,
512117fee7467c140dccdc66972f60031dae2d55b35Santos Cordon                CallHandlerServiceProxy callHandlerService) {
5137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (PhoneInterfaceManager.class) {
5147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
515117fee7467c140dccdc66972f60031dae2d55b35Santos Cordon                sInstance = new PhoneInterfaceManager(app, phone, callHandlerService);
5167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
5177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
5187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
5197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
5207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** Private constructor; @see init() */
524406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon    private PhoneInterfaceManager(PhoneGlobals app, Phone phone,
525117fee7467c140dccdc66972f60031dae2d55b35Santos Cordon            CallHandlerServiceProxy callHandlerService) {
5267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
5277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = phone;
5287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mCM = PhoneGlobals.getInstance().mCM;
5297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
5307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler = new MainThreadHandler();
531406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon        mCallHandlerService = callHandlerService;
5327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        publish();
5337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void publish() {
5367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("publish: " + this);
5377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        ServiceManager.addService("phone", this);
5397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
5427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Implementation of the ITelephony interface.
5437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
5447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void dial(String number) {
5467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("dial: " + number);
5477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: This is just a wrapper around the
5487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // ACTION_DIAL intent, which is available to any app since it puts up
5497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // the UI before it does anything.
5507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
5527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
5537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
5547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // PENDING: should we just silently fail if phone is offhook or ringing?
5577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        PhoneConstants.State state = mCM.getState();
5587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
5597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
5607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
5617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.startActivity(intent);
5627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void call(String callingPackage, String number) {
5667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("call: " + number);
5677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // This is just a wrapper around the ACTION_CALL intent, but we still
5697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // need to do a permission check since we're calling startActivity()
5707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // from the context of the phone app.
5717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
5727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
5747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                != AppOpsManager.MODE_ALLOWED) {
5757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
5767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
5797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
5807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
5817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
5847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
5857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.startActivity(intent);
5867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private boolean showCallScreenInternal(boolean specifyInitialDialpadState,
589bcf2099b92870b863f53e79288d4c8e73a4dc42dMakoto Onuki                                           boolean showDialpad) {
5907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!PhoneGlobals.sVoiceCapable) {
5917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Never allow the InCallScreen to appear on data-only devices.
5927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return false;
5937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (isIdle()) {
5957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return false;
5967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // If the phone isn't idle then go to the in-call screen
5987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        long callingId = Binder.clearCallingIdentity();
599406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon
600bcf2099b92870b863f53e79288d4c8e73a4dc42dMakoto Onuki        mCallHandlerService.bringToForeground(showDialpad);
601406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon
602406c0341600bd414fe7561b4edd8cdf7ed11f315Santos Cordon        Binder.restoreCallingIdentity(callingId);
6037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
6047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Show the in-call screen without specifying the initial dialpad state.
6077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean showCallScreen() {
6087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return showCallScreenInternal(false, false);
6097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // The variation of showCallScreen() that specifies the initial dialpad state.
6127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // (Ideally this would be called showCallScreen() too, just with a different
6137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // signature, but AIDL doesn't allow that.)
6147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean showCallScreenWithDialpad(boolean showDialpad) {
6157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return showCallScreenInternal(true, showDialpad);
6167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * End a call based on call state
6207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true is a call was ended
6217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean endCall() {
6237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
6247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (Boolean) sendRequest(CMD_END_CALL, null);
6257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void answerRingingCall() {
6287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("answerRingingCall...");
6297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
6307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // but that can probably wait till the big TelephonyManager API overhaul.
6317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.
6327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
6337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_ANSWER_RINGING_CALL);
6347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make the actual telephony calls to implement answerRingingCall().
6387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
6397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #answerRingingCall
6407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
6417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: it would be nice to return true if we answered the call, or
6427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * false if there wasn't actually a ringing incoming call, or some
6437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * other error occurred.  (In other words, pass back the return value
6447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
6457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * But that would require calling this method via sendRequest() rather
6467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * than sendRequestAsync(), and right now we don't actually *need* that
6477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * return value, so let's just return void for now.
6487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void answerRingingCallInternal() {
6507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final boolean hasRingingCall = !mPhone.getRingingCall().isIdle();
6517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (hasRingingCall) {
6527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasActiveCall = !mPhone.getForegroundCall().isIdle();
6537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasHoldingCall = !mPhone.getBackgroundCall().isIdle();
6547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (hasActiveCall && hasHoldingCall) {
6557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Both lines are in use!
6567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // TODO: provide a flag to let the caller specify what
6577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // policy to use if both lines are in use.  (The current
6587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // behavior is hardwired to "answer incoming, end ongoing",
6597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // which is how the CALL button is specced to behave.)
6607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
6617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
6627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
6637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // answerCall() will automatically hold the current active
6647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // call, if there is one.
6657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
6667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
6677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
6697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // No call was ringing.
6707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
6717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void silenceRinger() {
6757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("silenceRinger...");
6767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: find a more appropriate permission to check here.
6777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // (That can probably wait till the big TelephonyManager API overhaul.
6787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.)
6797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
6807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_SILENCE_RINGER);
6817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Internal implemenation of silenceRinger().
6857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
6867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #silenceRinger
6877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void silenceRingerInternal() {
6897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if ((mCM.getState() == PhoneConstants.State.RINGING)
6907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            && mApp.notifier.isRinging()) {
6917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Ringer is actually playing, so silence it.
6927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG) log("silenceRingerInternal: silencing...");
6937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.notifier.silenceRinger();
6947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isOffhook() {
6987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (mCM.getState() == PhoneConstants.State.OFFHOOK);
6997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRinging() {
7027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (mCM.getState() == PhoneConstants.State.RINGING);
7037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isIdle() {
7067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (mCM.getState() == PhoneConstants.State.IDLE);
7077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isSimPinEnabled() {
7107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceReadPermission();
7117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (PhoneGlobals.getInstance().isSimPinEnabled());
7127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean supplyPin(String pin) {
7159de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        int [] resultArray = supplyPinReportResult(pin);
7169de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
7179de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
7189de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
7199de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public boolean supplyPuk(String puk, String pin) {
7209de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        int [] resultArray = supplyPukReportResult(puk, pin);
7219de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
7229de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
7239de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
7249de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
7259de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPinReportResult(String pin) {
7267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
7277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final UnlockSim checkSimPin = new UnlockSim(mPhone.getIccCard());
7287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPin.start();
7297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPin.unlockSim(null, pin);
7307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7329de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
7339de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPukReportResult(String puk, String pin) {
7347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
7357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final UnlockSim checkSimPuk = new UnlockSim(mPhone.getIccCard());
7367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPuk.start();
7377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPuk.unlockSim(puk, pin);
7387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7419de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville     * Helper thread to turn async call to SimCard#supplyPin into
7427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * a synchronous one.
7437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static class UnlockSim extends Thread {
7457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private final IccCard mSimCard;
7477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private boolean mDone = false;
7499de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
7509de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mRetryCount = -1;
7517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For replies from SimCard interface
7537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private Handler mHandler;
7547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For async handler to identify request type
7567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private static final int SUPPLY_PIN_COMPLETE = 100;
7577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public UnlockSim(IccCard simCard) {
7597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mSimCard = simCard;
7607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
7637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void run() {
7647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.prepare();
7657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            synchronized (UnlockSim.this) {
7667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mHandler = new Handler() {
7677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    @Override
7687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    public void handleMessage(Message msg) {
7697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        AsyncResult ar = (AsyncResult) msg.obj;
7707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        switch (msg.what) {
7717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            case SUPPLY_PIN_COMPLETE:
7727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
7737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                synchronized (UnlockSim.this) {
7749de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    mRetryCount = msg.arg1;
7759de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    if (ar.exception != null) {
7769de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        if (ar.exception instanceof CommandException &&
7779de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                ((CommandException)(ar.exception)).getCommandError()
7789de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                == CommandException.Error.PASSWORD_INCORRECT) {
7799de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
7809de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        } else {
7819de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_GENERAL_FAILURE;
7829de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        }
7839de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    } else {
7849de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        mResult = PhoneConstants.PIN_RESULT_SUCCESS;
7859de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    }
7867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mDone = true;
7877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    UnlockSim.this.notifyAll();
7887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
7897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                break;
7907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
7917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
7927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                };
7937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                UnlockSim.this.notifyAll();
7947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
7957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.loop();
7967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /*
7997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Use PIN or PUK to unlock SIM card
8007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
8017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is null, unlock SIM card with PIN
8027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
8037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is not null, unlock SIM card with PUK and set PIN code
8047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
8059de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        synchronized int[] unlockSim(String puk, String pin) {
8067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (mHandler == null) {
8087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
8097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
8107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
8117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
8127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
8137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
8157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (puk == null) {
8177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPin(pin, callback);
8187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
8197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPuk(puk, pin, callback);
8207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (!mDone) {
8237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
8247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.d(LOG_TAG, "wait for done");
8257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
8267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
8277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Restore the interrupted status
8287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
8297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
8307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Log.d(LOG_TAG, "done");
8329de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            int[] resultArray = new int[2];
8339de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[0] = mResult;
8349de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[1] = mRetryCount;
8359de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            return resultArray;
8367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void updateServiceLocation() {
8407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: this call is harmless, and it's
8417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // needed for the ServiceState.requestStateUpdate() call (which is
8427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // already intentionally exposed to 3rd parties.)
8437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.updateServiceLocation();
8447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRadioOn() {
8477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getServiceState().getVoiceRegState() != ServiceState.STATE_POWER_OFF;
8487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void toggleRadioOnOff() {
8517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setRadioPower(!isRadioOn());
8537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadio(boolean turnOn) {
8557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if ((mPhone.getServiceState().getVoiceRegState() != ServiceState.STATE_POWER_OFF) != turnOn) {
8577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            toggleRadioOnOff();
8587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
8607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadioPower(boolean turnOn) {
8627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setRadioPower(turnOn);
8647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
8657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean enableDataConnectivity() {
8687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
869ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        mPhone.setDataEnabled(true);
8707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
8717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int enableApnType(String type) {
8747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.enableApnType(type);
8767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int disableApnType(String type) {
8797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.disableApnType(type);
8817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean disableDataConnectivity() {
8847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
885ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        mPhone.setDataEnabled(false);
8867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
8877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isDataConnectivityPossible() {
8907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.isDataConnectivityPossible();
8917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean handlePinMmi(String dialString) {
8947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString);
8967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void cancelMissedCallsNotification() {
8997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
9007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.notificationMgr.cancelMissedCallNotification();
9017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCallState() {
9047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return DefaultPhoneNotifier.convertCallState(mCM.getState());
9057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataState() {
9087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return DefaultPhoneNotifier.convertDataState(mPhone.getDataConnectionState());
9097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataActivity() {
9127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return DefaultPhoneNotifier.convertDataActivityState(mPhone.getDataActivityState());
9137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
9167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public Bundle getCellLocation() {
9177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
9187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
9197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
9207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
9217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
9227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
9237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
9247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
9257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
9267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
928e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
9297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: is active user");
9307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Bundle data = new Bundle();
9317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mPhone.getCellLocation().fillInNotifierBundle(data);
9327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return data;
9337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
9347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: suppress non-active user");
9357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
9367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
9407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void enableLocationUpdates() {
9417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
9427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
9437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.enableLocationUpdates();
9447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
9477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void disableLocationUpdates() {
9487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
9497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
9507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.disableLocationUpdates();
9517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
9547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @SuppressWarnings("unchecked")
9557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
9567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
9577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
9587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_FINE_LOCATION, null);
9597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
9607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check
9617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // for ACCESS_COARSE_LOCATION
9627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from
9637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // ACCESS_COARSE_LOCATION since this is the weaker precondition
9647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
9657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
9667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
9697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                callingPackage) != AppOpsManager.MODE_ALLOWED) {
9707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
9717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
972e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
9737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: is active user");
9747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ArrayList<NeighboringCellInfo> cells = null;
9767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
9787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                cells = (ArrayList<NeighboringCellInfo>) sendRequest(
9797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        CMD_HANDLE_NEIGHBORING_CELL, null);
9807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (RuntimeException e) {
981566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                loge("getNeighboringCellInfo " + e);
9827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
9837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return cells;
9847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
9857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
9867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
9877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
9927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<CellInfo> getAllCellInfo() {
9937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
9947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
9957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
9967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
9977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
9987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
9997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
10007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
10017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
10027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1004e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
10057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: is active user");
10067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return mPhone.getAllCellInfo();
10077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
10087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
10097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
10107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1013bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    @Override
10147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void setCellInfoListRate(int rateInMillis) {
10157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setCellInfoListRate(rateInMillis);
10167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
10197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Internal helper methods.
10207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
10217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1022e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static boolean checkIfCallerIsSelfOrForegroundUser() {
10237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean ok;
10247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean self = Binder.getCallingUid() == Process.myUid();
10267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!self) {
10277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Get the caller's user id then clear the calling identity
10287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // which will be restored in the finally clause.
10297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int callingUser = UserHandle.getCallingUserId();
10307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            long ident = Binder.clearCallingIdentity();
10317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
10337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // With calling identity cleared the current user is the foreground user.
10347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                int foregroundUser = ActivityManager.getCurrentUser();
10357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = (foregroundUser == callingUser);
10367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) {
10377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
10387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            + " callingUser=" + callingUser + " ok=" + ok);
10397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
10407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (Exception ex) {
10417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
10427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = false;
10437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } finally {
10447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Binder.restoreCallingIdentity(ident);
10457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
10477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
10487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ok = true;
10497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
10517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return ok;
10527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
10557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the READ_PHONE_STATE permission.
10567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
10577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
10587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
10597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceReadPermission() {
10607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
10617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
10647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the MODIFY_PHONE_STATE permission.
10657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
10667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
10677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
10687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceModifyPermission() {
10697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
10707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
10737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the CALL_PHONE permission.
10747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
10757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
10767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
10777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceCallPermission() {
10787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
10797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1081566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
108236ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
108336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     *
108436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * @throws SecurityException if the caller does not have the required permission
108536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     */
108636ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    private void enforcePrivilegedPhoneStatePermission() {
108736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
108836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal                null);
108936ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    }
109036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal
109136ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    /**
1092566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * Make sure the caller has SIM_COMMUNICATION permission.
1093566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     *
1094566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * @throws SecurityException if the caller does not have the required permission.
1095566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
1096566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private void enforceSimCommunicationPermission() {
1097566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.SIM_COMMUNICATION, null);
1098566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
10997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private String createTelUrl(String number) {
11017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TextUtils.isEmpty(number)) {
11027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
11037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1105e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return "tel:" + number;
11067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1108f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void log(String msg) {
11097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
11107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1112f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void loge(String msg) {
11137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
11147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getActivePhoneType() {
11177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getPhoneType();
11187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon index to display
11227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconIndex() {
11247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getCdmaEriIconIndex();
11257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon mode,
11297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 0 - ON
11307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 1 - FLASHING
11317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconMode() {
11337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getCdmaEriIconMode();
11347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI text,
11387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public String getCdmaEriText() {
11407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getCdmaEriText();
11417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns true if CDMA provisioning needs to run.
11457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean needsOtaServiceProvisioning() {
11477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.needsOtaServiceProvisioning();
11487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the unread count of voicemails
11527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceMessageCount() {
11547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getVoiceMessageCount();
11557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
11597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
11607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
11617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getNetworkType() {
11647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getServiceState().getDataNetworkType();
11657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
11697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataNetworkType() {
11727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getServiceState().getDataNetworkType();
11737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
11777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceNetworkType() {
11807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getServiceState().getVoiceNetworkType();
11817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true if a ICC card is present
11857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean hasIccCard() {
11877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getIccCard().hasIccCard();
11887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Return if the current radio is LTE on CDMA. This
11927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * is a tri-state return value as for a period of time
11937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * the mode may be unknown.
11947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
11957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1196e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * or {@link Phone#LTE_ON_CDMA_TRUE}
11977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getLteOnCdmaMode() {
11997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.getLteOnCdmaMode();
12007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1201f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1202f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1203f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1204f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1205f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public int getWhenToMakeWifiCalls() {
1206d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1207d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
1208f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
1209f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1210f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1211f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1212f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1213f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public void setWhenToMakeWifiCalls(int preference) {
1214d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1215d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        Settings.System.putInt(mPhone.getContext().getContentResolver(),
1216d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
1217f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    }
1218f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad
1219d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal    private static int getWhenToMakeWifiCallsDefaultPreference() {
1220d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        // TODO(sail): Use a build property to choose this value.
12219829e880f73f76119ba76ba032db42aad042858fEvan Charlton        return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
1222f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
122369f68120b94cecb2d87fe856bc115714b4e77bcdShishir Agrawal
1224566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1225566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public int iccOpenLogicalChannel(String AID) {
1226566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        enforceSimCommunicationPermission();
1227566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1228566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + AID);
1229566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        Integer channel = (Integer)sendRequest(CMD_OPEN_CHANNEL, AID);
1230566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + channel);
1231e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return channel;
1232566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1233566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1234566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1235566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public boolean iccCloseLogicalChannel(int channel) {
1236566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        enforceSimCommunicationPermission();
1237566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1238566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + channel);
1239566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1240566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return false;
1241566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1242e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
1243566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + success);
1244566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return success;
1245566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1246566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1247566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1248566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public String iccTransmitApduLogicalChannel(int channel, int cla,
1249566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            int command, int p1, int p2, int p3, String data) {
1250566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        enforceSimCommunicationPermission();
1251566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1252566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) {
1253566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1254566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1255566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " data=" + data);
1256566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1257566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1258566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1259566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            return "";
1260566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1261566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1262566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU,
1263566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1264566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1265566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1266566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // If the payload is null, there was an error. Indicate that by returning
1267566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // an empty string.
1268566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (response.payload == null) {
1269566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return "";
1270566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1271566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1272566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // Append the returned status code to the end of the response payload.
1273566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        String s = Integer.toHexString(
1274566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1275566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        s = IccUtils.bytesToHexString(response.payload) + s;
1276566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return s;
1277566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1278e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1279c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    @Override
1280c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    public String sendEnvelopeWithStatus(String content) {
1281c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        enforceSimCommunicationPermission();
1282c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1283c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1284c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        if (response.payload == null) {
1285c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton          return "";
1286c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        }
1287c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1288c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        // Append the returned status code to the end of the response payload.
1289c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        String s = Integer.toHexString(
1290c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1291c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        s = IccUtils.bytesToHexString(response.payload) + s;
1292c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        return s;
1293c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    }
1294c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1295e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1296e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1297e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1298e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1299e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1300e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return the NV item as a String, or null on error.
1301e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1302e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1303e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public String nvReadItem(int itemID) {
1304e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        enforceModifyPermission();
1305e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID);
1306e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1307e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1308e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return value;
1309e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1310e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1311e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1312e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1313e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1314e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1315e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1316e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemValue the value to write, as a String
1317e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1318e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1319e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1320e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteItem(int itemID, String itemValue) {
1321e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        enforceModifyPermission();
1322e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1323e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1324e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                new Pair<Integer, String>(itemID, itemValue));
1325e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1326e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1327e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1328e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1329e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1330e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1331e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1332e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1333e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param preferredRoamingList byte array containing the new PRL
1334e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1335e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1336e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1337e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
1338e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        enforceModifyPermission();
1339e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1340e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1341e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1342e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1343e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1344e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1345e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1346e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Perform the specified type of NV config reset.
1347e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1348e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1349e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1350e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1351e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1352e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1353e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvResetConfig(int resetType) {
1354e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        enforceModifyPermission();
1355e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType);
1356e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1357e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1358e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1359e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
13607c27be317e8757948178815426d3a329c852b9eeJake Hamby
13617c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
13627c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Get the preferred network type.
13637c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
13647c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
13657c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return the preferred network type, defined in RILConstants.java.
13667c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
13677c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
13687c27be317e8757948178815426d3a329c852b9eeJake Hamby    public int getPreferredNetworkType() {
13697c27be317e8757948178815426d3a329c852b9eeJake Hamby        enforceModifyPermission();
13707c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType");
13717c27be317e8757948178815426d3a329c852b9eeJake Hamby        int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
13727c27be317e8757948178815426d3a329c852b9eeJake Hamby        int networkType = (result != null ? result[0] : -1);
13737c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType: " + networkType);
13747c27be317e8757948178815426d3a329c852b9eeJake Hamby        return networkType;
13757c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
13767c27be317e8757948178815426d3a329c852b9eeJake Hamby
13777c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
13787c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Set the preferred network type.
13797c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
13807c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
13817c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @param networkType the preferred network type, defined in RILConstants.java.
13827c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return true on success; false on any failure.
13837c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
13847c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
13857c27be317e8757948178815426d3a329c852b9eeJake Hamby    public boolean setPreferredNetworkType(int networkType) {
13867c27be317e8757948178815426d3a329c852b9eeJake Hamby        enforceModifyPermission();
13877c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: type " + networkType);
13887c27be317e8757948178815426d3a329c852b9eeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
13897c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
13907c27be317e8757948178815426d3a329c852b9eeJake Hamby        return success;
13917c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
1392ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1393ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1394ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Set mobile data enabled
1395ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Used by the user through settings etc to turn on/off mobile data
1396ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1397ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @param enable {@code true} turn turn data on, else {@code false}
1398ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1399ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1400ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public void setDataEnabled(boolean enable) {
1401ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        enforceModifyPermission();
1402ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        mPhone.setDataEnabled(enable);
1403ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
1404ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1405ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1406646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Get whether mobile data is enabled.
1407646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     *
1408646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Note that this used to be available from ConnectivityService, gated by
1409646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * ACCESS_NETWORK_STATE permission, so this will accept either that or
1410646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * our MODIFY_PHONE_STATE.
1411ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1412ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @return {@code true} if data is enabled else {@code false}
1413ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1414ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1415ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public boolean getDataEnabled() {
1416646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        try {
1417646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1418646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1419646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        } catch (Exception e) {
1420646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1421646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1422646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        }
1423ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        return mPhone.getDataEnabled();
1424ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
14257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
1426