PhoneInterfaceManager.java revision eb6439a7bd453313f7ed7972d30e2478243801ff
17d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/*
27d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Copyright (C) 2006 The Android Open Source Project
37d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
47d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
57d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * you may not use this file except in compliance with the License.
67d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * You may obtain a copy of the License at
77d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
87d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
97d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Unless required by applicable law or agreed to in writing, software
117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * See the License for the specific language governing permissions and
147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * limitations under the License.
157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpackage com.android.phone;
187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.ActivityManager;
207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.AppOpsManager;
21bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepalimport android.content.ComponentName;
227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Context;
237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Intent;
2460f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageInfo;
2560f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageManager;
2660f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.Signature;
2736469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport android.net.ConnectivityManager;
287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.net.Uri;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Binder;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Bundle;
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
3336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.IBinder;
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Looper;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Process;
3736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport android.os.RemoteException;
387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.ServiceManager;
397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.UserHandle;
40f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.provider.Settings;
417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.CellInfo;
42e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.telephony.NeighboringCellInfo;
437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.ServiceState;
4436469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport android.telephony.SubscriptionManager;
45f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.telephony.TelephonyManager;
467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
48e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.util.Pair;
497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
50566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CallManager;
51566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CommandException;
5236ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport com.android.internal.telephony.Connection;
537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.DefaultPhoneNotifier;
547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.ITelephony;
55e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.telephony.IccCard;
567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
5736469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.PhoneFactory;
5836469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.CallManager;
5936469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.CommandException;
607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneConstants;
6136469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.dataconnection.DctController;
627226c84acb402f96e527650347391fa025294350Derek Tanimport com.android.internal.telephony.uicc.AdnRecord;
63566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccIoResult;
64566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
65eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawalimport com.android.internal.telephony.uicc.UiccCard;
6660f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport com.android.internal.telephony.uicc.UiccCarrierPrivilegeRules;
67566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
68e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.util.HexDump;
697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7036469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
7136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
7336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.HashMap;
7489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tanimport java.util.HashSet;
7536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Iterator;
76e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport java.util.List;
7736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Pealimport java.util.Map;
7889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tanimport java.util.Set;
797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Implementation of the ITelephony interface.
827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
83117fee7467c140dccdc66972f60031dae2d55b35Santos Cordonpublic class PhoneInterfaceManager extends ITelephony.Stub {
847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "PhoneInterfaceManager";
857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG_LOC = false;
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message codes used with mMainThreadHandler
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_PIN_MMI = 1;
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_ANSWER_RINGING_CALL = 4;
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_END_CALL = 5;  // not used yet
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_SILENCE_RINGER = 6;
95566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_TRANSMIT_APDU = 7;
96566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_DONE = 8;
97566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_OPEN_CHANNEL = 9;
98566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_OPEN_CHANNEL_DONE = 10;
99566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_CLOSE_CHANNEL = 11;
100566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
101e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_READ_ITEM = 13;
102e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_READ_ITEM_DONE = 14;
103e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_ITEM = 15;
104e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
105e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_CDMA_PRL = 17;
106e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
107e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_RESET_CONFIG = 19;
108e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
1097c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
1107c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
1117c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
1127c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
11335b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int CMD_SEND_ENVELOPE = 25;
11435b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int EVENT_SEND_ENVELOPE_DONE = 26;
115787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    private static final int CMD_SET_CDMA_SUBSCRIPTION = 27;
116787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    private static final int EVENT_SET_CDMA_SUBSCRIPTION_DONE = 28;
1177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The singleton instance. */
1197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static PhoneInterfaceManager sInstance;
1207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    PhoneGlobals mApp;
1227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    Phone mPhone;
1237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    CallManager mCM;
1247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    AppOpsManager mAppOps;
1257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    MainThreadHandler mMainThreadHandler;
1267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
12889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan     * Indicates if Android should display a simplified Mobile Network Settings UI in a specific
12989e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan     * subscription.
13089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan     */
13189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    Set<Long> mSimplifiedNetworkSettings;
1327226c84acb402f96e527650347391fa025294350Derek Tan    Map<Long, AdnRecord> mAdnRecordsForDisplay;
13389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
13489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    /**
135566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * A request object to use for transmitting data to an ICC.
136566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
137566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final class IccAPDUArgument {
138566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public int channel, cla, command, p1, p2, p3;
139566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public String data;
140566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
141566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public IccAPDUArgument(int channel, int cla, int command,
142566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                int p1, int p2, int p3, String data) {
143566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.channel = channel;
144566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.cla = cla;
145566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.command = command;
146566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p1 = p1;
147566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p2 = p2;
148566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p3 = p3;
149566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.data = data;
150566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
151566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
152566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
153566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
1547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
1557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request after sending. The main thread will notify the request when it is complete.
1567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final class MainThreadRequest {
1587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The argument to use for the request */
1597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object argument;
1607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The result of the request that is run on the main thread */
1617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object result;
1627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public MainThreadRequest(Object argument) {
1647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            this.argument = argument;
1657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
168cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    private static final class IncomingThirdPartyCallArgs {
169cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final ComponentName component;
170cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callId;
171cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callerDisplayName;
172cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
173cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public IncomingThirdPartyCallArgs(ComponentName component, String callId,
174cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal                String callerDisplayName) {
175cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.component = component;
176cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callId = callId;
177cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callerDisplayName = callerDisplayName;
178cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        }
179cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    }
180cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
1817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A handler that processes messages on the main thread in the phone process. Since many
1837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
1847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * inbound binder threads to the main thread in the phone process.  The Binder thread
1857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
1867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * on, which will be notified when the operation completes and will contain the result of the
1877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request.
1887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
1897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * <p>If a MainThreadRequest object is provided in the msg.obj field,
1907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * note that request.result must be set to something non-null for the calling thread to
1917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * unblock.
1927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final class MainThreadHandler extends Handler {
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
1967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            MainThreadRequest request;
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message onCompleted;
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar;
199eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            UiccCard uiccCard = UiccController.getInstance().getUiccCard();
2007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
2027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_PIN_MMI:
2037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
204e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request.result = mPhone.handlePinMmi((String) request.argument);
2057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_NEIGHBORING_CELL:
2127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
2137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
2147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            request);
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mPhone.getNeighboringCids(onCompleted);
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NEIGHBORING_CELL_DONE:
2197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    ar = (AsyncResult) msg.obj;
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) ar.userObj;
2217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (ar.exception == null && ar.result != null) {
2227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.result = ar.result;
2237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // create an empty list to notify the waiting thread
225e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = new ArrayList<NeighboringCellInfo>(0);
2267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_ANSWER_RINGING_CALL:
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    answerRingingCallInternal();
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_SILENCE_RINGER:
2387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    silenceRingerInternal();
2397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_END_CALL:
2427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
243e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    boolean hungUp;
2447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    int phoneType = mPhone.getPhoneType();
2457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
2467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // CDMA: If the user presses the Power button we treat it as
2477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // ending the complete call session
2487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
2497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
2507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // GSM: End the call as per the Phone state
2517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangup(mCM);
2527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
2547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
2567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.result = hungUp;
2577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
263566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_TRANSMIT_APDU:
264566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
265566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    IccAPDUArgument argument = (IccAPDUArgument) request.argument;
266eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
267eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccTransmitApduLogicalChannel: No UICC");
268eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
269eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
270eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
271eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
272eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
273eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_DONE, request);
274eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccTransmitApduLogicalChannel(
275566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            argument.channel, argument.cla, argument.command,
276566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            argument.p1, argument.p2, argument.p3, argument.data,
277566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
278eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
279566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
280566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
281566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_TRANSMIT_APDU_DONE:
282566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
283566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
284566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
285566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = ar.result;
286566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
287566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
288566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
289566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Empty response");
290e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
291566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: CommandException: " +
292e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
293566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
294566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Unknown exception");
295566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
296566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
297566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
298566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
299566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
300566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
301566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
3024d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case CMD_SEND_ENVELOPE:
3034d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) msg.obj;
304eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
305eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("sendEnvelopeWithStatus: No UICC");
306eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
307eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
308eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
309eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
310eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
311eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
312eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
313eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
3144d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
3154d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
3164d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case EVENT_SEND_ENVELOPE_DONE:
3174d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    ar = (AsyncResult) msg.obj;
3184d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) ar.userObj;
3199f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    if (ar.exception == null && ar.result != null) {
3209f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = ar.result;
3214d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    } else {
3229f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
3239f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        if (ar.result == null) {
3249f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: Empty response");
3259f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else if (ar.exception instanceof CommandException) {
3269f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: CommandException: " +
3279f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                                    ar.exception);
3289f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else {
3299f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: exception:" + ar.exception);
3309f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        }
3314d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
3324d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    synchronized (request) {
3334d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                        request.notifyAll();
3344d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
3354d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
3364d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
337566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_OPEN_CHANNEL:
338566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
339eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
340eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccOpenLogicalChannel: No UICC");
341eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
342eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
343eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
344eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
345eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
346eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
347eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
348eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
349566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
350566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
351566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_OPEN_CHANNEL_DONE:
352566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
353566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
354566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
355e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ((int[]) ar.result)[0];
356566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
357e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = -1;
358566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
359566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Empty response");
360e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
361566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: CommandException: " +
362e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
363566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
364566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Unknown exception");
365566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
366566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
367566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
368566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
369566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
370566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
371566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
372566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_CLOSE_CHANNEL:
373566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
374eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
375eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccCloseLogicalChannel: No UICC");
376eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
377eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
378eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
379eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
380eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
381eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
382eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
383eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
384566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
385566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
386566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_CLOSE_CHANNEL_DONE:
387e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "iccCloseLogicalChannel");
388e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
389e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
390e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_READ_ITEM:
391e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
392e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
393e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvReadItem((Integer) request.argument, onCompleted);
394e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
395e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
396e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_READ_ITEM_DONE:
397566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
398566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
399e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    if (ar.exception == null && ar.result != null) {
400e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ar.result;     // String
401566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
402e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = "";
403e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        if (ar.result == null) {
404e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Empty response");
405e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
406e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: CommandException: " +
407e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
408566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
409e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Unknown exception");
410566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
411566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
412566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
413566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
414566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
415566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
416566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
417e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_ITEM:
418e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
419e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
420e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
421e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
422e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
423e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
424e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_ITEM_DONE:
425e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteItem");
426e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
427e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
428e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_CDMA_PRL:
429e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
430e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
431e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
432e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
433e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
434e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_CDMA_PRL_DONE:
435e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteCdmaPrl");
436e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
437e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
438e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_RESET_CONFIG:
439e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
440e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
441e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
442e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
443e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
444e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_RESET_CONFIG_DONE:
445e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvResetConfig");
446e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
447e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
4487c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_GET_PREFERRED_NETWORK_TYPE:
4497c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
4507c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
4517c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.getPreferredNetworkType(onCompleted);
4527c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4537c27be317e8757948178815426d3a329c852b9eeJake Hamby
4547c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
4557c27be317e8757948178815426d3a329c852b9eeJake Hamby                    ar = (AsyncResult) msg.obj;
4567c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) ar.userObj;
4577c27be317e8757948178815426d3a329c852b9eeJake Hamby                    if (ar.exception == null && ar.result != null) {
4587c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = ar.result;     // Integer
4597c27be317e8757948178815426d3a329c852b9eeJake Hamby                    } else {
4607c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = -1;
4617c27be317e8757948178815426d3a329c852b9eeJake Hamby                        if (ar.result == null) {
4627c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Empty response");
4637c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else if (ar.exception instanceof CommandException) {
4647c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: CommandException: " +
4657c27be317e8757948178815426d3a329c852b9eeJake Hamby                                    ar.exception);
4667c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else {
4677c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Unknown exception");
4687c27be317e8757948178815426d3a329c852b9eeJake Hamby                        }
4697c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
4707c27be317e8757948178815426d3a329c852b9eeJake Hamby                    synchronized (request) {
4717c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.notifyAll();
4727c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
4737c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4747c27be317e8757948178815426d3a329c852b9eeJake Hamby
4757c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_SET_PREFERRED_NETWORK_TYPE:
4767c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
4777c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
4787c27be317e8757948178815426d3a329c852b9eeJake Hamby                    int networkType = (Integer) request.argument;
4797c27be317e8757948178815426d3a329c852b9eeJake Hamby                    mPhone.setPreferredNetworkType(networkType, onCompleted);
4807c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4817c27be317e8757948178815426d3a329c852b9eeJake Hamby
4827c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
4837c27be317e8757948178815426d3a329c852b9eeJake Hamby                    handleNullReturnEvent(msg, "setPreferredNetworkType");
4847c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
4857c27be317e8757948178815426d3a329c852b9eeJake Hamby
486787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                case CMD_SET_CDMA_SUBSCRIPTION:
487787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    request = (MainThreadRequest) msg.obj;
488787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    onCompleted = obtainMessage(EVENT_SET_CDMA_SUBSCRIPTION_DONE, request);
489787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    int subscriptionType = (Integer) request.argument;
490787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    mPhone.setCdmaSubscription(subscriptionType, onCompleted);
491787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    break;
492787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu
493787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                case EVENT_SET_CDMA_SUBSCRIPTION_DONE:
494787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    handleNullReturnEvent(msg, "setCdmaSubscription");
495787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    break;
496787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu
4977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                default:
4987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
4997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
5007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
5017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
502e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
503e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        private void handleNullReturnEvent(Message msg, String command) {
504e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            AsyncResult ar = (AsyncResult) msg.obj;
505e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            MainThreadRequest request = (MainThreadRequest) ar.userObj;
506e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            if (ar.exception == null) {
507e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = true;
508e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            } else {
509e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = false;
510e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                if (ar.exception instanceof CommandException) {
511e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": CommandException: " + ar.exception);
512e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                } else {
513e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": Unknown exception");
514e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                }
515e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
516e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            synchronized (request) {
517e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.notifyAll();
518e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
519e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        }
5207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
5237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread,
5247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * waits for the request to complete, and returns the result.
5257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequestAsync
5267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
5277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Object sendRequest(int command, Object argument) {
528500b0e04406d2995c1f29dea95c98cedaa669f74Santos Cordon        return sendRequest(command, argument, null);
52936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
53036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
53136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
53236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Posts the specified command to be executed on the main thread,
53336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * waits for the request to complete, and returns the result.
53436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @see #sendRequestAsync
53536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
53636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private Object sendRequest(int command, Object argument, Object argument2) {
5377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
5387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            throw new RuntimeException("This method will deadlock if called from the main thread.");
5397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        MainThreadRequest request = new MainThreadRequest(argument);
5427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Message msg = mMainThreadHandler.obtainMessage(command, request);
5437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        msg.sendToTarget();
5447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Wait for the request to complete
5467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (request) {
5477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (request.result == null) {
5487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
5497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.wait();
5507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
5517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Do nothing, go back and wait until the request is complete
5527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
5537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
5547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return request.result;
5567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
5597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Asynchronous ("fire and forget") version of sendRequest():
5607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread, and
5617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * returns immediately.
5627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequest
5637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
5647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void sendRequestAsync(int command) {
5657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler.sendEmptyMessage(command);
5667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
569bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * Same as {@link #sendRequestAsync(int)} except it takes an argument.
570bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * @see {@link #sendRequest(int,Object)}
571bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     */
572bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    private void sendRequestAsync(int command, Object argument) {
573bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        MainThreadRequest request = new MainThreadRequest(argument);
574bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        Message msg = mMainThreadHandler.obtainMessage(command, request);
575bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        msg.sendToTarget();
576bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    }
577bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal
578bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    /**
5797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton PhoneInterfaceManager instance.
5807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
5817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
582194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
5837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (PhoneInterfaceManager.class) {
5847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
585194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal                sInstance = new PhoneInterfaceManager(app, phone);
5867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
5877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
5887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
5897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
5907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
5917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
5927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
5937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** Private constructor; @see init() */
594194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
5957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
5967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = phone;
5977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mCM = PhoneGlobals.getInstance().mCM;
59889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        mSimplifiedNetworkSettings = new HashSet<Long>();
5997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
6007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler = new MainThreadHandler();
6017226c84acb402f96e527650347391fa025294350Derek Tan        mAdnRecordsForDisplay = new HashMap<Long, AdnRecord>();
6027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        publish();
6037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void publish() {
6067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("publish: " + this);
6077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        ServiceManager.addService("phone", this);
6097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
61136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // returns phone associated with the subId.
61236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // getPhone(0) returns default phone in single SIM mode.
61336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private Phone getPhone(long subId) {
61436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME: hack for the moment
61536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return mPhone;
61636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // return PhoneUtils.getPhoneUsingSubId(subId);
61736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
6187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
6197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Implementation of the ITelephony interface.
6207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
6217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void dial(String number) {
62336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        dialUsingSubId(getPreferredVoiceSubscription(), number);
62436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
62536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
62636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void dialUsingSubId(long subId, String number) {
6277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("dial: " + number);
6287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: This is just a wrapper around the
6297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // ACTION_DIAL intent, which is available to any app since it puts up
6307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // the UI before it does anything.
6317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
6337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
6347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
6357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // PENDING: should we just silently fail if phone is offhook or ringing?
63836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        PhoneConstants.State state = mCM.getState(subId);
6397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
6407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
6417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
64236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville            intent.putExtra(SUBSCRIPTION_KEY, subId);
6437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.startActivity(intent);
6447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void call(String callingPackage, String number) {
64836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        callUsingSubId(getPreferredVoiceSubscription(), callingPackage, number);
64936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
65036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
65136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void callUsingSubId(long subId, String callingPackage, String number) {
6527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("call: " + number);
6537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // This is just a wrapper around the ACTION_CALL intent, but we still
6557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // need to do a permission check since we're calling startActivity()
6567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // from the context of the phone app.
6577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
6587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
6607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                != AppOpsManager.MODE_ALLOWED) {
6617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
6627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
6657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
6667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
6677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
6687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
67036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        intent.putExtra(SUBSCRIPTION_KEY, subId);
6717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
6727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.startActivity(intent);
6737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
6767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * End a call based on call state
6777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true is a call was ended
6787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
6797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean endCall() {
68036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return endCallUsingSubId(getDefaultSubscription());
68136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
68236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
68336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
68436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * End a call based on the call state of the subId
68536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true is a call was ended
68636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
68736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean endCallUsingSubId(long subId) {
6887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
68936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_END_CALL, subId, null);
6907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
6917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
6927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void answerRingingCall() {
69336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        answerRingingCallUsingSubId(getDefaultSubscription());
69436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
69536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
69636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void answerRingingCallUsingSubId(long subId) {
6977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("answerRingingCall...");
6987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
6997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // but that can probably wait till the big TelephonyManager API overhaul.
7007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.
7017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
7027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_ANSWER_RINGING_CALL);
7037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make the actual telephony calls to implement answerRingingCall().
7077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
7087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #answerRingingCall
7097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
7107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: it would be nice to return true if we answered the call, or
7117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * false if there wasn't actually a ringing incoming call, or some
7127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * other error occurred.  (In other words, pass back the return value
7137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
7147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * But that would require calling this method via sendRequest() rather
7157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * than sendRequestAsync(), and right now we don't actually *need* that
7167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * return value, so let's just return void for now.
7177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void answerRingingCallInternal() {
7197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        final boolean hasRingingCall = !mPhone.getRingingCall().isIdle();
7207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (hasRingingCall) {
7217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasActiveCall = !mPhone.getForegroundCall().isIdle();
7227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            final boolean hasHoldingCall = !mPhone.getBackgroundCall().isIdle();
7237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (hasActiveCall && hasHoldingCall) {
7247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Both lines are in use!
7257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // TODO: provide a flag to let the caller specify what
7267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // policy to use if both lines are in use.  (The current
7277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // behavior is hardwired to "answer incoming, end ongoing",
7287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // which is how the CALL button is specced to behave.)
7297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
7307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
7317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
7327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // answerCall() will automatically hold the current active
7337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // call, if there is one.
7347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
7357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
7367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
7377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
7387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // No call was ringing.
7397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
7407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void silenceRinger() {
7447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("silenceRinger...");
7457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: find a more appropriate permission to check here.
7467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // (That can probably wait till the big TelephonyManager API overhaul.
7477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.)
7487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
7497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        sendRequestAsync(CMD_SILENCE_RINGER);
7507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Internal implemenation of silenceRinger().
7547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
7557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #silenceRinger
7567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void silenceRingerInternal() {
7587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if ((mCM.getState() == PhoneConstants.State.RINGING)
7597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            && mApp.notifier.isRinging()) {
7607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Ringer is actually playing, so silence it.
7617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG) log("silenceRingerInternal: silencing...");
7627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.notifier.silenceRinger();
7637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isOffhook() {
76736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isOffhookUsingSubId(getDefaultSubscription());
76836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
76936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
77036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isOffhookUsingSubId(long subId) {
77136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
7727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRinging() {
77536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (isRingingUsingSubId(getDefaultSubscription()));
77636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
77736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
77836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isRingingUsingSubId(long subId) {
77936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
7807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isIdle() {
78336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isIdleUsingSubId(getDefaultSubscription());
78436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
78536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
78636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isIdleUsingSubId(long subId) {
78736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
7887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isSimPinEnabled() {
7917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceReadPermission();
7927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (PhoneGlobals.getInstance().isSimPinEnabled());
7937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean supplyPin(String pin) {
79636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPinUsingSubId(getDefaultSubscription(), pin);
79736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
79836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
79936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean supplyPinUsingSubId(long subId, String pin) {
80036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        int [] resultArray = supplyPinReportResultUsingSubId(subId, pin);
8019de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
8029de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
8039de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
8049de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public boolean supplyPuk(String puk, String pin) {
80536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPukUsingSubId(getDefaultSubscription(), puk, pin);
80636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
80736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
80836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean supplyPukUsingSubId(long subId, String puk, String pin) {
80936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        int [] resultArray = supplyPukReportResultUsingSubId(subId, puk, pin);
8109de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
8119de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
8129de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
8139de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
8149de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPinReportResult(String pin) {
81536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPinReportResultUsingSubId(getDefaultSubscription(), pin);
81636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
81736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
81836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int[] supplyPinReportResultUsingSubId(long subId, String pin) {
8197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
82036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
8217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPin.start();
8227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPin.unlockSim(null, pin);
8237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8259de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
8269de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPukReportResult(String puk, String pin) {
82736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return supplyPukReportResultUsingSubId(getDefaultSubscription(), puk, pin);
82836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
82936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
83036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int[] supplyPukReportResultUsingSubId(long subId, String puk, String pin) {
8317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
83236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
8337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPuk.start();
8347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPuk.unlockSim(puk, pin);
8357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8389de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville     * Helper thread to turn async call to SimCard#supplyPin into
8397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * a synchronous one.
8407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static class UnlockSim extends Thread {
8427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private final IccCard mSimCard;
8447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private boolean mDone = false;
8469de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
8479de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mRetryCount = -1;
8487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For replies from SimCard interface
8507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private Handler mHandler;
8517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For async handler to identify request type
8537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private static final int SUPPLY_PIN_COMPLETE = 100;
8547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public UnlockSim(IccCard simCard) {
8567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mSimCard = simCard;
8577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
8607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void run() {
8617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.prepare();
8627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            synchronized (UnlockSim.this) {
8637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mHandler = new Handler() {
8647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    @Override
8657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    public void handleMessage(Message msg) {
8667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        AsyncResult ar = (AsyncResult) msg.obj;
8677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        switch (msg.what) {
8687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            case SUPPLY_PIN_COMPLETE:
8697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
8707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                synchronized (UnlockSim.this) {
8719de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    mRetryCount = msg.arg1;
8729de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    if (ar.exception != null) {
8739de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        if (ar.exception instanceof CommandException &&
8749de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                ((CommandException)(ar.exception)).getCommandError()
8759de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                == CommandException.Error.PASSWORD_INCORRECT) {
8769de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
8779de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        } else {
8789de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_GENERAL_FAILURE;
8799de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        }
8809de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    } else {
8819de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        mResult = PhoneConstants.PIN_RESULT_SUCCESS;
8829de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    }
8837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mDone = true;
8847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    UnlockSim.this.notifyAll();
8857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
8867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                break;
8877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
8887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
8897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                };
8907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                UnlockSim.this.notifyAll();
8917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.loop();
8937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /*
8967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Use PIN or PUK to unlock SIM card
8977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
8987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is null, unlock SIM card with PIN
8997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
9007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is not null, unlock SIM card with PUK and set PIN code
9017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
9029de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        synchronized int[] unlockSim(String puk, String pin) {
9037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (mHandler == null) {
9057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
9067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
9077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
9087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
9097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
9107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
9117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
9127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (puk == null) {
9147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPin(pin, callback);
9157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
9167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPuk(puk, pin, callback);
9177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
9187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (!mDone) {
9207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
9217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.d(LOG_TAG, "wait for done");
9227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
9237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
9247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Restore the interrupted status
9257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
9267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
9277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
9287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Log.d(LOG_TAG, "done");
9299de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            int[] resultArray = new int[2];
9309de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[0] = mResult;
9319de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[1] = mRetryCount;
9329de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            return resultArray;
9337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void updateServiceLocation() {
93736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        updateServiceLocationUsingSubId(getDefaultSubscription());
93836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
93936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
94036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
94136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void updateServiceLocationUsingSubId(long subId) {
9427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: this call is harmless, and it's
9437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // needed for the ServiceState.requestStateUpdate() call (which is
9447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // already intentionally exposed to 3rd parties.)
94536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).updateServiceLocation();
9467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRadioOn() {
94936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return isRadioOnUsingSubId(getDefaultSubscription());
95036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
95136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
95236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean isRadioOnUsingSubId(long subId) {
95336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
9547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void toggleRadioOnOff() {
95736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        toggleRadioOnOffUsingSubId(getDefaultSubscription());
95836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
95936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
96036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
96136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void toggleRadioOnOffUsingSubId(long subId) {
9627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
96336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(!isRadioOnUsingSubId(subId));
9647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
96536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
9667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadio(boolean turnOn) {
96736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return setRadioUsingSubId(getDefaultSubscription(), turnOn);
96836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
96936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
97036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean setRadioUsingSubId(long subId, boolean turnOn) {
9717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
97236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        if ((getPhone(subId).getServiceState().getState() !=
97336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                ServiceState.STATE_POWER_OFF) != turnOn) {
97436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville            toggleRadioOnOffUsingSubId(subId);
9757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
9777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
97836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
9797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadioPower(boolean turnOn) {
98036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return setRadioPowerUsingSubId(getDefaultSubscription(), turnOn);
98136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
98236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
98336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean setRadioPowerUsingSubId(long subId, boolean turnOn) {
9847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
98536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(turnOn);
9867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
9877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
98936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
9907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean enableDataConnectivity() {
9917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
99236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
99336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(true);
9947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
9957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
99736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
9987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean disableDataConnectivity() {
9997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
100036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
100136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(false);
10027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
10037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
100536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
10067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isDataConnectivityPossible() {
100736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        long subId = SubscriptionManager.getDefaultDataSubId();
100836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).isDataConnectivityPossible();
10097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean handlePinMmi(String dialString) {
101236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return handlePinMmiUsingSubId(getDefaultSubscription(), dialString);
101336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
101436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
101536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean handlePinMmiUsingSubId(long subId, String dialString) {
10167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
101736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
10187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCallState() {
102136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCallStateUsingSubId(getDefaultSubscription());
102236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
102336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
102436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCallStateUsingSubId(long subId) {
102536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
10267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataState() {
102936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
103036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
10317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataActivity() {
103436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        Phone phone = getPhone(SubscriptionManager.getDefaultDataSubId());
103536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
10367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
10397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public Bundle getCellLocation() {
10407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
10417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
10427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
10437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
10447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
10457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
10467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
10477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
10487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
10497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1051e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
10527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: is active user");
10537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Bundle data = new Bundle();
10547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mPhone.getCellLocation().fillInNotifierBundle(data);
10557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return data;
10567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
10577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: suppress non-active user");
10587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
10597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
10637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void enableLocationUpdates() {
106436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enableLocationUpdatesUsingSubId(getDefaultSubscription());
106536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
106636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
106736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void enableLocationUpdatesUsingSubId(long subId) {
10687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
10697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
107036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).enableLocationUpdates();
10717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
10747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void disableLocationUpdates() {
107536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        disableLocationUpdatesUsingSubId(getDefaultSubscription());
107636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
107736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
107836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void disableLocationUpdatesUsingSubId(long subId) {
10797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
10807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
108136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).disableLocationUpdates();
10827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
10857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @SuppressWarnings("unchecked")
10867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
10877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
10887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
10897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_FINE_LOCATION, null);
10907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
10917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check
10927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // for ACCESS_COARSE_LOCATION
10937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from
10947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // ACCESS_COARSE_LOCATION since this is the weaker precondition
10957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
10967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
10977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
11007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                callingPackage) != AppOpsManager.MODE_ALLOWED) {
11017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
11027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
1103e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
11047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: is active user");
11057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ArrayList<NeighboringCellInfo> cells = null;
11077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
11097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                cells = (ArrayList<NeighboringCellInfo>) sendRequest(
111036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                        CMD_HANDLE_NEIGHBORING_CELL, null, null);
11117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (RuntimeException e) {
111236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
11137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
11147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return cells;
11157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
11167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
11177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
11187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
11237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<CellInfo> getAllCellInfo() {
11247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        try {
11257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
11267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_FINE_LOCATION, null);
11277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } catch (SecurityException e) {
11287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
11297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
11307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // is the weaker precondition
11317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.enforceCallingOrSelfPermission(
11327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
11337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1135e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
11367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: is active user");
11377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return mPhone.getAllCellInfo();
11387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
11397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
11407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
11417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1144bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    @Override
11457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void setCellInfoListRate(int rateInMillis) {
11467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setCellInfoListRate(rateInMillis);
11477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
11507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Internal helper methods.
11517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
11527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1153e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static boolean checkIfCallerIsSelfOrForegroundUser() {
11547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean ok;
11557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean self = Binder.getCallingUid() == Process.myUid();
11577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!self) {
11587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Get the caller's user id then clear the calling identity
11597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // which will be restored in the finally clause.
11607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int callingUser = UserHandle.getCallingUserId();
11617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            long ident = Binder.clearCallingIdentity();
11627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
11647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // With calling identity cleared the current user is the foreground user.
11657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                int foregroundUser = ActivityManager.getCurrentUser();
11667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = (foregroundUser == callingUser);
11677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) {
11687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
11697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            + " callingUser=" + callingUser + " ok=" + ok);
11707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
11717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (Exception ex) {
11727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
11737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = false;
11747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } finally {
11757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Binder.restoreCallingIdentity(ident);
11767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
11777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
11787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
11797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ok = true;
11807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
11827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return ok;
11837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the READ_PHONE_STATE permission.
11877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
11887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
11897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceReadPermission() {
11917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, null);
11927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the MODIFY_PHONE_STATE permission.
11967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
11977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
11987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceModifyPermission() {
12007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
12017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1204a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure either system app or the caller has carrier privilege.
1205a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1206a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission/privilege
1207a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1208a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceModifyPermissionOrCarrierPrivilege() {
1209f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        int permission = mApp.checkCallingOrSelfPermission(
1210f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                android.Manifest.permission.MODIFY_PHONE_STATE);
1211f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (permission == PackageManager.PERMISSION_GRANTED) {
1212f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            return;
1213f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        }
1214f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal
1215f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        log("No modify permission, check carrier privilege next.");
1216f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1217f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1218f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No modify permission or carrier privilege.");
1219a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1220a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1221a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1222a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
1223a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure the caller has carrier privilege.
1224a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1225a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission
1226a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1227a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceCarrierPrivilege() {
1228a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        if (hasCarrierPrivileges() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1229f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1230f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No Carrier Privilege.");
1231a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1232a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1233a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1234a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
12357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the CALL_PHONE permission.
12367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
12377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
12387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
12397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceCallPermission() {
12407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
12417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1243566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
124436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
124536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     *
124636ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * @throws SecurityException if the caller does not have the required permission
124736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     */
124836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    private void enforcePrivilegedPhoneStatePermission() {
124936ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
125036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal                null);
125136ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    }
125236ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal
12537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private String createTelUrl(String number) {
12547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TextUtils.isEmpty(number)) {
12557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1258e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return "tel:" + number;
12597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1261f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void log(String msg) {
12627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
12637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1265f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void loge(String msg) {
12667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
12677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getActivePhoneType() {
127036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getActivePhoneTypeUsingSubId(getDefaultSubscription());
127136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
127236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
127336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getActivePhoneTypeUsingSubId(long subId) {
127436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getPhoneType();
12757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
12787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon index to display
12797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
12807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconIndex() {
128136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriIconIndexUsingSubId(getDefaultSubscription());
128236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
128336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
128436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
128536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCdmaEriIconIndexUsingSubId(long subId) {
128636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconIndex();
12877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
12907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon mode,
12917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 0 - ON
12927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 1 - FLASHING
12937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
12947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconMode() {
129536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriIconModeUsingSubId(getDefaultSubscription());
129636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
129736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
129836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getCdmaEriIconModeUsingSubId(long subId) {
129936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconMode();
13007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI text,
13047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public String getCdmaEriText() {
130636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getCdmaEriTextUsingSubId(getDefaultSubscription());
130736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
130836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
130936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public String getCdmaEriTextUsingSubId(long subId) {
131036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriText();
13117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns true if CDMA provisioning needs to run.
13157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean needsOtaServiceProvisioning() {
13177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.needsOtaServiceProvisioning();
13187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the unread count of voicemails
13227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceMessageCount() {
132436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getVoiceMessageCountUsingSubId(getDefaultSubscription());
132536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
132636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
132736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
132836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the unread count of voicemails for a subId
132936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
133036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getVoiceMessageCountUsingSubId( long subId) {
133136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getVoiceMessageCount();
13327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
13367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
13377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
13387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
13407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getNetworkType() {
134136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getNetworkTypeUsingSubId(getDefaultSubscription());
134236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
134336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
134436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
134536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the network type for a subId
134636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
134736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
134836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getNetworkTypeUsingSubId(long subId) {
134936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
13507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
13547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
13567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataNetworkType() {
135736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getDataNetworkTypeUsingSubId(getDefaultSubscription());
135836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
135936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
136036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
136136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the data network type for a subId
136236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
136336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
136436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDataNetworkTypeUsingSubId(long subId) {
136536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
13667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
13707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
13727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceNetworkType() {
137336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getVoiceNetworkTypeUsingSubId(getDefaultSubscription());
137436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
137536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
137636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
137736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the Voice network type for a subId
137836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
137936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
138036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getVoiceNetworkTypeUsingSubId(long subId) {
138136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getVoiceNetworkType();
13827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
13857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true if a ICC card is present
13867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
13877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean hasIccCard() {
138836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME Make changes to pass defaultSimId of type int
138936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return hasIccCardUsingSlotId(getDefaultSubscription());
139036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
139136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
139236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
139336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true if a ICC card is present for a slotId
139436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
139536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public boolean hasIccCardUsingSlotId(long slotId) {
139636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(slotId).getIccCard().hasIccCard();
13977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Return if the current radio is LTE on CDMA. This
14017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * is a tri-state return value as for a period of time
14027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * the mode may be unknown.
14037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
14047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1405e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * or {@link Phone#LTE_ON_CDMA_TRUE}
14067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getLteOnCdmaMode() {
140836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getLteOnCdmaModeUsingSubId(getDefaultSubscription());
140936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
141036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
141136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getLteOnCdmaModeUsingSubId(long subId) {
141236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getLteOnCdmaMode();
141336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
141436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
141536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setPhone(Phone phone) {
141636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone = phone;
141736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
141836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
141936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
142036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
142136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default subId, 0 in the case of single standby.
142236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
142336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private long getDefaultSubscription() {
142436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return SubscriptionManager.getDefaultSubId();
142536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
142636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
142736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    private long getPreferredVoiceSubscription() {
142836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return SubscriptionManager.getDefaultVoiceSubId();
14297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1430f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1431f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1432f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1433f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1434f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public int getWhenToMakeWifiCalls() {
1435d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1436d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
1437f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
1438f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1439f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1440f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1441f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1442f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public void setWhenToMakeWifiCalls(int preference) {
1443d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1444d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        Settings.System.putInt(mPhone.getContext().getContentResolver(),
1445d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
1446f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    }
1447f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad
1448d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal    private static int getWhenToMakeWifiCallsDefaultPreference() {
1449d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        // TODO(sail): Use a build property to choose this value.
14509829e880f73f76119ba76ba032db42aad042858fEvan Charlton        return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
1451f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
145269f68120b94cecb2d87fe856bc115714b4e77bcdShishir Agrawal
1453566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1454566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public int iccOpenLogicalChannel(String AID) {
1455a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1456566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1457566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + AID);
1458566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        Integer channel = (Integer)sendRequest(CMD_OPEN_CHANNEL, AID);
1459566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + channel);
1460e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return channel;
1461566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1462566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1463566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1464566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public boolean iccCloseLogicalChannel(int channel) {
1465a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1466566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1467566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + channel);
1468566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1469566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return false;
1470566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1471e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
1472566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + success);
1473566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return success;
1474566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1475566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1476566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1477566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public String iccTransmitApduLogicalChannel(int channel, int cla,
1478566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            int command, int p1, int p2, int p3, String data) {
1479a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1480566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1481566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) {
1482566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1483566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1484566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " data=" + data);
1485566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1486566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1487566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1488566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            return "";
1489566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1490566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1491566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU,
1492566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1493566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1494566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1495566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // If the payload is null, there was an error. Indicate that by returning
1496566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // an empty string.
1497566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (response.payload == null) {
1498566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return "";
1499566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1500566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1501566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // Append the returned status code to the end of the response payload.
1502566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        String s = Integer.toHexString(
1503566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1504566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        s = IccUtils.bytesToHexString(response.payload) + s;
1505566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return s;
1506566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1507e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1508c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    @Override
1509c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    public String sendEnvelopeWithStatus(String content) {
1510a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1511c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1512c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1513c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        if (response.payload == null) {
1514c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton          return "";
1515c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        }
1516c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1517c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        // Append the returned status code to the end of the response payload.
1518c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        String s = Integer.toHexString(
1519c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1520c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        s = IccUtils.bytesToHexString(response.payload) + s;
1521c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        return s;
1522c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    }
1523c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1524e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1525e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1526e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1527e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1528e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1529e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return the NV item as a String, or null on error.
1530e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1531e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1532e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public String nvReadItem(int itemID) {
1533a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1534e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID);
1535e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1536e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1537e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return value;
1538e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1539e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1540e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1541e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1542e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1543e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1544e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1545e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemValue the value to write, as a String
1546e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1547e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1548e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1549e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteItem(int itemID, String itemValue) {
1550a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1551e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1552e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1553e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                new Pair<Integer, String>(itemID, itemValue));
1554e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1555e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1556e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1557e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1558e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1559e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1560e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1561e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1562e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param preferredRoamingList byte array containing the new PRL
1563e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1564e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1565e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1566e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
1567a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1568e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1569e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1570e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1571e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1572e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1573e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1574e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1575e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Perform the specified type of NV config reset.
1576e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1577e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1578e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1579e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1580e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1581e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1582e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvResetConfig(int resetType) {
1583a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1584e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType);
1585e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1586e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1587e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1588e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
15897c27be317e8757948178815426d3a329c852b9eeJake Hamby
15907c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
159136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
159236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default sim, 0 in the case of single standby.
159336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
159436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDefaultSim() {
159536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        //TODO Need to get it from Telephony Devcontroller
159636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return 0;
159736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
159836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
159936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public String[] getPcscfAddress() {
160036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceReadPermission();
160136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return mPhone.getPcscfAddress();
160236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
160336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
160436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setImsRegistrationState(boolean registered) {
160536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceModifyPermission();
160636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone.setImsRegistrationState(registered);
160736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
160836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
160936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
161084d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Get the calculated preferred network type.
161184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Used for debugging incorrect network type.
161284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     *
161384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * @return the preferred network type, defined in RILConstants.java.
161484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     */
161584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    @Override
161684d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    public int getCalculatedPreferredNetworkType() {
161784d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu        enforceReadPermission();
161884d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu        return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext());
161984d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    }
162084d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu
162184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    /**
16227c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Get the preferred network type.
16237c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
16247c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
16257c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return the preferred network type, defined in RILConstants.java.
16267c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
16277c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
16287c27be317e8757948178815426d3a329c852b9eeJake Hamby    public int getPreferredNetworkType() {
1629a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
16307c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType");
16317c27be317e8757948178815426d3a329c852b9eeJake Hamby        int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null);
16327c27be317e8757948178815426d3a329c852b9eeJake Hamby        int networkType = (result != null ? result[0] : -1);
16337c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType: " + networkType);
16347c27be317e8757948178815426d3a329c852b9eeJake Hamby        return networkType;
16357c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
16367c27be317e8757948178815426d3a329c852b9eeJake Hamby
16377c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
16387c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Set the preferred network type.
16397c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
16407c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
16417c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @param networkType the preferred network type, defined in RILConstants.java.
16427c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return true on success; false on any failure.
16437c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
16447c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
16457c27be317e8757948178815426d3a329c852b9eeJake Hamby    public boolean setPreferredNetworkType(int networkType) {
1646a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
16477c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: type " + networkType);
16487c27be317e8757948178815426d3a329c852b9eeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType);
16497c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
165080bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        if (success) {
165180bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
165280bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu                    Settings.Global.PREFERRED_NETWORK_MODE, networkType);
165380bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        }
16547c27be317e8757948178815426d3a329c852b9eeJake Hamby        return success;
16557c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
1656ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1657ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1658787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * Set the CDMA subscription source.
1659787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * Used for device supporting both NV and RUIM for CDMA.
1660787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     *
1661787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * @param subscriptionType the subscription type, 0 for RUIM, 1 for NV.
1662787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     * @return true on success; false on any failure.
1663787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu     */
1664787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    @Override
1665787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    public boolean setCdmaSubscription(int subscriptionType) {
1666a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1667787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (DBG) log("setCdmaSubscription: type " + subscriptionType);
1668787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (subscriptionType != mPhone.CDMA_SUBSCRIPTION_RUIM_SIM &&
1669787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu            subscriptionType != mPhone.CDMA_SUBSCRIPTION_NV) {
1670787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu           loge("setCdmaSubscription: unsupported subscriptionType.");
1671787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu           return false;
1672787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        }
1673787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        Boolean success = (Boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION, subscriptionType);
1674787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (DBG) log("setCdmaSubscription: " + (success ? "ok" : "fail"));
1675787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        if (success) {
1676787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
1677787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu                    Settings.Global.CDMA_SUBSCRIPTION_MODE, subscriptionType);
1678787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        }
1679787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu        return success;
1680787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    }
1681787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu
1682787bc7e2fd1cfbaeb16748663e190bf27aec06b2Junda Liu    /**
1683ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Set mobile data enabled
1684ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Used by the user through settings etc to turn on/off mobile data
1685ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1686ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @param enable {@code true} turn turn data on, else {@code false}
1687ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1688ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1689ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public void setDataEnabled(boolean enable) {
1690ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        enforceModifyPermission();
1691ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        mPhone.setDataEnabled(enable);
1692ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
1693ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1694ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1695646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Get whether mobile data is enabled.
1696646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     *
1697646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Note that this used to be available from ConnectivityService, gated by
1698646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * ACCESS_NETWORK_STATE permission, so this will accept either that or
1699646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * our MODIFY_PHONE_STATE.
1700ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
1701ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @return {@code true} if data is enabled else {@code false}
1702ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
1703ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
1704ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    public boolean getDataEnabled() {
1705646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        try {
1706646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
1707646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1708646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        } catch (Exception e) {
1709646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
1710646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
1711646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        }
1712ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        return mPhone.getDataEnabled();
1713ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
171460f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal
171560f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    @Override
171660f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    public int hasCarrierPrivileges() {
1717eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1718eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
1719eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("hasCarrierPrivileges: No UICC");
1720eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1721eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
1722eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatusForCurrentTransaction(
1723f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                mPhone.getContext().getPackageManager());
172460f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    }
17252934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu
17262934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    @Override
17276d5a285c9ebe1d3a6952542b6cad3d6df51ac298Shishir Agrawal    public int checkCarrierPrivilegesForPackage(String pkgname) {
1728eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1729eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
1730eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("checkCarrierPrivilegesForPackage: No UICC");
1731eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
1732eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
1733eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgname);
17342934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    }
173589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
173689e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
1737eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    public List<String> getCarrierPackageNamesForBroadcastIntent(Intent intent) {
1738eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard();
1739eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        if (card == null) {
1740eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            loge("getCarrierPackageNamesForBroadcastIntent: No UICC");
1741eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            return null ;
1742eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        }
1743eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        return card.getCarrierPackageNamesForBroadcastIntent(
1744eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            mPhone.getContext().getPackageManager(), intent);
1745eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    }
1746eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal
1747eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    @Override
174889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    public void enableSimplifiedNetworkSettings(long subId, boolean enable) {
1749352d8cdf7ed125668d865f61172abfc31835c5a9Derek Tan        enforceModifyPermissionOrCarrierPrivilege();
175089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        if (enable) {
175189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan            mSimplifiedNetworkSettings.add(subId);
175289e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        } else {
175389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan            mSimplifiedNetworkSettings.remove(subId);
175489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        }
175589e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    }
175689e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
175789e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
175889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    public boolean getSimplifiedNetworkSettingsEnabled(long subId) {
175989e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        enforceReadPermission();
176089e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan        return mSimplifiedNetworkSettings.contains(subId);
176189e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    }
17627226c84acb402f96e527650347391fa025294350Derek Tan
17637226c84acb402f96e527650347391fa025294350Derek Tan    @Override
17647226c84acb402f96e527650347391fa025294350Derek Tan    public void setLine1NumberForDisplay(long subId, String alphaTag, String number) {
1765352d8cdf7ed125668d865f61172abfc31835c5a9Derek Tan        enforceModifyPermissionOrCarrierPrivilege();
17667226c84acb402f96e527650347391fa025294350Derek Tan        mAdnRecordsForDisplay.put(subId, new AdnRecord(alphaTag, number));
17677226c84acb402f96e527650347391fa025294350Derek Tan    }
17687226c84acb402f96e527650347391fa025294350Derek Tan
17697226c84acb402f96e527650347391fa025294350Derek Tan    @Override
17707226c84acb402f96e527650347391fa025294350Derek Tan    public String getLine1NumberForDisplay(long subId) {
17717226c84acb402f96e527650347391fa025294350Derek Tan        enforceReadPermission();
17727226c84acb402f96e527650347391fa025294350Derek Tan        if (!mAdnRecordsForDisplay.containsKey(subId)) {
17737226c84acb402f96e527650347391fa025294350Derek Tan            return null;
17747226c84acb402f96e527650347391fa025294350Derek Tan        }
17757226c84acb402f96e527650347391fa025294350Derek Tan        AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
17767226c84acb402f96e527650347391fa025294350Derek Tan        if (adnRecord.getNumber() == null || adnRecord.getNumber().isEmpty()) {
17777226c84acb402f96e527650347391fa025294350Derek Tan            return null;
17787226c84acb402f96e527650347391fa025294350Derek Tan        }
17797226c84acb402f96e527650347391fa025294350Derek Tan        return adnRecord.getNumber();
17807226c84acb402f96e527650347391fa025294350Derek Tan    }
17817226c84acb402f96e527650347391fa025294350Derek Tan
17827226c84acb402f96e527650347391fa025294350Derek Tan    @Override
17837226c84acb402f96e527650347391fa025294350Derek Tan    public String getLine1AlphaTagForDisplay(long subId) {
17847226c84acb402f96e527650347391fa025294350Derek Tan        enforceReadPermission();
17857226c84acb402f96e527650347391fa025294350Derek Tan        if (!mAdnRecordsForDisplay.containsKey(subId)) {
17867226c84acb402f96e527650347391fa025294350Derek Tan            return null;
17877226c84acb402f96e527650347391fa025294350Derek Tan        }
17887226c84acb402f96e527650347391fa025294350Derek Tan        AdnRecord adnRecord = mAdnRecordsForDisplay.get(subId);
17897226c84acb402f96e527650347391fa025294350Derek Tan        if (adnRecord.getAlphaTag() == null || adnRecord.getAlphaTag().isEmpty()) {
17907226c84acb402f96e527650347391fa025294350Derek Tan            return null;
17917226c84acb402f96e527650347391fa025294350Derek Tan        }
17927226c84acb402f96e527650347391fa025294350Derek Tan        return adnRecord.getAlphaTag();
17937226c84acb402f96e527650347391fa025294350Derek Tan    }
1794b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal
1795b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    @Override
1796b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    public boolean setOperatorBrandOverride(String iccId, String brand) {
1797b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1798b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal        return mPhone.setOperatorBrandOverride(iccId, brand);
1799b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    }
18007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
1801