PhoneInterfaceManager.java revision 97ebb427fc22f1f14eab7c79745dfcbf2eb2ff7a
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;
2497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tanimport android.content.SharedPreferences;
2560f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageInfo;
2660f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageManager;
2760f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.Signature;
2836469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport android.net.ConnectivityManager;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.net.Uri;
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Binder;
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Bundle;
337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
3436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.IBinder;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Looper;
367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Process;
3836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.RemoteException;
397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.ServiceManager;
407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.UserHandle;
4197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tanimport android.preference.PreferenceManager;
42f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.provider.Settings;
437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.CellInfo;
44da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawalimport android.telephony.IccOpenLogicalChannelResponse;
45e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.telephony.NeighboringCellInfo;
467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.ServiceState;
4736469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport android.telephony.SubscriptionManager;
48f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.telephony.TelephonyManager;
497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
51e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.util.Pair;
527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
53566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CallManager;
54566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CommandException;
5536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport com.android.internal.telephony.Connection;
567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.DefaultPhoneNotifier;
577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.ITelephony;
58e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.telephony.IccCard;
597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
6036469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.PhoneFactory;
6136469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.CallManager;
6236469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.CommandException;
637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneConstants;
6436469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.dataconnection.DctController;
657226c84acb402f96e527650347391fa025294350Derek Tanimport com.android.internal.telephony.uicc.AdnRecord;
66566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccIoResult;
67566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
68eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawalimport com.android.internal.telephony.uicc.UiccCard;
6960f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
70566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
71e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.util.HexDump;
727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7336469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
7436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
7636ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.HashMap;
7789e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tanimport java.util.HashSet;
7836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Iterator;
79e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport java.util.List;
8036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Map;
8189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tanimport java.util.Set;
827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Implementation of the ITelephony interface.
857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
86117fee7467c140dccdc66972f60031dae2d55b35Santos Cordonpublic class PhoneInterfaceManager extends ITelephony.Stub {
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "PhoneInterfaceManager";
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG_LOC = false;
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message codes used with mMainThreadHandler
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_PIN_MMI = 1;
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_ANSWER_RINGING_CALL = 4;
967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_END_CALL = 5;  // not used yet
977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_SILENCE_RINGER = 6;
98da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
99da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
100566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_OPEN_CHANNEL = 9;
101566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_OPEN_CHANNEL_DONE = 10;
102566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_CLOSE_CHANNEL = 11;
103566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
104e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_READ_ITEM = 13;
105e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_READ_ITEM_DONE = 14;
106e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_ITEM = 15;
107e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
108e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_CDMA_PRL = 17;
109e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
110e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_RESET_CONFIG = 19;
111e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
1127c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
1137c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
1147c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
1157c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
11635b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int CMD_SEND_ENVELOPE = 25;
11735b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int EVENT_SEND_ENVELOPE_DONE = 26;
1186b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
1196b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
1206b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
1216b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
1226b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_EXCHANGE_SIM_IO = 31;
1236b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
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
13497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    SharedPreferences carrierPrivilegeConfigs;
13597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
13697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
13797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX =
13897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            "carrier_simplified_network_settings_";
13989e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
14089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    /**
141566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * A request object to use for transmitting data to an ICC.
142566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
143566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final class IccAPDUArgument {
144566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public int channel, cla, command, p1, p2, p3;
145566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public String data;
146566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
147566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public IccAPDUArgument(int channel, int cla, int command,
148566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                int p1, int p2, int p3, String data) {
149566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.channel = channel;
150566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.cla = cla;
151566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.command = command;
152566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p1 = p1;
153566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p2 = p2;
154566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p3 = p3;
155566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.data = data;
156566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
157566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
158566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
159566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
1607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
1617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request after sending. The main thread will notify the request when it is complete.
1627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final class MainThreadRequest {
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The argument to use for the request */
1657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object argument;
1667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The result of the request that is run on the main thread */
1677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object result;
1687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public MainThreadRequest(Object argument) {
1707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            this.argument = argument;
1717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
174cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    private static final class IncomingThirdPartyCallArgs {
175cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final ComponentName component;
176cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callId;
177cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callerDisplayName;
178cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
179cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public IncomingThirdPartyCallArgs(ComponentName component, String callId,
180cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal                String callerDisplayName) {
181cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.component = component;
182cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callId = callId;
183cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callerDisplayName = callerDisplayName;
184cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        }
185cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    }
186cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
1877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A handler that processes messages on the main thread in the phone process. Since many
1897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
1907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * inbound binder threads to the main thread in the phone process.  The Binder thread
1917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
1927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * on, which will be notified when the operation completes and will contain the result of the
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request.
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * <p>If a MainThreadRequest object is provided in the msg.obj field,
1967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * note that request.result must be set to something non-null for the calling thread to
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * unblock.
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final class MainThreadHandler extends Handler {
2007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
2017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
2027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            MainThreadRequest request;
2037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message onCompleted;
2047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar;
205eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            UiccCard uiccCard = UiccController.getInstance().getUiccCard();
206da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            IccAPDUArgument iccArgument;
2077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
2097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_PIN_MMI:
2107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
211e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request.result = mPhone.handlePinMmi((String) request.argument);
2127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_NEIGHBORING_CELL:
2197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
2217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            request);
2227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mPhone.getNeighboringCids(onCompleted);
2237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NEIGHBORING_CELL_DONE:
2267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    ar = (AsyncResult) msg.obj;
2277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) ar.userObj;
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (ar.exception == null && ar.result != null) {
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.result = ar.result;
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // create an empty list to notify the waiting thread
232e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = new ArrayList<NeighboringCellInfo>(0);
2337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_ANSWER_RINGING_CALL:
2417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    answerRingingCallInternal();
2427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_SILENCE_RINGER:
2457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    silenceRingerInternal();
2467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_END_CALL:
2497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
250e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    boolean hungUp;
2517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    int phoneType = mPhone.getPhoneType();
2527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
2537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // CDMA: If the user presses the Power button we treat it as
2547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // ending the complete call session
2557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
2567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
2577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // GSM: End the call as per the Phone state
2587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangup(mCM);
2597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
2617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
2637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.result = hungUp;
2647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
270da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
271566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
272da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
273eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
274eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccTransmitApduLogicalChannel: No UICC");
275eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
276eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
277eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
278eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
279eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
280da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
281da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
282eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccTransmitApduLogicalChannel(
283da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.channel, iccArgument.cla, iccArgument.command,
284da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
285566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
286eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
287566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
288566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
289da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
290566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
291566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
292566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
293566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = ar.result;
294566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
295566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
296566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
297566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Empty response");
298e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
299566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: CommandException: " +
300e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
301566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
302566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Unknown exception");
303566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
304566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
305566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
306566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
307566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
308566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
309566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
310da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
311da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
312da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
313da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
314da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccTransmitApduBasicChannel: No UICC");
315da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
316da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
317da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
318da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
319da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
320da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
321da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
322da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccTransmitApduBasicChannel(
323da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
324da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p3, iccArgument.data, onCompleted);
325da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
326da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
327da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
328da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
329da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
330da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
331da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
332da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
333da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
334da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
335da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.result == null) {
336da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Empty response");
337da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else if (ar.exception instanceof CommandException) {
338da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: CommandException: " +
339da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                    ar.exception);
340da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else {
341da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Unknown exception");
342da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
343da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
344da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
345da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
346da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
347da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
348da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
349da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_EXCHANGE_SIM_IO:
350da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
351da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
352da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
353da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccExchangeSimIO: No UICC");
354da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
355da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
356da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
357da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
358da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
359da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
360da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                request);
361da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
362da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
363da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.data, onCompleted);
364da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
365da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
366da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
367da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_EXCHANGE_SIM_IO_DONE:
368da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
369da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
370da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
371da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
372da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
373da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6f, 0, (byte[])null);
374da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
375da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
376da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
377da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
378da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
379da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
3804d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case CMD_SEND_ENVELOPE:
3814d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) msg.obj;
382eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
383eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("sendEnvelopeWithStatus: No UICC");
384eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
385eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
386eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
387eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
388eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
389eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
390eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
391eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
3924d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
3934d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
3944d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case EVENT_SEND_ENVELOPE_DONE:
3954d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    ar = (AsyncResult) msg.obj;
3964d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) ar.userObj;
3979f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    if (ar.exception == null && ar.result != null) {
3989f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = ar.result;
3994d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    } else {
4009f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
4019f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        if (ar.result == null) {
4029f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: Empty response");
4039f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else if (ar.exception instanceof CommandException) {
4049f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: CommandException: " +
4059f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                                    ar.exception);
4069f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else {
4079f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: exception:" + ar.exception);
4089f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        }
4094d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4104d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    synchronized (request) {
4114d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                        request.notifyAll();
4124d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4134d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
4144d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
415566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_OPEN_CHANNEL:
416566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
417eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
418eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccOpenLogicalChannel: No UICC");
419eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
420eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
421eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
422eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
423eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
424eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
425eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
426eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
427566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
428566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
429566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_OPEN_CHANNEL_DONE:
430566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
431566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
432da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    IccOpenLogicalChannelResponse openChannelResp;
433566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
434da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int[] result = (int[]) ar.result;
435da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int channelId = result[0];
436da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        byte[] selectResponse = null;
437da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (result.length > 1) {
438da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            selectResponse = new byte[result.length - 1];
439da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            for (int i = 1; i < result.length; ++i) {
440da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                selectResponse[i - 1] = (byte) result[i];
441da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
442da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
443da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(channelId,
444527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                            IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
445566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
446566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
447566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Empty response");
448566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
449da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.exception != null) {
450da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccOpenLogicalChannel: Exception: " + ar.exception);
451da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
452da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
453527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                        int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
454da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if ((ar.exception != null) && (ar.exception instanceof CommandException)) {
455da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            if (ar.exception.getMessage().compareTo("MISSING_RESOURCE") == 0) {
456527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
457da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            } else if (ar.exception.getMessage().compareTo("NO_SUCH_ELEMENT") == 0) {
458527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
459da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
460da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
461da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(
462da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
463566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
46482c8a46052629d1450320c116d14c7353bfe4ea1Shishir Agrawal                    request.result = openChannelResp;
465566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
466566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
467566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
468566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
469566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
470566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_CLOSE_CHANNEL:
471566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
472eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
473eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccCloseLogicalChannel: No UICC");
474eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
475eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
476eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
477eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
478eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
479eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
480eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
481eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
482566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
483566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
484566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_CLOSE_CHANNEL_DONE:
485e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "iccCloseLogicalChannel");
486e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
487e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
488e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_READ_ITEM:
489e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
490e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
491e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvReadItem((Integer) request.argument, onCompleted);
492e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
493e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
494e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_READ_ITEM_DONE:
495566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
496566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
497e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    if (ar.exception == null && ar.result != null) {
498e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ar.result;     // String
499566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
500e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = "";
501e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        if (ar.result == null) {
502e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Empty response");
503e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
504e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: CommandException: " +
505e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
506566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
507e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Unknown exception");
508566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
509566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
510566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
511566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
512566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
513566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
514566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
515e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_ITEM:
516e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
517e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
518e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
519e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
520e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
521e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
522e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_ITEM_DONE:
523e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteItem");
524e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
525e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
526e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_CDMA_PRL:
527e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
528e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
529e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
530e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
531e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
532e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_CDMA_PRL_DONE:
533e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteCdmaPrl");
534e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
535e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
536e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_RESET_CONFIG:
537e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
538e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
539e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
540e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
541e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
542e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_RESET_CONFIG_DONE:
543e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvResetConfig");
544e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
545e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
5467c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_GET_PREFERRED_NETWORK_TYPE:
5477c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
5487c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
5497c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.getPreferredNetworkType(onCompleted);
5507c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5517c27be317e8757948178815426d3a329c852b9eeJake Hamby
5527c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
5537c27be317e8757948178815426d3a329c852b9eeJake Hamby                    ar = (AsyncResult) msg.obj;
5547c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) ar.userObj;
5557c27be317e8757948178815426d3a329c852b9eeJake Hamby                    if (ar.exception == null && ar.result != null) {
5567c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = ar.result;     // Integer
5577c27be317e8757948178815426d3a329c852b9eeJake Hamby                    } else {
5587c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = -1;
5597c27be317e8757948178815426d3a329c852b9eeJake Hamby                        if (ar.result == null) {
5607c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Empty response");
5617c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else if (ar.exception instanceof CommandException) {
5627c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: CommandException: " +
5637c27be317e8757948178815426d3a329c852b9eeJake Hamby                                    ar.exception);
5647c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else {
5657c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Unknown exception");
5667c27be317e8757948178815426d3a329c852b9eeJake Hamby                        }
5677c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
5687c27be317e8757948178815426d3a329c852b9eeJake Hamby                    synchronized (request) {
5697c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.notifyAll();
5707c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
5717c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5727c27be317e8757948178815426d3a329c852b9eeJake Hamby
5737c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_SET_PREFERRED_NETWORK_TYPE:
5747c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
5757c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
5767c27be317e8757948178815426d3a329c852b9eeJake Hamby                    int networkType = (Integer) request.argument;
5777c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.setPreferredNetworkType(networkType, onCompleted);
5787c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5797c27be317e8757948178815426d3a329c852b9eeJake Hamby
5807c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
5817c27be317e8757948178815426d3a329c852b9eeJake Hamby                    handleNullReturnEvent(msg, "setPreferredNetworkType");
5827c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5837c27be317e8757948178815426d3a329c852b9eeJake Hamby
5844bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
5854bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)msg.obj;
5864bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
5874bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
5884bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
5894bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
5904bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
5914bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    ar = (AsyncResult)msg.obj;
5924bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)ar.userObj;
5934bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request.result = ar;
5944bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    synchronized (request) {
5954bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        request.notifyAll();
5964bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
5974bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
5984bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
5997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                default:
6007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
6017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
6027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
604e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
605e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        private void handleNullReturnEvent(Message msg, String command) {
606e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            AsyncResult ar = (AsyncResult) msg.obj;
607e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            MainThreadRequest request = (MainThreadRequest) ar.userObj;
608e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            if (ar.exception == null) {
609e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = true;
610e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            } else {
611e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = false;
612e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                if (ar.exception instanceof CommandException) {
613e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": CommandException: " + ar.exception);
614e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                } else {
615e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": Unknown exception");
616e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                }
617e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
618e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            synchronized (request) {
619e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.notifyAll();
620e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
621e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        }
6227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread,
6267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * waits for the request to complete, and returns the result.
6277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequestAsync
6287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Object sendRequest(int command, Object argument) {
630500b0e04406d2995c1f29dea95c98cedaa669f74Santos Cordon        return sendRequest(command, argument, null);
63136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
63236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
63336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
63436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Posts the specified command to be executed on the main thread,
63536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * waits for the request to complete, and returns the result.
63636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @see #sendRequestAsync
63736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
63836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private Object sendRequest(int command, Object argument, Object argument2) {
6397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
6407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            throw new RuntimeException("This method will deadlock if called from the main thread.");
6417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        MainThreadRequest request = new MainThreadRequest(argument);
6447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Message msg = mMainThreadHandler.obtainMessage(command, request);
6457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        msg.sendToTarget();
6467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Wait for the request to complete
6487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (request) {
6497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (request.result == null) {
6507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
6517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.wait();
6527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
6537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Do nothing, go back and wait until the request is complete
6547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
6557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return request.result;
6587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Asynchronous ("fire and forget") version of sendRequest():
6627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread, and
6637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * returns immediately.
6647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequest
6657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void sendRequestAsync(int command) {
6677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler.sendEmptyMessage(command);
6687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
671bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * Same as {@link #sendRequestAsync(int)} except it takes an argument.
672bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * @see {@link #sendRequest(int,Object)}
673bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     */
674bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    private void sendRequestAsync(int command, Object argument) {
675bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        MainThreadRequest request = new MainThreadRequest(argument);
676bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        Message msg = mMainThreadHandler.obtainMessage(command, request);
677bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        msg.sendToTarget();
678bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    }
679bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal
680bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    /**
6817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton PhoneInterfaceManager instance.
6827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
6837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
684194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
6857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (PhoneInterfaceManager.class) {
6867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
687194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal                sInstance = new PhoneInterfaceManager(app, phone);
6887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
6897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
6907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
6927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** Private constructor; @see init() */
696194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
6977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
6987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = phone;
6997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mCM = PhoneGlobals.getInstance().mCM;
7007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
7017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler = new MainThreadHandler();
70297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        carrierPrivilegeConfigs =
70397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
7047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        publish();
7057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void publish() {
7087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("publish: " + this);
7097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        ServiceManager.addService("phone", this);
7117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
71336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // returns phone associated with the subId.
71436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // getPhone(0) returns default phone in single SIM mode.
71536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private Phone getPhone(long subId) {
71636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME: hack for the moment
71736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return mPhone;
71836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // return PhoneUtils.getPhoneUsingSubId(subId);
71936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
7207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
7217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Implementation of the ITelephony interface.
7227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
7237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void dial(String number) {
72536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        dialUsingSubId(getPreferredVoiceSubscription(), number);
72636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
72736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
72836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void dialUsingSubId(long subId, String number) {
7297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("dial: " + number);
7307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: This is just a wrapper around the
7317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // ACTION_DIAL intent, which is available to any app since it puts up
7327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // the UI before it does anything.
7337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
7357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
7367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // PENDING: should we just silently fail if phone is offhook or ringing?
74036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        PhoneConstants.State state = mCM.getState(subId);
7417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
7427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
7437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
74436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville            intent.putExtra(SUBSCRIPTION_KEY, subId);
7457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.startActivity(intent);
7467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void call(String callingPackage, String number) {
75036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        callUsingSubId(getPreferredVoiceSubscription(), callingPackage, number);
75136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
75236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
75336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void callUsingSubId(long subId, String callingPackage, String number) {
7547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("call: " + number);
7557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // This is just a wrapper around the ACTION_CALL intent, but we still
7577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // need to do a permission check since we're calling startActivity()
7587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // from the context of the phone app.
7597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
7607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
7627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                != AppOpsManager.MODE_ALLOWED) {
7637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
7677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
7687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
77236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        intent.putExtra(SUBSCRIPTION_KEY, subId);
7737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
7747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.startActivity(intent);
7757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * End a call based on call state
7797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true is a call was ended
7807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean endCall() {
78236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return endCallUsingSubId(getDefaultSubscription());
78336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
78436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
78536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
78636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * End a call based on the call state of the subId
78736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true is a call was ended
78836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
78936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean endCallUsingSubId(long subId) {
7907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
79136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_END_CALL, subId, null);
7927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void answerRingingCall() {
79536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        answerRingingCallUsingSubId(getDefaultSubscription());
79636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
79736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
79836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void answerRingingCallUsingSubId(long subId) {
7997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("answerRingingCall...");
8007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
8017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // but that can probably wait till the big TelephonyManager API overhaul.
8027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.
8037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_ANSWER_RINGING_CALL);
8057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make the actual telephony calls to implement answerRingingCall().
8097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
8107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #answerRingingCall
8117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
8127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: it would be nice to return true if we answered the call, or
8137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * false if there wasn't actually a ringing incoming call, or some
8147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * other error occurred.  (In other words, pass back the return value
8157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
8167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * But that would require calling this method via sendRequest() rather
8177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * than sendRequestAsync(), and right now we don't actually *need* that
8187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * return value, so let's just return void for now.
8197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void answerRingingCallInternal() {
8217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final boolean hasRingingCall = !mPhone.getRingingCall().isIdle();
8227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (hasRingingCall) {
8237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasActiveCall = !mPhone.getForegroundCall().isIdle();
8247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasHoldingCall = !mPhone.getBackgroundCall().isIdle();
8257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (hasActiveCall && hasHoldingCall) {
8267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Both lines are in use!
8277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // TODO: provide a flag to let the caller specify what
8287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // policy to use if both lines are in use.  (The current
8297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // behavior is hardwired to "answer incoming, end ongoing",
8307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // which is how the CALL button is specced to behave.)
8317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
8327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
8337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
8347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // answerCall() will automatically hold the current active
8357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // call, if there is one.
8367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
8377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
8387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
8407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // No call was ringing.
8417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
8427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void silenceRinger() {
8467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("silenceRinger...");
8477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: find a more appropriate permission to check here.
8487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // (That can probably wait till the big TelephonyManager API overhaul.
8497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.)
8507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
8517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_SILENCE_RINGER);
8527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Internal implemenation of silenceRinger().
8567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
8577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #silenceRinger
8587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void silenceRingerInternal() {
8607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if ((mCM.getState() == PhoneConstants.State.RINGING)
8617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            && mApp.notifier.isRinging()) {
8627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Ringer is actually playing, so silence it.
8637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG) log("silenceRingerInternal: silencing...");
8647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.notifier.silenceRinger();
8657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isOffhook() {
86936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isOffhookUsingSubId(getDefaultSubscription());
87036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
87136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
87236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isOffhookUsingSubId(long subId) {
87336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
8747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRinging() {
87736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (isRingingUsingSubId(getDefaultSubscription()));
87836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
87936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
88036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isRingingUsingSubId(long subId) {
88136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
8827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isIdle() {
88536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isIdleUsingSubId(getDefaultSubscription());
88636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
88736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
88836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isIdleUsingSubId(long subId) {
88936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
8907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isSimPinEnabled() {
8937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceReadPermission();
8947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (PhoneGlobals.getInstance().isSimPinEnabled());
8957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean supplyPin(String pin) {
89836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPinUsingSubId(getDefaultSubscription(), pin);
89936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
90036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
90136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean supplyPinUsingSubId(long subId, String pin) {
90236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        int [] resultArray = supplyPinReportResultUsingSubId(subId, pin);
9039de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
9049de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
9059de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
9069de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public boolean supplyPuk(String puk, String pin) {
90736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPukUsingSubId(getDefaultSubscription(), puk, pin);
90836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
90936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
91036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean supplyPukUsingSubId(long subId, String puk, String pin) {
91136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        int [] resultArray = supplyPukReportResultUsingSubId(subId, puk, pin);
9129de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
9139de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
9149de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
9159de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
9169de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPinReportResult(String pin) {
91736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPinReportResultUsingSubId(getDefaultSubscription(), pin);
91836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
91936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
92036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int[] supplyPinReportResultUsingSubId(long subId, String pin) {
9217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
92236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
9237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPin.start();
9247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPin.unlockSim(null, pin);
9257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9279de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
9289de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPukReportResult(String puk, String pin) {
92936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPukReportResultUsingSubId(getDefaultSubscription(), puk, pin);
93036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
93136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
93236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin) {
9337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
93436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
9357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPuk.start();
9367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPuk.unlockSim(puk, pin);
9377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
9409de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville     * Helper thread to turn async call to SimCard#supplyPin into
9417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * a synchronous one.
9427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
9437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static class UnlockSim extends Thread {
9447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private final IccCard mSimCard;
9467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private boolean mDone = false;
9489de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
9499de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mRetryCount = -1;
9507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For replies from SimCard interface
9527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private Handler mHandler;
9537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For async handler to identify request type
9557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private static final int SUPPLY_PIN_COMPLETE = 100;
9567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public UnlockSim(IccCard simCard) {
9587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mSimCard = simCard;
9597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
9627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void run() {
9637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.prepare();
9647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            synchronized (UnlockSim.this) {
9657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mHandler = new Handler() {
9667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    @Override
9677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    public void handleMessage(Message msg) {
9687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        AsyncResult ar = (AsyncResult) msg.obj;
9697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        switch (msg.what) {
9707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            case SUPPLY_PIN_COMPLETE:
9717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
9727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                synchronized (UnlockSim.this) {
9739de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    mRetryCount = msg.arg1;
9749de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    if (ar.exception != null) {
9759de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        if (ar.exception instanceof CommandException &&
9769de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                ((CommandException)(ar.exception)).getCommandError()
9779de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                == CommandException.Error.PASSWORD_INCORRECT) {
9789de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
9799de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        } else {
9809de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_GENERAL_FAILURE;
9819de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        }
9829de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    } else {
9839de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        mResult = PhoneConstants.PIN_RESULT_SUCCESS;
9849de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    }
9857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mDone = true;
9867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    UnlockSim.this.notifyAll();
9877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
9887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                break;
9897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
9907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
9917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                };
9927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                UnlockSim.this.notifyAll();
9937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
9947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.loop();
9957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /*
9987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Use PIN or PUK to unlock SIM card
9997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
10007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is null, unlock SIM card with PIN
10017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
10027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is not null, unlock SIM card with PUK and set PIN code
10037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
10049de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        synchronized int[] unlockSim(String puk, String pin) {
10057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (mHandler == null) {
10077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
10087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
10097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
10107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
10117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
10127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
10147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (puk == null) {
10167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPin(pin, callback);
10177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
10187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPuk(puk, pin, callback);
10197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (!mDone) {
10227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
10237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.d(LOG_TAG, "wait for done");
10247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
10257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
10267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Restore the interrupted status
10277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
10287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
10297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Log.d(LOG_TAG, "done");
10319de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            int[] resultArray = new int[2];
10329de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[0] = mResult;
10339de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[1] = mRetryCount;
10349de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            return resultArray;
10357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void updateServiceLocation() {
103936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        updateServiceLocationUsingSubId(getDefaultSubscription());
104036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
104136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
104236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
104336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void updateServiceLocationUsingSubId(long subId) {
10447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: this call is harmless, and it's
10457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // needed for the ServiceState.requestStateUpdate() call (which is
10467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // already intentionally exposed to 3rd parties.)
104736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).updateServiceLocation();
10487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRadioOn() {
105136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isRadioOnUsingSubId(getDefaultSubscription());
105236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
105336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
105436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isRadioOnUsingSubId(long subId) {
105536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
10567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void toggleRadioOnOff() {
105936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        toggleRadioOnOffUsingSubId(getDefaultSubscription());
106036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
106136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
106236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
106336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void toggleRadioOnOffUsingSubId(long subId) {
10647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
106536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(!isRadioOnUsingSubId(subId));
10667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
106736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
10687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadio(boolean turnOn) {
106936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return setRadioUsingSubId(getDefaultSubscription(), turnOn);
107036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
107136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
107236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean setRadioUsingSubId(long subId, boolean turnOn) {
10737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
107436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        if ((getPhone(subId).getServiceState().getState() !=
107536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                ServiceState.STATE_POWER_OFF) != turnOn) {
107636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville            toggleRadioOnOffUsingSubId(subId);
10777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
10797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
108036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
10811fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    public boolean needMobileRadioShutdown() {
10821fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        /*
10831fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         * If any of the Radios are available, it will need to be
10841fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         * shutdown. So return true if any Radio is available.
10851fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         */
10861fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
10871fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            Phone phone = PhoneFactory.getPhone(i);
10881fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            if (phone != null && phone.isRadioAvailable()) return true;
10891fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
10901fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
10911fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        return false;
10921fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
10931fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
10941fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    public void shutdownMobileRadios() {
10951fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
10961fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            logv("Shutting down Phone " + i);
10971fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            shutdownRadioUsingPhoneId(i);
10981fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
10991fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
11001fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
11011fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    private void shutdownRadioUsingPhoneId(int phoneId) {
11021fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        enforceModifyPermission();
11031fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        Phone phone = PhoneFactory.getPhone(phoneId);
11041fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        if (phone != null && phone.isRadioAvailable()) {
11051fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            phone.shutdownRadio();
11061fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
11071fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
11081fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
11097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadioPower(boolean turnOn) {
111036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return setRadioPowerUsingSubId(getDefaultSubscription(), turnOn);
111136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
111236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
111336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean setRadioPowerUsingSubId(long subId, boolean turnOn) {
11147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
111536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(turnOn);
11167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
111936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
11207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean enableDataConnectivity() {
11217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
112236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
112336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(true);
11247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
112736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
11287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean disableDataConnectivity() {
11297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
113036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
113136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(false);
11327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
113536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
11367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isDataConnectivityPossible() {
113736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
113836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).isDataConnectivityPossible();
11397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean handlePinMmi(String dialString) {
114236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return handlePinMmiUsingSubId(getDefaultSubscription(), dialString);
114336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
114436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
114536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean handlePinMmiUsingSubId(long subId, String dialString) {
11467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
114736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
11487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCallState() {
115136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCallStateUsingSubId(getDefaultSubscription());
115236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
115336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
115436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCallStateUsingSubId(long subId) {
115536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
11567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataState() {
115936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
116036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
11617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataActivity() {
116436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
116536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
11667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public Bundle getCellLocation() {
11707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
11717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
11727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
11737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
11747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
11757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
11767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
11777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
11787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
11797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1181e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
11827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: is active user");
11837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Bundle data = new Bundle();
11847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mPhone.getCellLocation().fillInNotifierBundle(data);
11857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return data;
11867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
11877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: suppress non-active user");
11887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
11897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void enableLocationUpdates() {
119436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enableLocationUpdatesUsingSubId(getDefaultSubscription());
119536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
119636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
119736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void enableLocationUpdatesUsingSubId(long subId) {
11987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
11997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
120036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).enableLocationUpdates();
12017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
12047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void disableLocationUpdates() {
120536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        disableLocationUpdatesUsingSubId(getDefaultSubscription());
120636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
120736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
120836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void disableLocationUpdatesUsingSubId(long subId) {
12097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
12107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
121136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).disableLocationUpdates();
12127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
12157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @SuppressWarnings("unchecked")
12167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
12177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
12187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_FINE_LOCATION, null);
12207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
12217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check
12227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // for ACCESS_COARSE_LOCATION
12237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from
12247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // ACCESS_COARSE_LOCATION since this is the weaker precondition
12257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
12277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
12307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                callingPackage) != AppOpsManager.MODE_ALLOWED) {
12317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1233e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
12347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: is active user");
12357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ArrayList<NeighboringCellInfo> cells = null;
12377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
12397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                cells = (ArrayList<NeighboringCellInfo>) sendRequest(
124036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                        CMD_HANDLE_NEIGHBORING_CELL, null, null);
12417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (RuntimeException e) {
124236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
12437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
12447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return cells;
12457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
12467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
12477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
12537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<CellInfo> getAllCellInfo() {
12547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
12557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
12577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
12587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
12597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
12607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
12617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
12627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
12637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1265e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
12667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: is active user");
12677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return mPhone.getAllCellInfo();
12687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
12697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
12707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1274bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    @Override
12757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void setCellInfoListRate(int rateInMillis) {
12767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setCellInfoListRate(rateInMillis);
12777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
12807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Internal helper methods.
12817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
12827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1283e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static boolean checkIfCallerIsSelfOrForegroundUser() {
12847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean ok;
12857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean self = Binder.getCallingUid() == Process.myUid();
12877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!self) {
12887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Get the caller's user id then clear the calling identity
12897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // which will be restored in the finally clause.
12907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int callingUser = UserHandle.getCallingUserId();
12917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            long ident = Binder.clearCallingIdentity();
12927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
12947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // With calling identity cleared the current user is the foreground user.
12957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                int foregroundUser = ActivityManager.getCurrentUser();
12967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = (foregroundUser == callingUser);
12977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) {
12987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
12997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            + " callingUser=" + callingUser + " ok=" + ok);
13007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
13017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (Exception ex) {
13027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
13037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = false;
13047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } finally {
13057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Binder.restoreCallingIdentity(ident);
13067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
13077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
13087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
13097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ok = true;
13107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
13127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return ok;
13137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the READ_PHONE_STATE permission.
13177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
13197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceReadPermission() {
13217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
13227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the MODIFY_PHONE_STATE permission.
13267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
13287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceModifyPermission() {
13307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
13317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1334a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure either system app or the caller has carrier privilege.
1335a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1336a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission/privilege
1337a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1338a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceModifyPermissionOrCarrierPrivilege() {
1339f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        int permission = mApp.checkCallingOrSelfPermission(
1340f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                android.Manifest.permission.MODIFY_PHONE_STATE);
1341f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (permission == PackageManager.PERMISSION_GRANTED) {
1342f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            return;
1343f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        }
1344f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal
1345f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        log("No modify permission, check carrier privilege next.");
1346f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1347f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1348f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No modify permission or carrier privilege.");
1349a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1350a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1351a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1352a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
1353a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure the caller has carrier privilege.
1354a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1355a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission
1356a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1357a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceCarrierPrivilege() {
1358a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1359f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1360f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No Carrier Privilege.");
1361a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1362a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1363a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1364a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
13657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the CALL_PHONE permission.
13667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
13687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceCallPermission() {
13707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
13717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1373566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
137436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
137536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     *
137636ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * @throws SecurityException if the caller does not have the required permission
137736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     */
137836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    private void enforcePrivilegedPhoneStatePermission() {
137936ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
138036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal                null);
138136ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    }
138236ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal
13837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private String createTelUrl(String number) {
13847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TextUtils.isEmpty(number)) {
13857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
13867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1388e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return "tel:" + number;
13897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1391f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void log(String msg) {
13927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
13937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13951fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    private static void logv(String msg) {
13961fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
13971fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
13981fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
1399f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void loge(String msg) {
14007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
14017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getActivePhoneType() {
140436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getActivePhoneTypeUsingSubId(getDefaultSubscription());
140536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
140636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
140736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getActivePhoneTypeUsingSubId(long subId) {
140836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getPhoneType();
14097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon index to display
14137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconIndex() {
141536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriIconIndexUsingSubId(getDefaultSubscription());
141636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
141736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
141836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
141936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCdmaEriIconIndexUsingSubId(long subId) {
142036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconIndex();
14217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon mode,
14257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 0 - ON
14267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 1 - FLASHING
14277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconMode() {
142936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriIconModeUsingSubId(getDefaultSubscription());
143036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
143136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
143236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCdmaEriIconModeUsingSubId(long subId) {
143336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconMode();
14347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI text,
14387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public String getCdmaEriText() {
144036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriTextUsingSubId(getDefaultSubscription());
144136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
144236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
144336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public String getCdmaEriTextUsingSubId(long subId) {
144436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriText();
14457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1448ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     * Returns the CDMA MDN.
1449ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     */
1450ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    public String getCdmaMdn(long subId) {
1451ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1452ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1453ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return getPhone(subId).getLine1Number();
1454ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        } else {
1455ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return null;
1456ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        }
1457ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    }
1458ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu
1459ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    /**
1460ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     * Returns the CDMA MIN.
1461ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     */
1462ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    public String getCdmaMin(long subId) {
1463ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1464ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1465ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return getPhone(subId).getCdmaMin();
1466ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        } else {
1467ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return null;
1468ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        }
1469ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    }
1470ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu
1471ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    /**
14727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns true if CDMA provisioning needs to run.
14737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean needsOtaServiceProvisioning() {
14757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.needsOtaServiceProvisioning();
14767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the unread count of voicemails
14807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceMessageCount() {
148236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getVoiceMessageCountUsingSubId(getDefaultSubscription());
148336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
148436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
148536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
148636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the unread count of voicemails for a subId
148736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
148836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getVoiceMessageCountUsingSubId( long subId) {
148936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getVoiceMessageCount();
14907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
14947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
14957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
14967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getNetworkType() {
149936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getNetworkTypeUsingSubId(getDefaultSubscription());
150036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
150136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
150236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
150336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the network type for a subId
150436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
150536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
150636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getNetworkTypeUsingSubId(long subId) {
150736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
15087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
15127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
15147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataNetworkType() {
151536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getDataNetworkTypeUsingSubId(getDefaultSubscription());
151636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
151736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
151836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
151936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the data network type for a subId
152036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
152136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
152236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDataNetworkTypeUsingSubId(long subId) {
152336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
15247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
15287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
15307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceNetworkType() {
153136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getVoiceNetworkTypeUsingSubId(getDefaultSubscription());
153236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
153336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
153436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
153536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the Voice network type for a subId
153636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
153736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
153836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getVoiceNetworkTypeUsingSubId(long subId) {
153936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getVoiceNetworkType();
15407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true if a ICC card is present
15447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean hasIccCard() {
154636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME Make changes to pass defaultSimId of type int
154736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return hasIccCardUsingSlotId(getDefaultSubscription());
154836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
154936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
155036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
155136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true if a ICC card is present for a slotId
155236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
155336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean hasIccCardUsingSlotId(long slotId) {
155436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(slotId).getIccCard().hasIccCard();
15557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Return if the current radio is LTE on CDMA. This
15597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * is a tri-state return value as for a period of time
15607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * the mode may be unknown.
15617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
15627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1563e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * or {@link Phone#LTE_ON_CDMA_TRUE}
15647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getLteOnCdmaMode() {
156636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getLteOnCdmaModeUsingSubId(getDefaultSubscription());
156736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
156836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
156936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getLteOnCdmaModeUsingSubId(long subId) {
157036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getLteOnCdmaMode();
157136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
157236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
157336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setPhone(Phone phone) {
157436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone = phone;
157536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
157636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
157736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
157836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
157936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default subId, 0 in the case of single standby.
158036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
158136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private long getDefaultSubscription() {
158236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return SubscriptionManager.getDefaultSubId();
158336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
158436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
158536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private long getPreferredVoiceSubscription() {
158636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return SubscriptionManager.getDefaultVoiceSubId();
15877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1588f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1589f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1590f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1591f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1592f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public int getWhenToMakeWifiCalls() {
1593d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1594d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
1595f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
1596f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1597f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1598f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1599f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1600f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public void setWhenToMakeWifiCalls(int preference) {
1601d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1602d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        Settings.System.putInt(mPhone.getContext().getContentResolver(),
1603d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
1604f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    }
1605f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad
1606d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal    private static int getWhenToMakeWifiCallsDefaultPreference() {
1607da120f4e3d32ca97c5b4c21d6c505d834a29ab8dSantos Cordon        // TODO: Use a build property to choose this value.
16089829e880f73f76119ba76ba032db42aad042858fEvan Charlton        return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
1609f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
161069f68120b94cecb2d87fe856bc115714b4e77bcdShishir Agrawal
1611566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1612da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
1613a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1614566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1615566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + AID);
1616da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1617da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            CMD_OPEN_CHANNEL, AID);
1618da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + response);
1619da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return response;
1620566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1621566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1622566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1623566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public boolean iccCloseLogicalChannel(int channel) {
1624a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1625566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1626566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + channel);
1627566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1628566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return false;
1629566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1630e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
1631566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + success);
1632566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return success;
1633566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1634566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1635566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1636566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public String iccTransmitApduLogicalChannel(int channel, int cla,
1637566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            int command, int p1, int p2, int p3, String data) {
1638a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1639566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1640566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) {
1641566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1642566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1643566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " data=" + data);
1644566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1645566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1646566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1647566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            return "";
1648566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1649566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1650da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
1651566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1652566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1653566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1654566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // Append the returned status code to the end of the response payload.
1655566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        String s = Integer.toHexString(
1656566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
16575ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        if (response.payload != null) {
16585ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal            s = IccUtils.bytesToHexString(response.payload) + s;
16595ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        }
1660566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return s;
1661566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1662e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1663c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    @Override
1664da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1665da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                int p3, String data) {
1666da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1667da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1668da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1669da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1670da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1671da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1672da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1673da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1674da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1675da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccTransmitApduBasicChannel: " + response);
1676da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1677da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        // Append the returned status code to the end of the response payload.
1678da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        String s = Integer.toHexString(
1679da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
16805ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        if (response.payload != null) {
16815ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal            s = IccUtils.bytesToHexString(response.payload) + s;
16825ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        }
1683da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return s;
1684da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
1685da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1686da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
1687da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1688da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            String filePath) {
1689da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1690da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1691da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1692da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("Exchange SIM_IO " + fileID + ":" + command + " " +
1693da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                p1 + " " + p2 + " " + p3 + ":" + filePath);
1694da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1695da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1696da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response =
1697da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
1698da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    new IccAPDUArgument(fileID, command, -1, p1, p2, p3, filePath));
1699da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1700da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1701da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal          log("Exchange SIM_IO [R]" + response);
1702da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1703da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1704da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        byte[] result = null;
1705da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        int length = 2;
1706da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (response.payload != null) {
1707da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            length = 2 + response.payload.length;
1708da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
1709da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1710da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        } else {
1711da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
1712da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1713da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1714da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 1] = (byte) response.sw2;
1715da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 2] = (byte) response.sw1;
1716da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return result;
1717da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
1718da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1719da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
1720c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    public String sendEnvelopeWithStatus(String content) {
1721a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1722c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1723c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1724c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        if (response.payload == null) {
1725c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton          return "";
1726c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        }
1727c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1728c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        // Append the returned status code to the end of the response payload.
1729c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        String s = Integer.toHexString(
1730c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1731c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        s = IccUtils.bytesToHexString(response.payload) + s;
1732c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        return s;
1733c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    }
1734c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1735e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1736e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1737e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1738e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1739e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1740e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return the NV item as a String, or null on error.
1741e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1742e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1743e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public String nvReadItem(int itemID) {
1744a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1745e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID);
1746e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1747e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1748e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return value;
1749e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1750e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1751e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1752e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1753e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1754e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1755e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1756e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemValue the value to write, as a String
1757e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1758e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1759e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1760e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteItem(int itemID, String itemValue) {
1761a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1762e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1763e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1764e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                new Pair<Integer, String>(itemID, itemValue));
1765e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1766e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1767e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1768e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1769e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1770e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1771e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1772e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1773e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param preferredRoamingList byte array containing the new PRL
1774e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1775e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1776e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1777e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
1778a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1779e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1780e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1781e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1782e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1783e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1784e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1785e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1786e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Perform the specified type of NV config reset.
1787e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1788e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1789e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1790e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1791e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1792e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1793e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvResetConfig(int resetType) {
1794a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1795e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType);
1796e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1797e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1798e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1799e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
18007c27be317e8757948178815426d3a329c852b9eeJake Hamby
18017c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
180236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
180336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default sim, 0 in the case of single standby.
180436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
180536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDefaultSim() {
180636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        //TODO Need to get it from Telephony Devcontroller
180736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return 0;
180836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
180936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
181087fca6f34c10e43e4dcfdd3f4e35bd4050e19582ram    public String[] getPcscfAddress(String apnType) {
181136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceReadPermission();
181287fca6f34c10e43e4dcfdd3f4e35bd4050e19582ram        return mPhone.getPcscfAddress(apnType);
181336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
181436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
181536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setImsRegistrationState(boolean registered) {
181636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceModifyPermission();
181736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone.setImsRegistrationState(registered);
181836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
181936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
182036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
182184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Get the calculated preferred network type.
182284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Used for debugging incorrect network type.
182384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     *
182484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * @return the preferred network type, defined in RILConstants.java.
182584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     */
182684d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    @Override
182784d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    public int getCalculatedPreferredNetworkType() {
182884d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu        enforceReadPermission();
182984d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu        return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext());
183084d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    }
183184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu
183284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    /**
18337c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Get the preferred network type.
18347c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
18357c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
18367c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return the preferred network type, defined in RILConstants.java.
18377c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
18387c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
18397c27be317e8757948178815426d3a329c852b9eeJake Hamby    public int getPreferredNetworkType() {
1840a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
18417c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType");
18427c27be317e8757948178815426d3a329c852b9eeJake Hamby        int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
18437c27be317e8757948178815426d3a329c852b9eeJake Hamby        int networkType = (result != null ? result[0] : -1);
18447c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType: " + networkType);
18457c27be317e8757948178815426d3a329c852b9eeJake Hamby        return networkType;
18467c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
18477c27be317e8757948178815426d3a329c852b9eeJake Hamby
18487c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
18497c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Set the preferred network type.
18507c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
18517c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
18527c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @param networkType the preferred network type, defined in RILConstants.java.
18537c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return true on success; false on any failure.
18547c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
18557c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
18567c27be317e8757948178815426d3a329c852b9eeJake Hamby    public boolean setPreferredNetworkType(int networkType) {
1857a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
18587c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: type " + networkType);
18597c27be317e8757948178815426d3a329c852b9eeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
18607c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
186180bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        if (success) {
186280bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
186380bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu                    Settings.Global.PREFERRED_NETWORK_MODE, networkType);
186480bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        }
18657c27be317e8757948178815426d3a329c852b9eeJake Hamby        return success;
18667c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
1867ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1868ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1869ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Set mobile data enabled
1870ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Used by the user through settings etc to turn on/off mobile data
1871ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1872ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @param enable {@code true} turn turn data on, else {@code false}
1873ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1874ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1875ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public void setDataEnabled(boolean enable) {
1876ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        enforceModifyPermission();
1877ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        mPhone.setDataEnabled(enable);
1878ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
1879ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1880ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1881646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Get whether mobile data is enabled.
1882646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     *
1883646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Note that this used to be available from ConnectivityService, gated by
1884646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * ACCESS_NETWORK_STATE permission, so this will accept either that or
1885646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * our MODIFY_PHONE_STATE.
1886ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1887ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @return {@code true} if data is enabled else {@code false}
1888ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1889ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1890ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public boolean getDataEnabled() {
1891646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        try {
1892646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1893646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1894646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        } catch (Exception e) {
1895646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1896646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1897646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        }
1898ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        return mPhone.getDataEnabled();
1899ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
190060f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal
190160f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    @Override
190260f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    public int hasCarrierPrivileges() {
1903eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1904eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
1905eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("hasCarrierPrivileges: No UICC");
1906eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1907eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
1908eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatusForCurrentTransaction(
1909f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                mPhone.getContext().getPackageManager());
191060f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    }
19112934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu
19122934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    @Override
19136d5a285c9ebe1d3a6952542b6cad3d6df51ac298Shishir Agrawal    public int checkCarrierPrivilegesForPackage(String pkgname) {
1914eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1915eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
1916eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("checkCarrierPrivilegesForPackage: No UICC");
1917eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1918eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
1919eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
19202934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    }
192189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
192289e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
1923af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero    public List<String> getCarrierPackageNamesForIntent(Intent intent) {
1924eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1925eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        if (card == null) {
1926af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero            loge("getCarrierPackageNamesForIntent: No UICC");
1927eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            return null ;
1928eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        }
1929af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero        return card.getCarrierPackageNamesForIntent(
1930eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            mPhone.getContext().getPackageManager(), intent);
1931eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    }
1932eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal
193397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private String getIccId(long subId) {
193497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        UiccCard card = getPhone(subId).getUiccCard();
193597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (card == null) {
193697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            loge("getIccId: No UICC");
193797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return null;
193897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
193997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = card.getIccId();
194097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (TextUtils.isEmpty(iccId)) {
194197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            loge("getIccId: ICC ID is null or empty.");
194297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return null;
194397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
194497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return iccId;
194597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    }
194697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
1947eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    @Override
194889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
1949352d8cdf7ed125668d865f61172abfc31835c5a9Derek Tan        enforceModifyPermissionOrCarrierPrivilege();
195097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
195197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
195297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
195397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
195497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
195597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            if (enable) {
195697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                editor.putBoolean(snsPrefKey, true);
195797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            } else {
195897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                editor.remove(snsPrefKey);
195997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            }
196097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            editor.commit();
196189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        }
196289e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    }
196389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
196489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
196589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
196689e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        enforceReadPermission();
196797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
196897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
196997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String snsPrefKey = PREF_CARRIERS_SIMPLIFIED_NETWORK_SETTINGS_PREFIX + iccId;
197097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return carrierPrivilegeConfigs.getBoolean(snsPrefKey, false);
197197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
197297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return false;
197389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    }
19747226c84acb402f96e527650347391fa025294350Derek Tan
19757226c84acb402f96e527650347391fa025294350Derek Tan    @Override
19767226c84acb402f96e527650347391fa025294350Derek Tan    public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
1977352d8cdf7ed125668d865f61172abfc31835c5a9Derek Tan        enforceModifyPermissionOrCarrierPrivilege();
197897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
197997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
198097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
198197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
198297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            SharedPreferences.Editor editor = carrierPrivilegeConfigs.edit();
198397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            if (alphaTag == null) {
198497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                editor.remove(alphaTagPrefKey);
198597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            } else {
198697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                editor.putString(alphaTagPrefKey, alphaTag);
198797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            }
198897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
198997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
199097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            if (number == null) {
199197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                editor.remove(numberPrefKey);
199297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            } else {
199397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                editor.putString(numberPrefKey, number);
199497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            }
199597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            editor.commit();
199697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
19977226c84acb402f96e527650347391fa025294350Derek Tan    }
19987226c84acb402f96e527650347391fa025294350Derek Tan
19997226c84acb402f96e527650347391fa025294350Derek Tan    @Override
20007226c84acb402f96e527650347391fa025294350Derek Tan    public String getLine1NumberForDisplay(long subId) {
20017226c84acb402f96e527650347391fa025294350Derek Tan        enforceReadPermission();
200297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
200397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
200497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
200597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
200697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return carrierPrivilegeConfigs.getString(numberPrefKey, null);
20077226c84acb402f96e527650347391fa025294350Derek Tan        }
200897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return null;
20097226c84acb402f96e527650347391fa025294350Derek Tan    }
20107226c84acb402f96e527650347391fa025294350Derek Tan
20117226c84acb402f96e527650347391fa025294350Derek Tan    @Override
20127226c84acb402f96e527650347391fa025294350Derek Tan    public String getLine1AlphaTagForDisplay(long subId) {
20137226c84acb402f96e527650347391fa025294350Derek Tan        enforceReadPermission();
201497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
201597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
201697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
201797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
201897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return carrierPrivilegeConfigs.getString(alphaTagPrefKey, null);
20197226c84acb402f96e527650347391fa025294350Derek Tan        }
202097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return null;
20217226c84acb402f96e527650347391fa025294350Derek Tan    }
2022b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal
2023b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    @Override
2024a3dfd75141d37ae7e170eeb200374f62235b092eShishir Agrawal    public boolean setOperatorBrandOverride(String brand) {
2025b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
2026a3dfd75141d37ae7e170eeb200374f62235b092eShishir Agrawal        return mPhone.setOperatorBrandOverride(brand);
2027b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    }
20284bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
20294bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    @Override
20304bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
20314bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        enforceModifyPermission();
20324bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
20334bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        int returnValue = 0;
20344bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        try {
20354bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
20364bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(result.exception == null) {
20374bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if (result.result != null) {
20384bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    byte[] responseData = (byte[])(result.result);
20394bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    if(responseData.length > oemResp.length) {
20404bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
20414bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                responseData.length +  "bytes. Buffer Size is " +
20424bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                oemResp.length + "bytes.");
20434bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
20444bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
20454bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    returnValue = responseData.length;
20464bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                }
20474bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            } else {
20484bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                CommandException ex = (CommandException) result.exception;
20494bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                returnValue = ex.getCommandError().ordinal();
20504bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if(returnValue > 0) returnValue *= -1;
20514bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            }
20524bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        } catch (RuntimeException e) {
20534bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
20544bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
20554bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(returnValue > 0) returnValue *= -1;
20564bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        }
20574bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
20584bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        return returnValue;
20594bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    }
20607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
2061