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