PhoneInterfaceManager.java revision da120f4e3d32ca97c5b4c21d6c505d834a29ab8d
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;
2460f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageInfo;
2560f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageManager;
2660f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.Signature;
2736469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport android.net.ConnectivityManager;
287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.net.Uri;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Binder;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Bundle;
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
3336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.IBinder;
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Looper;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Process;
3736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.RemoteException;
387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.ServiceManager;
397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.UserHandle;
40f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.provider.Settings;
417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.CellInfo;
42da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawalimport android.telephony.IccOpenLogicalChannelResponse;
43e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.telephony.NeighboringCellInfo;
447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.ServiceState;
4536469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport android.telephony.SubscriptionManager;
46f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.telephony.TelephonyManager;
477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
49e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.util.Pair;
507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
51566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CallManager;
52566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CommandException;
5336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport com.android.internal.telephony.Connection;
547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.DefaultPhoneNotifier;
557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.ITelephony;
56e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.telephony.IccCard;
577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
5836469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.PhoneFactory;
5936469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.CallManager;
6036469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.CommandException;
617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneConstants;
6236469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.dataconnection.DctController;
637226c84acb402f96e527650347391fa025294350Derek Tanimport com.android.internal.telephony.uicc.AdnRecord;
64566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccIoResult;
65566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
66eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawalimport com.android.internal.telephony.uicc.UiccCard;
6760f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
68566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
69e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.util.HexDump;
707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7136469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
7236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
7436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.HashMap;
7589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tanimport java.util.HashSet;
7636ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Iterator;
77e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport java.util.List;
7836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Map;
7989e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tanimport java.util.Set;
807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Implementation of the ITelephony interface.
837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
84117fee7467c140dccdc66972f60031dae2d55b35Santos Cordonpublic class PhoneInterfaceManager extends ITelephony.Stub {
857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "PhoneInterfaceManager";
867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG_LOC = false;
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message codes used with mMainThreadHandler
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_PIN_MMI = 1;
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_ANSWER_RINGING_CALL = 4;
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_END_CALL = 5;  // not used yet
957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_SILENCE_RINGER = 6;
96da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
97da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
98566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_OPEN_CHANNEL = 9;
99566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_OPEN_CHANNEL_DONE = 10;
100566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_CLOSE_CHANNEL = 11;
101566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
102e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_READ_ITEM = 13;
103e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_READ_ITEM_DONE = 14;
104e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_ITEM = 15;
105e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
106e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_CDMA_PRL = 17;
107e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
108e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_RESET_CONFIG = 19;
109e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
1107c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
1117c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
1127c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
1137c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
11435b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int CMD_SEND_ENVELOPE = 25;
11535b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int EVENT_SEND_ENVELOPE_DONE = 26;
116787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    private static final int CMD_SET_CDMA_SUBSCRIPTION = 27;
117787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    private static final int EVENT_SET_CDMA_SUBSCRIPTION_DONE = 28;
1184bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 29;
1194bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 30;
120da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 31;
121da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 32;
122da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int CMD_EXCHANGE_SIM_IO = 33;
123da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int EVENT_EXCHANGE_SIM_IO_DONE = 34;
1247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The singleton instance. */
1267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static PhoneInterfaceManager sInstance;
1277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    PhoneGlobals mApp;
1297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    Phone mPhone;
1307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    CallManager mCM;
1317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    AppOpsManager mAppOps;
1327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    MainThreadHandler mMainThreadHandler;
1337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan     * Indicates if Android should display a simplified Mobile Network Settings UI in a specific
13689e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan     * subscription.
13789e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan     */
13889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    Set<Long> mSimplifiedNetworkSettings;
1397226c84acb402f96e527650347391fa025294350Derek Tan    Map<Long, AdnRecord> mAdnRecordsForDisplay;
14089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
14189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    /**
142566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * A request object to use for transmitting data to an ICC.
143566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
144566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final class IccAPDUArgument {
145566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public int channel, cla, command, p1, p2, p3;
146566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public String data;
147566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
148566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public IccAPDUArgument(int channel, int cla, int command,
149566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                int p1, int p2, int p3, String data) {
150566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.channel = channel;
151566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.cla = cla;
152566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.command = command;
153566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p1 = p1;
154566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p2 = p2;
155566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p3 = p3;
156566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.data = data;
157566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
158566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
159566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
160566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
1617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
1627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request after sending. The main thread will notify the request when it is complete.
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final class MainThreadRequest {
1657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The argument to use for the request */
1667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object argument;
1677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The result of the request that is run on the main thread */
1687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object result;
1697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public MainThreadRequest(Object argument) {
1717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            this.argument = argument;
1727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
175cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    private static final class IncomingThirdPartyCallArgs {
176cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final ComponentName component;
177cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callId;
178cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callerDisplayName;
179cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
180cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public IncomingThirdPartyCallArgs(ComponentName component, String callId,
181cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal                String callerDisplayName) {
182cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.component = component;
183cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callId = callId;
184cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callerDisplayName = callerDisplayName;
185cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        }
186cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    }
187cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
1887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A handler that processes messages on the main thread in the phone process. Since many
1907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
1917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * inbound binder threads to the main thread in the phone process.  The Binder thread
1927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * on, which will be notified when the operation completes and will contain the result of the
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request.
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
1967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * <p>If a MainThreadRequest object is provided in the msg.obj field,
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * note that request.result must be set to something non-null for the calling thread to
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * unblock.
1997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
2007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final class MainThreadHandler extends Handler {
2017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
2027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
2037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            MainThreadRequest request;
2047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message onCompleted;
2057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar;
206eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            UiccCard uiccCard = UiccController.getInstance().getUiccCard();
207da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            IccAPDUArgument iccArgument;
2087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
2107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_PIN_MMI:
2117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
212e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request.result = mPhone.handlePinMmi((String) request.argument);
2137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_NEIGHBORING_CELL:
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
2217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
2227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            request);
2237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mPhone.getNeighboringCids(onCompleted);
2247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NEIGHBORING_CELL_DONE:
2277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    ar = (AsyncResult) msg.obj;
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) ar.userObj;
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (ar.exception == null && ar.result != null) {
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.result = ar.result;
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // create an empty list to notify the waiting thread
233e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = new ArrayList<NeighboringCellInfo>(0);
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_ANSWER_RINGING_CALL:
2427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    answerRingingCallInternal();
2437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_SILENCE_RINGER:
2467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    silenceRingerInternal();
2477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_END_CALL:
2507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
251e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    boolean hungUp;
2527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    int phoneType = mPhone.getPhoneType();
2537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
2547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // CDMA: If the user presses the Power button we treat it as
2557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // ending the complete call session
2567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
2577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
2587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // GSM: End the call as per the Phone state
2597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangup(mCM);
2607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
2627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
2647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.result = hungUp;
2657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
271da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
272566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
273da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
274eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
275eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccTransmitApduLogicalChannel: No UICC");
276eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
277eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
278eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
279eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
280eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
281da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
282da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
283eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccTransmitApduLogicalChannel(
284da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.channel, iccArgument.cla, iccArgument.command,
285da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
286566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
287eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
288566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
289566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
290da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
291566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
292566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
293566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
294566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = ar.result;
295566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
296566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
297566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
298566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Empty response");
299e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
300566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: CommandException: " +
301e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
302566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
303566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Unknown exception");
304566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
305566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
306566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
307566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
308566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
309566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
310566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
311da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
312da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
313da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
314da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
315da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccTransmitApduBasicChannel: No UICC");
316da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
317da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
318da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
319da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
320da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
321da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
322da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
323da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccTransmitApduBasicChannel(
324da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
325da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p3, iccArgument.data, onCompleted);
326da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
327da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
328da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
329da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
330da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
331da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
332da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
333da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
334da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
335da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
336da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.result == null) {
337da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Empty response");
338da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else if (ar.exception instanceof CommandException) {
339da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: CommandException: " +
340da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                    ar.exception);
341da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else {
342da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Unknown exception");
343da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
344da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
345da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
346da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
347da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
348da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
349da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
350da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_EXCHANGE_SIM_IO:
351da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
352da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
353da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
354da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccExchangeSimIO: No UICC");
355da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
356da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
357da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
358da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
359da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
360da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
361da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                request);
362da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
363da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
364da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.data, onCompleted);
365da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
366da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
367da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
368da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_EXCHANGE_SIM_IO_DONE:
369da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
370da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
371da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
372da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
373da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
374da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6f, 0, (byte[])null);
375da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
376da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
377da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
378da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
379da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
380da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
3814d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case CMD_SEND_ENVELOPE:
3824d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) msg.obj;
383eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
384eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("sendEnvelopeWithStatus: No UICC");
385eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
386eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
387eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
388eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
389eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
390eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
391eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
392eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
3934d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
3944d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
3954d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case EVENT_SEND_ENVELOPE_DONE:
3964d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    ar = (AsyncResult) msg.obj;
3974d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) ar.userObj;
3989f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    if (ar.exception == null && ar.result != null) {
3999f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = ar.result;
4004d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    } else {
4019f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
4029f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        if (ar.result == null) {
4039f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: Empty response");
4049f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else if (ar.exception instanceof CommandException) {
4059f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: CommandException: " +
4069f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                                    ar.exception);
4079f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else {
4089f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: exception:" + ar.exception);
4099f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        }
4104d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4114d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    synchronized (request) {
4124d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                        request.notifyAll();
4134d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4144d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
4154d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
416566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_OPEN_CHANNEL:
417566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
418eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
419eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccOpenLogicalChannel: No UICC");
420eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
421eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
422eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
423eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
424eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
425eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
426eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
427eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
428566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
429566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
430566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_OPEN_CHANNEL_DONE:
431566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
432566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
433da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    IccOpenLogicalChannelResponse openChannelResp;
434566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
435da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int[] result = (int[]) ar.result;
436da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int channelId = result[0];
437da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        byte[] selectResponse = null;
438da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (result.length > 1) {
439da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            selectResponse = new byte[result.length - 1];
440da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            for (int i = 1; i < result.length; ++i) {
441da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                selectResponse[i - 1] = (byte) result[i];
442da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
443da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
444da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(channelId,
445da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            IccOpenLogicalChannelResponse.NO_ERROR, selectResponse );
446566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
447566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
448566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Empty response");
449566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
450da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.exception != null) {
451da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccOpenLogicalChannel: Exception: " + ar.exception);
452da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
453da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
454da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int errorCode = IccOpenLogicalChannelResponse.UNKNOWN_ERROR;
455da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
456da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
457da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.MISSING_RESOURCE;
458da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
459da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.NO_SUCH_ELEMENT;
460da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
461da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
462da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(
463da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
464566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
46582c8a46052629d1450320c116d14c7353bfe4ea1Shishir Agrawal                    request.result = openChannelResp;
466566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
467566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
468566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
469566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
470566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
471566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_CLOSE_CHANNEL:
472566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
473eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
474eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccCloseLogicalChannel: No UICC");
475eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
476eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
477eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
478eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
479eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
480eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
481eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
482eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
483566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
484566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
485566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_CLOSE_CHANNEL_DONE:
486e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "iccCloseLogicalChannel");
487e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
488e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
489e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_READ_ITEM:
490e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
491e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
492e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvReadItem((Integer) request.argument, onCompleted);
493e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
494e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
495e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_READ_ITEM_DONE:
496566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
497566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
498e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    if (ar.exception == null && ar.result != null) {
499e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ar.result;     // String
500566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
501e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = "";
502e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        if (ar.result == null) {
503e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Empty response");
504e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
505e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: CommandException: " +
506e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
507566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
508e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Unknown exception");
509566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
510566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
511566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
512566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
513566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
514566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
515566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
516e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_ITEM:
517e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
518e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
519e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
520e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
521e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
522e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
523e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_ITEM_DONE:
524e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteItem");
525e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
526e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
527e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_CDMA_PRL:
528e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
529e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
530e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
531e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
532e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
533e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_CDMA_PRL_DONE:
534e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteCdmaPrl");
535e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
536e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
537e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_RESET_CONFIG:
538e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
539e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
540e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
541e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
542e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
543e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_RESET_CONFIG_DONE:
544e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvResetConfig");
545e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
546e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
5477c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_GET_PREFERRED_NETWORK_TYPE:
5487c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
5497c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
5507c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.getPreferredNetworkType(onCompleted);
5517c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5527c27be317e8757948178815426d3a329c852b9eeJake Hamby
5537c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
5547c27be317e8757948178815426d3a329c852b9eeJake Hamby                    ar = (AsyncResult) msg.obj;
5557c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) ar.userObj;
5567c27be317e8757948178815426d3a329c852b9eeJake Hamby                    if (ar.exception == null && ar.result != null) {
5577c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = ar.result;     // Integer
5587c27be317e8757948178815426d3a329c852b9eeJake Hamby                    } else {
5597c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = -1;
5607c27be317e8757948178815426d3a329c852b9eeJake Hamby                        if (ar.result == null) {
5617c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Empty response");
5627c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else if (ar.exception instanceof CommandException) {
5637c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: CommandException: " +
5647c27be317e8757948178815426d3a329c852b9eeJake Hamby                                    ar.exception);
5657c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else {
5667c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Unknown exception");
5677c27be317e8757948178815426d3a329c852b9eeJake Hamby                        }
5687c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
5697c27be317e8757948178815426d3a329c852b9eeJake Hamby                    synchronized (request) {
5707c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.notifyAll();
5717c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
5727c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5737c27be317e8757948178815426d3a329c852b9eeJake Hamby
5747c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_SET_PREFERRED_NETWORK_TYPE:
5757c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
5767c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
5777c27be317e8757948178815426d3a329c852b9eeJake Hamby                    int networkType = (Integer) request.argument;
5787c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.setPreferredNetworkType(networkType, onCompleted);
5797c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5807c27be317e8757948178815426d3a329c852b9eeJake Hamby
5817c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
5827c27be317e8757948178815426d3a329c852b9eeJake Hamby                    handleNullReturnEvent(msg, "setPreferredNetworkType");
5837c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5847c27be317e8757948178815426d3a329c852b9eeJake Hamby
585787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                case CMD_SET_CDMA_SUBSCRIPTION:
586787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    request = (MainThreadRequest) msg.obj;
587787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_DONE, request);
588787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    int subscriptionType = (Integer) request.argument;
589787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    mPhone.setCdmaSubscription(subscriptionType, onCompleted);
590787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    break;
591787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu
592787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                case EVENT_SET_CDMA_SUBSCRIPTION_DONE:
593787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    handleNullReturnEvent(msg, "setCdmaSubscription");
594787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    break;
595787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu
5964bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
5974bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)msg.obj;
5984bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
5994bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
6004bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
6014bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
6024bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
6034bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    ar = (AsyncResult)msg.obj;
6044bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)ar.userObj;
6054bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request.result = ar;
6064bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    synchronized (request) {
6074bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        request.notifyAll();
6084bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
6094bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
6104bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
6117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                default:
6127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
6137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
6147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
616e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
617e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        private void handleNullReturnEvent(Message msg, String command) {
618e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            AsyncResult ar = (AsyncResult) msg.obj;
619e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            MainThreadRequest request = (MainThreadRequest) ar.userObj;
620e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            if (ar.exception == null) {
621e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = true;
622e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            } else {
623e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = false;
624e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                if (ar.exception instanceof CommandException) {
625e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": CommandException: " + ar.exception);
626e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                } else {
627e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": Unknown exception");
628e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                }
629e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
630e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            synchronized (request) {
631e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.notifyAll();
632e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
633e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        }
6347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread,
6387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * waits for the request to complete, and returns the result.
6397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequestAsync
6407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Object sendRequest(int command, Object argument) {
642500b0e04406d2995c1f29dea95c98cedaa669f74Santos Cordon        return sendRequest(command, argument, null);
64336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
64436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
64536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
64636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Posts the specified command to be executed on the main thread,
64736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * waits for the request to complete, and returns the result.
64836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @see #sendRequestAsync
64936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
65036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private Object sendRequest(int command, Object argument, Object argument2) {
6517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
6527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            throw new RuntimeException("This method will deadlock if called from the main thread.");
6537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        MainThreadRequest request = new MainThreadRequest(argument);
6567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Message msg = mMainThreadHandler.obtainMessage(command, request);
6577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        msg.sendToTarget();
6587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Wait for the request to complete
6607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (request) {
6617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (request.result == null) {
6627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
6637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.wait();
6647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
6657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Do nothing, go back and wait until the request is complete
6667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
6677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return request.result;
6707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Asynchronous ("fire and forget") version of sendRequest():
6747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread, and
6757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * returns immediately.
6767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequest
6777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void sendRequestAsync(int command) {
6797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler.sendEmptyMessage(command);
6807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
683bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * Same as {@link #sendRequestAsync(int)} except it takes an argument.
684bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * @see {@link #sendRequest(int,Object)}
685bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     */
686bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    private void sendRequestAsync(int command, Object argument) {
687bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        MainThreadRequest request = new MainThreadRequest(argument);
688bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        Message msg = mMainThreadHandler.obtainMessage(command, request);
689bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        msg.sendToTarget();
690bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    }
691bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal
692bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    /**
6937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton PhoneInterfaceManager instance.
6947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
6957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
696194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
6977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (PhoneInterfaceManager.class) {
6987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
699194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal                sInstance = new PhoneInterfaceManager(app, phone);
7007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
7017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
7027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
7037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
7047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** Private constructor; @see init() */
708194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
7097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
7107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = phone;
7117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mCM = PhoneGlobals.getInstance().mCM;
71289e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        mSimplifiedNetworkSettings = new HashSet<Long>();
7137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
7147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler = new MainThreadHandler();
7157226c84acb402f96e527650347391fa025294350Derek Tan        mAdnRecordsForDisplay = new HashMap<Long, AdnRecord>();
7167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        publish();
7177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void publish() {
7207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("publish: " + this);
7217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        ServiceManager.addService("phone", this);
7237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
72536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // returns phone associated with the subId.
72636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // getPhone(0) returns default phone in single SIM mode.
72736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private Phone getPhone(long subId) {
72836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME: hack for the moment
72936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return mPhone;
73036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // return PhoneUtils.getPhoneUsingSubId(subId);
73136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
7327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
7337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Implementation of the ITelephony interface.
7347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
7357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void dial(String number) {
73736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        dialUsingSubId(getPreferredVoiceSubscription(), number);
73836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
73936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
74036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void dialUsingSubId(long subId, String number) {
7417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("dial: " + number);
7427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: This is just a wrapper around the
7437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // ACTION_DIAL intent, which is available to any app since it puts up
7447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // the UI before it does anything.
7457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
7477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
7487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // PENDING: should we just silently fail if phone is offhook or ringing?
75236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        PhoneConstants.State state = mCM.getState(subId);
7537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
7547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
7557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
75636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville            intent.putExtra(SUBSCRIPTION_KEY, subId);
7577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.startActivity(intent);
7587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void call(String callingPackage, String number) {
76236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        callUsingSubId(getPreferredVoiceSubscription(), callingPackage, number);
76336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
76436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
76536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void callUsingSubId(long subId, String callingPackage, String number) {
7667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("call: " + number);
7677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // This is just a wrapper around the ACTION_CALL intent, but we still
7697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // need to do a permission check since we're calling startActivity()
7707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // from the context of the phone app.
7717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
7727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
7747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                != AppOpsManager.MODE_ALLOWED) {
7757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
7797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
7807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
78436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        intent.putExtra(SUBSCRIPTION_KEY, subId);
7857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.startActivity(intent);
7877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * End a call based on call state
7917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true is a call was ended
7927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean endCall() {
79436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return endCallUsingSubId(getDefaultSubscription());
79536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
79636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
79736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
79836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * End a call based on the call state of the subId
79936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true is a call was ended
80036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
80136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean endCallUsingSubId(long subId) {
8027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
80336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_END_CALL, subId, null);
8047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void answerRingingCall() {
80736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        answerRingingCallUsingSubId(getDefaultSubscription());
80836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
80936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
81036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void answerRingingCallUsingSubId(long subId) {
8117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("answerRingingCall...");
8127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
8137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // but that can probably wait till the big TelephonyManager API overhaul.
8147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.
8157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_ANSWER_RINGING_CALL);
8177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make the actual telephony calls to implement answerRingingCall().
8217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
8227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #answerRingingCall
8237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
8247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: it would be nice to return true if we answered the call, or
8257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * false if there wasn't actually a ringing incoming call, or some
8267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * other error occurred.  (In other words, pass back the return value
8277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
8287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * But that would require calling this method via sendRequest() rather
8297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * than sendRequestAsync(), and right now we don't actually *need* that
8307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * return value, so let's just return void for now.
8317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void answerRingingCallInternal() {
8337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final boolean hasRingingCall = !mPhone.getRingingCall().isIdle();
8347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (hasRingingCall) {
8357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasActiveCall = !mPhone.getForegroundCall().isIdle();
8367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasHoldingCall = !mPhone.getBackgroundCall().isIdle();
8377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (hasActiveCall && hasHoldingCall) {
8387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Both lines are in use!
8397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // TODO: provide a flag to let the caller specify what
8407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // policy to use if both lines are in use.  (The current
8417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // behavior is hardwired to "answer incoming, end ongoing",
8427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // which is how the CALL button is specced to behave.)
8437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
8447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
8457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
8467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // answerCall() will automatically hold the current active
8477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // call, if there is one.
8487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
8497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
8507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
8527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // No call was ringing.
8537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
8547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void silenceRinger() {
8587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("silenceRinger...");
8597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: find a more appropriate permission to check here.
8607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // (That can probably wait till the big TelephonyManager API overhaul.
8617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.)
8627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_SILENCE_RINGER);
8647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Internal implemenation of silenceRinger().
8687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
8697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #silenceRinger
8707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void silenceRingerInternal() {
8727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if ((mCM.getState() == PhoneConstants.State.RINGING)
8737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            && mApp.notifier.isRinging()) {
8747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Ringer is actually playing, so silence it.
8757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG) log("silenceRingerInternal: silencing...");
8767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.notifier.silenceRinger();
8777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isOffhook() {
88136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isOffhookUsingSubId(getDefaultSubscription());
88236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
88336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
88436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isOffhookUsingSubId(long subId) {
88536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
8867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRinging() {
88936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (isRingingUsingSubId(getDefaultSubscription()));
89036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
89136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
89236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isRingingUsingSubId(long subId) {
89336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
8947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isIdle() {
89736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isIdleUsingSubId(getDefaultSubscription());
89836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
89936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
90036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isIdleUsingSubId(long subId) {
90136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
9027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isSimPinEnabled() {
9057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceReadPermission();
9067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (PhoneGlobals.getInstance().isSimPinEnabled());
9077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean supplyPin(String pin) {
91036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPinUsingSubId(getDefaultSubscription(), pin);
91136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
91236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
91336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean supplyPinUsingSubId(long subId, String pin) {
91436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        int [] resultArray = supplyPinReportResultUsingSubId(subId, pin);
9159de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
9169de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
9179de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
9189de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public boolean supplyPuk(String puk, String pin) {
91936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPukUsingSubId(getDefaultSubscription(), puk, pin);
92036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
92136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
92236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean supplyPukUsingSubId(long subId, String puk, String pin) {
92336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        int [] resultArray = supplyPukReportResultUsingSubId(subId, puk, pin);
9249de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
9259de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
9269de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
9279de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
9289de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPinReportResult(String pin) {
92936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPinReportResultUsingSubId(getDefaultSubscription(), pin);
93036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
93136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
93236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int[] supplyPinReportResultUsingSubId(long subId, String pin) {
9337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
93436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
9357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPin.start();
9367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPin.unlockSim(null, pin);
9377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9399de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
9409de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPukReportResult(String puk, String pin) {
94136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPukReportResultUsingSubId(getDefaultSubscription(), puk, pin);
94236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
94336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
94436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin) {
9457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
94636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
9477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPuk.start();
9487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPuk.unlockSim(puk, pin);
9497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
9529de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville     * Helper thread to turn async call to SimCard#supplyPin into
9537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * a synchronous one.
9547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
9557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static class UnlockSim extends Thread {
9567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private final IccCard mSimCard;
9587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private boolean mDone = false;
9609de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
9619de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mRetryCount = -1;
9627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For replies from SimCard interface
9647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private Handler mHandler;
9657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For async handler to identify request type
9677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private static final int SUPPLY_PIN_COMPLETE = 100;
9687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public UnlockSim(IccCard simCard) {
9707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mSimCard = simCard;
9717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
9747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void run() {
9757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.prepare();
9767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            synchronized (UnlockSim.this) {
9777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mHandler = new Handler() {
9787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    @Override
9797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    public void handleMessage(Message msg) {
9807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        AsyncResult ar = (AsyncResult) msg.obj;
9817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        switch (msg.what) {
9827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            case SUPPLY_PIN_COMPLETE:
9837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
9847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                synchronized (UnlockSim.this) {
9859de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    mRetryCount = msg.arg1;
9869de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    if (ar.exception != null) {
9879de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        if (ar.exception instanceof CommandException &&
9889de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                ((CommandException)(ar.exception)).getCommandError()
9899de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                == CommandException.Error.PASSWORD_INCORRECT) {
9909de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
9919de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        } else {
9929de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_GENERAL_FAILURE;
9939de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        }
9949de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    } else {
9959de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        mResult = PhoneConstants.PIN_RESULT_SUCCESS;
9969de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    }
9977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mDone = true;
9987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    UnlockSim.this.notifyAll();
9997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
10007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                break;
10017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
10027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
10037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                };
10047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                UnlockSim.this.notifyAll();
10057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.loop();
10077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /*
10107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Use PIN or PUK to unlock SIM card
10117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
10127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is null, unlock SIM card with PIN
10137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
10147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is not null, unlock SIM card with PUK and set PIN code
10157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
10169de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        synchronized int[] unlockSim(String puk, String pin) {
10177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (mHandler == null) {
10197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
10207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
10217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
10227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
10237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
10247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
10267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (puk == null) {
10287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPin(pin, callback);
10297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
10307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPuk(puk, pin, callback);
10317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (!mDone) {
10347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
10357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.d(LOG_TAG, "wait for done");
10367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
10377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
10387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Restore the interrupted status
10397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
10407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
10417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Log.d(LOG_TAG, "done");
10439de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            int[] resultArray = new int[2];
10449de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[0] = mResult;
10459de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[1] = mRetryCount;
10469de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            return resultArray;
10477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void updateServiceLocation() {
105136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        updateServiceLocationUsingSubId(getDefaultSubscription());
105236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
105336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
105436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
105536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void updateServiceLocationUsingSubId(long subId) {
10567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: this call is harmless, and it's
10577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // needed for the ServiceState.requestStateUpdate() call (which is
10587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // already intentionally exposed to 3rd parties.)
105936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).updateServiceLocation();
10607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRadioOn() {
106336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isRadioOnUsingSubId(getDefaultSubscription());
106436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
106536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
106636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isRadioOnUsingSubId(long subId) {
106736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
10687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void toggleRadioOnOff() {
107136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        toggleRadioOnOffUsingSubId(getDefaultSubscription());
107236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
107336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
107436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
107536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void toggleRadioOnOffUsingSubId(long subId) {
10767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
107736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(!isRadioOnUsingSubId(subId));
10787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
107936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
10807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadio(boolean turnOn) {
108136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return setRadioUsingSubId(getDefaultSubscription(), turnOn);
108236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
108336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
108436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean setRadioUsingSubId(long subId, boolean turnOn) {
10857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
108636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        if ((getPhone(subId).getServiceState().getState() !=
108736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                ServiceState.STATE_POWER_OFF) != turnOn) {
108836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville            toggleRadioOnOffUsingSubId(subId);
10897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
10917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
109236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
10937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadioPower(boolean turnOn) {
109436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return setRadioPowerUsingSubId(getDefaultSubscription(), turnOn);
109536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
109636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
109736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean setRadioPowerUsingSubId(long subId, boolean turnOn) {
10987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
109936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(turnOn);
11007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
110336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
11047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean enableDataConnectivity() {
11057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
110636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
110736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(true);
11087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
111136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
11127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean disableDataConnectivity() {
11137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
111436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
111536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(false);
11167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
111936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
11207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isDataConnectivityPossible() {
112136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
112236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).isDataConnectivityPossible();
11237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean handlePinMmi(String dialString) {
112636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return handlePinMmiUsingSubId(getDefaultSubscription(), dialString);
112736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
112836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
112936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean handlePinMmiUsingSubId(long subId, String dialString) {
11307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
113136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
11327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCallState() {
113536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCallStateUsingSubId(getDefaultSubscription());
113636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
113736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
113836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCallStateUsingSubId(long subId) {
113936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
11407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataState() {
114336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
114436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
11457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataActivity() {
114836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
114936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
11507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public Bundle getCellLocation() {
11547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
11557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
11567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
11577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
11587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
11597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
11607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
11617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
11627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
11637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1165e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
11667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: is active user");
11677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Bundle data = new Bundle();
11687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mPhone.getCellLocation().fillInNotifierBundle(data);
11697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return data;
11707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
11717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: suppress non-active user");
11727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
11737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void enableLocationUpdates() {
117836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enableLocationUpdatesUsingSubId(getDefaultSubscription());
117936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
118036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
118136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void enableLocationUpdatesUsingSubId(long subId) {
11827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
11837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
118436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).enableLocationUpdates();
11857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void disableLocationUpdates() {
118936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        disableLocationUpdatesUsingSubId(getDefaultSubscription());
119036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
119136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
119236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void disableLocationUpdatesUsingSubId(long subId) {
11937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
11947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
119536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).disableLocationUpdates();
11967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @SuppressWarnings("unchecked")
12007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
12017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
12027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_FINE_LOCATION, null);
12047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
12057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check
12067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // for ACCESS_COARSE_LOCATION
12077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from
12087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // ACCESS_COARSE_LOCATION since this is the weaker precondition
12097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
12117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
12147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                callingPackage) != AppOpsManager.MODE_ALLOWED) {
12157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1217e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
12187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: is active user");
12197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ArrayList<NeighboringCellInfo> cells = null;
12217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
12237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                cells = (ArrayList<NeighboringCellInfo>) sendRequest(
122436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                        CMD_HANDLE_NEIGHBORING_CELL, null, null);
12257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (RuntimeException e) {
122636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
12277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
12287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return cells;
12297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
12307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
12317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
12377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<CellInfo> getAllCellInfo() {
12387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
12397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
12417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
12427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
12437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
12447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
12457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
12477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1249e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
12507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: is active user");
12517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return mPhone.getAllCellInfo();
12527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
12537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
12547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1258bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    @Override
12597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void setCellInfoListRate(int rateInMillis) {
12607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setCellInfoListRate(rateInMillis);
12617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
12647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Internal helper methods.
12657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
12667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1267e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static boolean checkIfCallerIsSelfOrForegroundUser() {
12687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean ok;
12697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean self = Binder.getCallingUid() == Process.myUid();
12717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!self) {
12727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Get the caller's user id then clear the calling identity
12737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // which will be restored in the finally clause.
12747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int callingUser = UserHandle.getCallingUserId();
12757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            long ident = Binder.clearCallingIdentity();
12767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
12787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // With calling identity cleared the current user is the foreground user.
12797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                int foregroundUser = ActivityManager.getCurrentUser();
12807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = (foregroundUser == callingUser);
12817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) {
12827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
12837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            + " callingUser=" + callingUser + " ok=" + ok);
12847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
12857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (Exception ex) {
12867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
12877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = false;
12887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } finally {
12897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Binder.restoreCallingIdentity(ident);
12907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
12917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
12927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
12937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ok = true;
12947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
12967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return ok;
12977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the READ_PHONE_STATE permission.
13017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
13037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceReadPermission() {
13057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
13067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the MODIFY_PHONE_STATE permission.
13107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
13127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceModifyPermission() {
13147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
13157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1318a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure either system app or the caller has carrier privilege.
1319a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1320a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission/privilege
1321a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1322a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceModifyPermissionOrCarrierPrivilege() {
1323f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        int permission = mApp.checkCallingOrSelfPermission(
1324f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                android.Manifest.permission.MODIFY_PHONE_STATE);
1325f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (permission == PackageManager.PERMISSION_GRANTED) {
1326f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            return;
1327f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        }
1328f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal
1329f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        log("No modify permission, check carrier privilege next.");
1330f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1331f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1332f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No modify permission or carrier privilege.");
1333a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1334a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1335a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1336a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
1337a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure the caller has carrier privilege.
1338a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1339a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission
1340a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1341a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceCarrierPrivilege() {
1342a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1343f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1344f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No Carrier Privilege.");
1345a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1346a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1347a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1348a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
13497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the CALL_PHONE permission.
13507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
13527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceCallPermission() {
13547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
13557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1357566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
135836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
135936ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     *
136036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * @throws SecurityException if the caller does not have the required permission
136136ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     */
136236ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    private void enforcePrivilegedPhoneStatePermission() {
136336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
136436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal                null);
136536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    }
136636ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal
13677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private String createTelUrl(String number) {
13687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TextUtils.isEmpty(number)) {
13697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
13707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1372e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return "tel:" + number;
13737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1375f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void log(String msg) {
13767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
13777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1379f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void loge(String msg) {
13807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
13817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getActivePhoneType() {
138436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getActivePhoneTypeUsingSubId(getDefaultSubscription());
138536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
138636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
138736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getActivePhoneTypeUsingSubId(long subId) {
138836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getPhoneType();
13897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon index to display
13937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconIndex() {
139536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriIconIndexUsingSubId(getDefaultSubscription());
139636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
139736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
139836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
139936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCdmaEriIconIndexUsingSubId(long subId) {
140036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconIndex();
14017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon mode,
14057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 0 - ON
14067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 1 - FLASHING
14077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconMode() {
140936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriIconModeUsingSubId(getDefaultSubscription());
141036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
141136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
141236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCdmaEriIconModeUsingSubId(long subId) {
141336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconMode();
14147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI text,
14187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public String getCdmaEriText() {
142036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriTextUsingSubId(getDefaultSubscription());
142136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
142236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
142336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public String getCdmaEriTextUsingSubId(long subId) {
142436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriText();
14257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns true if CDMA provisioning needs to run.
14297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean needsOtaServiceProvisioning() {
14317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.needsOtaServiceProvisioning();
14327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the unread count of voicemails
14367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceMessageCount() {
143836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getVoiceMessageCountUsingSubId(getDefaultSubscription());
143936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
144036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
144136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
144236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the unread count of voicemails for a subId
144336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
144436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getVoiceMessageCountUsingSubId( long subId) {
144536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getVoiceMessageCount();
14467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
14507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
14517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
14527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getNetworkType() {
145536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getNetworkTypeUsingSubId(getDefaultSubscription());
145636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
145736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
145836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
145936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the network type for a subId
146036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
146136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
146236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getNetworkTypeUsingSubId(long subId) {
146336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
14647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
14687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataNetworkType() {
147136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getDataNetworkTypeUsingSubId(getDefaultSubscription());
147236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
147336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
147436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
147536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the data network type for a subId
147636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
147736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
147836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDataNetworkTypeUsingSubId(long subId) {
147936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
14807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
14847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceNetworkType() {
148736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getVoiceNetworkTypeUsingSubId(getDefaultSubscription());
148836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
148936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
149036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
149136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the Voice network type for a subId
149236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
149336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
149436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getVoiceNetworkTypeUsingSubId(long subId) {
149536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getVoiceNetworkType();
14967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true if a ICC card is present
15007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean hasIccCard() {
150236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME Make changes to pass defaultSimId of type int
150336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return hasIccCardUsingSlotId(getDefaultSubscription());
150436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
150536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
150636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
150736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true if a ICC card is present for a slotId
150836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
150936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean hasIccCardUsingSlotId(long slotId) {
151036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(slotId).getIccCard().hasIccCard();
15117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Return if the current radio is LTE on CDMA. This
15157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * is a tri-state return value as for a period of time
15167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * the mode may be unknown.
15177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
15187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1519e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * or {@link Phone#LTE_ON_CDMA_TRUE}
15207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getLteOnCdmaMode() {
152236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getLteOnCdmaModeUsingSubId(getDefaultSubscription());
152336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
152436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
152536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getLteOnCdmaModeUsingSubId(long subId) {
152636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getLteOnCdmaMode();
152736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
152836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
152936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setPhone(Phone phone) {
153036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone = phone;
153136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
153236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
153336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
153436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
153536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default subId, 0 in the case of single standby.
153636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
153736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private long getDefaultSubscription() {
153836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return SubscriptionManager.getDefaultSubId();
153936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
154036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
154136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private long getPreferredVoiceSubscription() {
154236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return SubscriptionManager.getDefaultVoiceSubId();
15437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1544f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1545f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1546f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1547f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1548f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public int getWhenToMakeWifiCalls() {
1549d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1550d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
1551f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
1552f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1553f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1554f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1555f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1556f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public void setWhenToMakeWifiCalls(int preference) {
1557d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1558d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        Settings.System.putInt(mPhone.getContext().getContentResolver(),
1559d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
1560f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    }
1561f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad
1562d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal    private static int getWhenToMakeWifiCallsDefaultPreference() {
1563da120f4e3d32ca97c5b4c21d6c505d834a29ab8dSantos Cordon        // TODO: Use a build property to choose this value.
15649829e880f73f76119ba76ba032db42aad042858fEvan Charlton        return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
1565f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
156669f68120b94cecb2d87fe856bc115714b4e77bcdShishir Agrawal
1567566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1568da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
1569a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1570566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1571566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + AID);
1572da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1573da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            CMD_OPEN_CHANNEL, AID);
1574da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + response);
1575da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return response;
1576566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1577566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1578566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1579566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public boolean iccCloseLogicalChannel(int channel) {
1580a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1581566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1582566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + channel);
1583566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1584566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return false;
1585566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1586e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
1587566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + success);
1588566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return success;
1589566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1590566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1591566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1592566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public String iccTransmitApduLogicalChannel(int channel, int cla,
1593566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            int command, int p1, int p2, int p3, String data) {
1594a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1595566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1596566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) {
1597566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1598566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1599566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " data=" + data);
1600566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1601566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1602566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1603566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            return "";
1604566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1605566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1606da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
1607566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1608566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1609566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1610566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // If the payload is null, there was an error. Indicate that by returning
1611566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // an empty string.
1612566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (response.payload == null) {
1613566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return "";
1614566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1615566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1616566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // Append the returned status code to the end of the response payload.
1617566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        String s = Integer.toHexString(
1618566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1619566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        s = IccUtils.bytesToHexString(response.payload) + s;
1620566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return s;
1621566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1622e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1623c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    @Override
1624da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1625da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                int p3, String data) {
1626da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1627da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1628da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1629da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1630da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1631da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1632da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1633da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1634da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1635da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccTransmitApduBasicChannel: " + response);
1636da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1637da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        // If the payload is null, there was an error. Indicate that by returning
1638da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        // an empty string.
1639da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (response.payload == null) {
1640da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal          return "";
1641da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1642da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1643da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        // Append the returned status code to the end of the response payload.
1644da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        String s = Integer.toHexString(
1645da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1646da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        s = IccUtils.bytesToHexString(response.payload) + s;
1647da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return s;
1648da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
1649da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1650da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
1651da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1652da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            String filePath) {
1653da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1654da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1655da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1656da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("Exchange SIM_IO " + fileID + ":" + command + " " +
1657da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                p1 + " " + p2 + " " + p3 + ":" + filePath);
1658da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1659da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1660da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response =
1661da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
1662da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    new IccAPDUArgument(fileID, command, -1, p1, p2, p3, filePath));
1663da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1664da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1665da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal          log("Exchange SIM_IO [R]" + response);
1666da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1667da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1668da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        byte[] result = null;
1669da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        int length = 2;
1670da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (response.payload != null) {
1671da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            length = 2 + response.payload.length;
1672da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
1673da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1674da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        } else {
1675da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
1676da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1677da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1678da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 1] = (byte) response.sw2;
1679da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 2] = (byte) response.sw1;
1680da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return result;
1681da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
1682da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1683da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
1684c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    public String sendEnvelopeWithStatus(String content) {
1685a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1686c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1687c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1688c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        if (response.payload == null) {
1689c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton          return "";
1690c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        }
1691c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1692c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        // Append the returned status code to the end of the response payload.
1693c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        String s = Integer.toHexString(
1694c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1695c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        s = IccUtils.bytesToHexString(response.payload) + s;
1696c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        return s;
1697c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    }
1698c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1699e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1700e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1701e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1702e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1703e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1704e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return the NV item as a String, or null on error.
1705e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1706e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1707e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public String nvReadItem(int itemID) {
1708a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1709e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID);
1710e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1711e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1712e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return value;
1713e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1714e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1715e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1716e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1717e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1718e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1719e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1720e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemValue the value to write, as a String
1721e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1722e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1723e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1724e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteItem(int itemID, String itemValue) {
1725a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1726e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1727e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1728e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                new Pair<Integer, String>(itemID, itemValue));
1729e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1730e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1731e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1732e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1733e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1734e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1735e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1736e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1737e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param preferredRoamingList byte array containing the new PRL
1738e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1739e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1740e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1741e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
1742a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1743e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1744e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1745e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1746e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1747e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1748e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1749e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1750e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Perform the specified type of NV config reset.
1751e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1752e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1753e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1754e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1755e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1756e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1757e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvResetConfig(int resetType) {
1758a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1759e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType);
1760e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1761e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1762e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1763e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
17647c27be317e8757948178815426d3a329c852b9eeJake Hamby
17657c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
176636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
176736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default sim, 0 in the case of single standby.
176836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
176936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDefaultSim() {
177036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        //TODO Need to get it from Telephony Devcontroller
177136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return 0;
177236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
177336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
177487fca6f34c10e43e4dcfdd3f4e35bd4050e19582ram    public String[] getPcscfAddress(String apnType) {
177536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceReadPermission();
177687fca6f34c10e43e4dcfdd3f4e35bd4050e19582ram        return mPhone.getPcscfAddress(apnType);
177736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
177836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
177936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setImsRegistrationState(boolean registered) {
178036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceModifyPermission();
178136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone.setImsRegistrationState(registered);
178236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
178336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
178436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
178584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Get the calculated preferred network type.
178684d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Used for debugging incorrect network type.
178784d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     *
178884d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * @return the preferred network type, defined in RILConstants.java.
178984d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     */
179084d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    @Override
179184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    public int getCalculatedPreferredNetworkType() {
179284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu        enforceReadPermission();
179384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu        return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext());
179484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    }
179584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu
179684d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    /**
17977c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Get the preferred network type.
17987c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
17997c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
18007c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return the preferred network type, defined in RILConstants.java.
18017c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
18027c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
18037c27be317e8757948178815426d3a329c852b9eeJake Hamby    public int getPreferredNetworkType() {
1804a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
18057c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType");
18067c27be317e8757948178815426d3a329c852b9eeJake Hamby        int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
18077c27be317e8757948178815426d3a329c852b9eeJake Hamby        int networkType = (result != null ? result[0] : -1);
18087c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType: " + networkType);
18097c27be317e8757948178815426d3a329c852b9eeJake Hamby        return networkType;
18107c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
18117c27be317e8757948178815426d3a329c852b9eeJake Hamby
18127c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
18137c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Set the preferred network type.
18147c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
18157c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
18167c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @param networkType the preferred network type, defined in RILConstants.java.
18177c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return true on success; false on any failure.
18187c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
18197c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
18207c27be317e8757948178815426d3a329c852b9eeJake Hamby    public boolean setPreferredNetworkType(int networkType) {
1821a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
18227c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: type " + networkType);
18237c27be317e8757948178815426d3a329c852b9eeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
18247c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
182580bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        if (success) {
182680bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
182780bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu                    Settings.Global.PREFERRED_NETWORK_MODE, networkType);
182880bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        }
18297c27be317e8757948178815426d3a329c852b9eeJake Hamby        return success;
18307c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
1831ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1832ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1833787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * Set the CDMA subscription source.
1834787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * Used for device supporting both NV and RUIM for CDMA.
1835787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     *
1836787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
1837787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * @return true on success; false on any failure.
1838787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     */
1839787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    @Override
1840787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    public boolean setCdmaSubscription(int subscriptionType) {
1841a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1842787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (DBG) log("setCdmaSubscription: type " + subscriptionType);
1843787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (subscriptionType != mPhone.CDMA_SUBSCRIPTION_RUIM_SIM &&
1844787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu            subscriptionType != mPhone.CDMA_SUBSCRIPTION_NV) {
1845787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu           loge("setCdmaSubscription: unsupported subscriptionType.");
1846787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu           return false;
1847787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        }
1848787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        Boolean success = (Boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION, subscriptionType);
1849787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (DBG) log("setCdmaSubscription: " + (success ? "ok" : "fail"));
1850787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (success) {
1851787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
1852787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    Settings.Global.CDMA_SUBSCRIPTION_MODE, subscriptionType);
1853787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        }
1854787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        return success;
1855787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    }
1856787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu
1857787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    /**
1858ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Set mobile data enabled
1859ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Used by the user through settings etc to turn on/off mobile data
1860ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1861ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @param enable {@code true} turn turn data on, else {@code false}
1862ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1863ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1864ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public void setDataEnabled(boolean enable) {
1865ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        enforceModifyPermission();
1866ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        mPhone.setDataEnabled(enable);
1867ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
1868ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1869ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1870646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Get whether mobile data is enabled.
1871646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     *
1872646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Note that this used to be available from ConnectivityService, gated by
1873646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * ACCESS_NETWORK_STATE permission, so this will accept either that or
1874646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * our MODIFY_PHONE_STATE.
1875ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1876ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @return {@code true} if data is enabled else {@code false}
1877ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1878ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1879ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public boolean getDataEnabled() {
1880646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        try {
1881646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1882646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1883646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        } catch (Exception e) {
1884646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1885646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1886646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        }
1887ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        return mPhone.getDataEnabled();
1888ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
188960f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal
189060f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    @Override
189160f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    public int hasCarrierPrivileges() {
1892eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1893eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
1894eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("hasCarrierPrivileges: No UICC");
1895eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1896eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
1897eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatusForCurrentTransaction(
1898f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                mPhone.getContext().getPackageManager());
189960f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    }
19002934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu
19012934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    @Override
19026d5a285c9ebe1d3a6952542b6cad3d6df51ac298Shishir Agrawal    public int checkCarrierPrivilegesForPackage(String pkgname) {
1903eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1904eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
1905eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("checkCarrierPrivilegesForPackage: No UICC");
1906eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1907eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
1908eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
19092934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    }
191089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
191189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
1912eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    public List<String> getCarrierPackageNamesForBroadcastIntent(Intent intent) {
1913eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1914eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        if (card == null) {
1915eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            loge("getCarrierPackageNamesForBroadcastIntent: No UICC");
1916eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            return null ;
1917eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        }
1918eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        return card.getCarrierPackageNamesForBroadcastIntent(
1919eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            mPhone.getContext().getPackageManager(), intent);
1920eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    }
1921eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal
1922eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    @Override
192389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
1924352d8cdf7ed125668d865f61172abfc31835c5a9Derek Tan        enforceModifyPermissionOrCarrierPrivilege();
192589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        if (enable) {
192689e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan            mSimplifiedNetworkSettings.add(subId);
192789e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        } else {
192889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan            mSimplifiedNetworkSettings.remove(subId);
192989e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        }
193089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    }
193189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
193289e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
193389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
193489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        enforceReadPermission();
193589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        return mSimplifiedNetworkSettings.contains(subId);
193689e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    }
19377226c84acb402f96e527650347391fa025294350Derek Tan
19387226c84acb402f96e527650347391fa025294350Derek Tan    @Override
19397226c84acb402f96e527650347391fa025294350Derek Tan    public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
1940352d8cdf7ed125668d865f61172abfc31835c5a9Derek Tan        enforceModifyPermissionOrCarrierPrivilege();
19417226c84acb402f96e527650347391fa025294350Derek Tan        mAdnRecordsForDisplay.put(subId, new AdnRecord(alphaTag, number));
19427226c84acb402f96e527650347391fa025294350Derek Tan    }
19437226c84acb402f96e527650347391fa025294350Derek Tan
19447226c84acb402f96e527650347391fa025294350Derek Tan    @Override
19457226c84acb402f96e527650347391fa025294350Derek Tan    public String getLine1NumberForDisplay(long subId) {
19467226c84acb402f96e527650347391fa025294350Derek Tan        enforceReadPermission();
19477226c84acb402f96e527650347391fa025294350Derek Tan        if (!mAdnRecordsForDisplay.containsKey(subId)) {
19487226c84acb402f96e527650347391fa025294350Derek Tan            return null;
19497226c84acb402f96e527650347391fa025294350Derek Tan        }
19507226c84acb402f96e527650347391fa025294350Derek Tan        AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
19517226c84acb402f96e527650347391fa025294350Derek Tan        if (adnRecord.getNumber() == null || adnRecord.getNumber().isEmpty()) {
19527226c84acb402f96e527650347391fa025294350Derek Tan            return null;
19537226c84acb402f96e527650347391fa025294350Derek Tan        }
19547226c84acb402f96e527650347391fa025294350Derek Tan        return adnRecord.getNumber();
19557226c84acb402f96e527650347391fa025294350Derek Tan    }
19567226c84acb402f96e527650347391fa025294350Derek Tan
19577226c84acb402f96e527650347391fa025294350Derek Tan    @Override
19587226c84acb402f96e527650347391fa025294350Derek Tan    public String getLine1AlphaTagForDisplay(long subId) {
19597226c84acb402f96e527650347391fa025294350Derek Tan        enforceReadPermission();
19607226c84acb402f96e527650347391fa025294350Derek Tan        if (!mAdnRecordsForDisplay.containsKey(subId)) {
19617226c84acb402f96e527650347391fa025294350Derek Tan            return null;
19627226c84acb402f96e527650347391fa025294350Derek Tan        }
19637226c84acb402f96e527650347391fa025294350Derek Tan        AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
19647226c84acb402f96e527650347391fa025294350Derek Tan        if (adnRecord.getAlphaTag() == null || adnRecord.getAlphaTag().isEmpty()) {
19657226c84acb402f96e527650347391fa025294350Derek Tan            return null;
19667226c84acb402f96e527650347391fa025294350Derek Tan        }
19677226c84acb402f96e527650347391fa025294350Derek Tan        return adnRecord.getAlphaTag();
19687226c84acb402f96e527650347391fa025294350Derek Tan    }
1969b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal
1970b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    @Override
1971b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    public boolean setOperatorBrandOverride(String iccId, String brand) {
1972b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1973b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal        return mPhone.setOperatorBrandOverride(iccId, brand);
1974b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    }
19754bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
19764bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    @Override
19774bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
19784bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        enforceModifyPermission();
19794bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
19804bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        int returnValue = 0;
19814bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        try {
19824bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
19834bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(result.exception == null) {
19844bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if (result.result != null) {
19854bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    byte[] responseData = (byte[])(result.result);
19864bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    if(responseData.length > oemResp.length) {
19874bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
19884bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                responseData.length +  "bytes. Buffer Size is " +
19894bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                oemResp.length + "bytes.");
19904bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
19914bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
19924bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    returnValue = responseData.length;
19934bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                }
19944bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            } else {
19954bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                CommandException ex = (CommandException) result.exception;
19964bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                returnValue = ex.getCommandError().ordinal();
19974bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if(returnValue > 0) returnValue *= -1;
19984bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            }
19994bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        } catch (RuntimeException e) {
20004bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
20014bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
20024bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(returnValue > 0) returnValue *= -1;
20034bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        }
20044bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
20054bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        return returnValue;
20064bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    }
20077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
2008