17d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/*
27d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Copyright (C) 2006 The Android Open Source Project
37d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
47d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Licensed under the Apache License, Version 2.0 (the "License");
57d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * you may not use this file except in compliance with the License.
67d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * You may obtain a copy of the License at
77d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
87d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *      http://www.apache.org/licenses/LICENSE-2.0
97d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon *
107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Unless required by applicable law or agreed to in writing, software
117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * distributed under the License is distributed on an "AS IS" BASIS,
127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * See the License for the specific language governing permissions and
147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * limitations under the License.
157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonpackage com.android.phone;
187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.ActivityManager;
207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.app.AppOpsManager;
21bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepalimport android.content.ComponentName;
227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Context;
237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.content.Intent;
2497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tanimport android.content.SharedPreferences;
2560f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawalimport android.content.pm.PackageManager;
267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.net.Uri;
277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.AsyncResult;
287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Binder;
297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Bundle;
307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Handler;
317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Looper;
327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Message;
337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.Process;
347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.ServiceManager;
357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.os.UserHandle;
36981d85874294656a51683ae6ecc6ba312d3635ceStuart Scottimport android.os.UserManager;
3797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tanimport android.preference.PreferenceManager;
38f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.provider.Settings;
397a1885ba88b4ca833d6dae8b352097636f242917Santos Cordonimport android.telecom.PhoneAccount;
409431b838f89399db2278c0436bd2817322a45f74Andrew Leeimport android.telecom.TelecomManager;
4112f7d80f47bdad9ed1c02b8b916f75e4f11fe873Junda Liuimport android.telephony.CarrierConfigManager;
427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.CellInfo;
43da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawalimport android.telephony.IccOpenLogicalChannelResponse;
44e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.telephony.NeighboringCellInfo;
455d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Savilleimport android.telephony.RadioAccessFamily;
467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.telephony.ServiceState;
470f3b5fcda1b76fbd6042f9a6f81f69d0b44bc3eeWink Savilleimport android.telephony.SubscriptionInfo;
4885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport android.telephony.SubscriptionManager;
49f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awadimport android.telephony.TelephonyManager;
507fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadhamimport android.telephony.ModemActivityInfo;
517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.text.TextUtils;
5285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport android.util.ArrayMap;
5385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport android.util.ArraySet;
547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport android.util.Log;
55e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport android.util.Pair;
5685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport android.util.Slog;
577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
58312e8177b25ab359627685d449e0a5fdb539809fAndrew Leeimport com.android.ims.ImsManager;
59566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CallManager;
60302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawalimport com.android.internal.telephony.CellNetworkScanResult;
61566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CommandException;
627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.DefaultPhoneNotifier;
637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.ITelephony;
64e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.telephony.IccCard;
651c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamathimport com.android.internal.telephony.MccTable;
66302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawalimport com.android.internal.telephony.OperatorInfo;
677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
6836469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.PhoneFactory;
695d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Savilleimport com.android.internal.telephony.ProxyController;
707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneConstants;
71b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganovimport com.android.internal.telephony.RILConstants;
72ac1bdfd36366426513d51bd2c4b107b00533889eWink Savilleimport com.android.internal.telephony.SubscriptionController;
73566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccIoResult;
74566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
75eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawalimport com.android.internal.telephony.uicc.UiccCard;
76566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
77e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.util.HexDump;
787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7936469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
8036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
8285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport java.util.Arrays;
83621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawalimport java.util.HashMap;
84621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawalimport java.util.Iterator;
85e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport java.util.List;
861c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamathimport java.util.Locale;
8785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport java.util.Map;
8885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport java.util.Objects;
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Implementation of the ITelephony interface.
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
93117fee7467c140dccdc66972f60031dae2d55b35Santos Cordonpublic class PhoneInterfaceManager extends ITelephony.Stub {
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "PhoneInterfaceManager";
957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG_LOC = false;
9785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    private static final boolean DBG_MERGE = false;
987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message codes used with mMainThreadHandler
1007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_PIN_MMI = 1;
1017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
1027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
1037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_ANSWER_RINGING_CALL = 4;
1047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_END_CALL = 5;  // not used yet
105da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
106da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
107566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_OPEN_CHANNEL = 9;
108566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_OPEN_CHANNEL_DONE = 10;
109566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_CLOSE_CHANNEL = 11;
110566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
111e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_READ_ITEM = 13;
112e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_READ_ITEM_DONE = 14;
113e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_ITEM = 15;
114e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
115e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_CDMA_PRL = 17;
116e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
117e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_RESET_CONFIG = 19;
118e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
1197c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
1207c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
1217c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
1227c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
12335b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int CMD_SEND_ENVELOPE = 25;
12435b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int EVENT_SEND_ENVELOPE_DONE = 26;
1256b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
1266b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
1276b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
1286b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
1296b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_EXCHANGE_SIM_IO = 31;
1306b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
13176d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
13276d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
13354788801de04c603a856596f4ae4377ab77a9821Stuart Scott    private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
13454788801de04c603a856596f4ae4377ab77a9821Stuart Scott    private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
1357fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
1367fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
137302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    private static final int CMD_PERFORM_NETWORK_SCAN = 39;
138302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
139302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
140302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
1417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The singleton instance. */
1437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static PhoneInterfaceManager sInstance;
1447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1453ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private PhoneGlobals mApp;
1463ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private Phone mPhone;
1473ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private CallManager mCM;
148981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott    private UserManager mUserManager;
1493ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private AppOpsManager mAppOps;
1503ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private MainThreadHandler mMainThreadHandler;
151ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville    private SubscriptionController mSubscriptionController;
1523ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private SharedPreferences mTelephonySharedPreferences;
1537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
15597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
15685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
157df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    private static final String PREF_ENABLE_VIDEO_CALLING = "enable_video_calling";
15889e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
15989e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    /**
160566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * A request object to use for transmitting data to an ICC.
161566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
162566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final class IccAPDUArgument {
163566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public int channel, cla, command, p1, p2, p3;
164566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public String data;
165566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
166566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public IccAPDUArgument(int channel, int cla, int command,
167566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                int p1, int p2, int p3, String data) {
168566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.channel = channel;
169566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.cla = cla;
170566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.command = command;
171566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p1 = p1;
172566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p2 = p2;
173566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p3 = p3;
174566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.data = data;
175566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
176566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
177566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
178566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
17977ba317277863812508869705308373b42364e0aShishir Agrawal     * A request object to use for transmitting data to an ICC.
18077ba317277863812508869705308373b42364e0aShishir Agrawal     */
18177ba317277863812508869705308373b42364e0aShishir Agrawal    private static final class ManualNetworkSelectionArgument {
18277ba317277863812508869705308373b42364e0aShishir Agrawal        public OperatorInfo operatorInfo;
18377ba317277863812508869705308373b42364e0aShishir Agrawal        public boolean persistSelection;
18477ba317277863812508869705308373b42364e0aShishir Agrawal
18577ba317277863812508869705308373b42364e0aShishir Agrawal        public ManualNetworkSelectionArgument(OperatorInfo operatorInfo, boolean persistSelection) {
18677ba317277863812508869705308373b42364e0aShishir Agrawal            this.operatorInfo = operatorInfo;
18777ba317277863812508869705308373b42364e0aShishir Agrawal            this.persistSelection = persistSelection;
18877ba317277863812508869705308373b42364e0aShishir Agrawal        }
18977ba317277863812508869705308373b42364e0aShishir Agrawal    }
19077ba317277863812508869705308373b42364e0aShishir Agrawal
19177ba317277863812508869705308373b42364e0aShishir Agrawal    /**
1927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request after sending. The main thread will notify the request when it is complete.
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final class MainThreadRequest {
1967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The argument to use for the request */
1977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object argument;
1987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The result of the request that is run on the main thread */
1997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object result;
20076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        /** The subscriber id that this request applies to. Null if default. */
20176d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        public Integer subId;
2027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public MainThreadRequest(Object argument) {
2047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            this.argument = argument;
2057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
20676d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
20776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        public MainThreadRequest(Object argument, Integer subId) {
20876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal            this.argument = argument;
20976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal            this.subId = subId;
21076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        }
2117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
2127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
213cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    private static final class IncomingThirdPartyCallArgs {
214cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final ComponentName component;
215cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callId;
216cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callerDisplayName;
217cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
218cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public IncomingThirdPartyCallArgs(ComponentName component, String callId,
219cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal                String callerDisplayName) {
220cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.component = component;
221cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callId = callId;
222cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callerDisplayName = callerDisplayName;
223cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        }
224cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    }
225cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
2267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
2277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A handler that processes messages on the main thread in the phone process. Since many
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * inbound binder threads to the main thread in the phone process.  The Binder thread
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * on, which will be notified when the operation completes and will contain the result of the
2327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request.
2337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * <p>If a MainThreadRequest object is provided in the msg.obj field,
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * note that request.result must be set to something non-null for the calling thread to
2367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * unblock.
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
2387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final class MainThreadHandler extends Handler {
2397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
2407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
2417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            MainThreadRequest request;
2427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message onCompleted;
2437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar;
24421409250c4001605606a37c3903dc22805410900Shishir Agrawal            UiccCard uiccCard = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
245da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            IccAPDUArgument iccArgument;
2467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
248716f67e149e8defd72262b7e7f875ea2aef57652Yorke Lee                case CMD_HANDLE_PIN_MMI: {
2497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
250716f67e149e8defd72262b7e7f875ea2aef57652Yorke Lee                    final Phone phone = getPhoneFromRequest(request);
251716f67e149e8defd72262b7e7f875ea2aef57652Yorke Lee                    request.result = phone != null ?
252716f67e149e8defd72262b7e7f875ea2aef57652Yorke Lee                            getPhoneFromRequest(request).handlePinMmi((String) request.argument)
253716f67e149e8defd72262b7e7f875ea2aef57652Yorke Lee                            : false;
2547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
259716f67e149e8defd72262b7e7f875ea2aef57652Yorke Lee                }
2607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_NEIGHBORING_CELL:
2627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
2637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
2647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            request);
2657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mPhone.getNeighboringCids(onCompleted);
2667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NEIGHBORING_CELL_DONE:
2697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    ar = (AsyncResult) msg.obj;
2707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) ar.userObj;
2717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (ar.exception == null && ar.result != null) {
2727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.result = ar.result;
2737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // create an empty list to notify the waiting thread
275e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = new ArrayList<NeighboringCellInfo>(0);
2767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_ANSWER_RINGING_CALL:
2840887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                    request = (MainThreadRequest) msg.obj;
285584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    int answer_subId = request.subId;
2860887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                    answerRingingCallInternal(answer_subId);
2877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_END_CALL:
2907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
291584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    int end_subId = request.subId;
2920887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                    final boolean hungUp;
293ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    Phone phone = getPhone(end_subId);
294ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    if (phone == null) {
295ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                        if (DBG) log("CMD_END_CALL: no phone for id: " + end_subId);
296ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                        break;
297ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    }
298ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    int phoneType = phone.getPhoneType();
2997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
3007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // CDMA: If the user presses the Power button we treat it as
3017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // ending the complete call session
3020887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                        hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
3037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
3047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // GSM: End the call as per the Phone state
3057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangup(mCM);
3067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
3077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
3087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
3097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
3107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.result = hungUp;
3117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
3127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
3137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
3147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
3157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
3167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
317da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
318566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
319da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
320eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
321eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccTransmitApduLogicalChannel: No UICC");
322eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
323eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
324eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
325eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
326eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
327da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
328da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
329eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccTransmitApduLogicalChannel(
330da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.channel, iccArgument.cla, iccArgument.command,
331da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
332566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
333eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
334566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
335566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
336da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
337566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
338566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
339566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
340566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = ar.result;
341566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
342566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
343566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
344566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Empty response");
345e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
346566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: CommandException: " +
347e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
348566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
349566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Unknown exception");
350566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
351566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
352566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
353566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
354566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
355566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
356566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
357da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
358da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
359da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
360da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
361da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccTransmitApduBasicChannel: No UICC");
362da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
363da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
364da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
365da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
366da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
367da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
368da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
369da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccTransmitApduBasicChannel(
370da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
371da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p3, iccArgument.data, onCompleted);
372da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
373da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
374da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
375da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
376da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
377da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
378da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
379da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
380da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
381da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
382da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.result == null) {
383da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Empty response");
384da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else if (ar.exception instanceof CommandException) {
385da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: CommandException: " +
386da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                    ar.exception);
387da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else {
388da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Unknown exception");
389da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
390da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
391da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
392da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
393da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
394da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
395da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
396da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_EXCHANGE_SIM_IO:
397da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
398da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
399da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
400da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccExchangeSimIO: No UICC");
401da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
402da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
403da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
404da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
405da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
406da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
407da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                request);
408da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
409da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
410da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.data, onCompleted);
411da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
412da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
413da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
414da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_EXCHANGE_SIM_IO_DONE:
415da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
416da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
417da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
418da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
419da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
420da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6f, 0, (byte[])null);
421da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
422da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
423da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
424da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
425da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
426da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
4274d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case CMD_SEND_ENVELOPE:
4284d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) msg.obj;
429eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
430eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("sendEnvelopeWithStatus: No UICC");
431eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
432eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
433eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
434eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
435eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
436eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
437eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
438eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
4394d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
4404d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
4414d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case EVENT_SEND_ENVELOPE_DONE:
4424d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    ar = (AsyncResult) msg.obj;
4434d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) ar.userObj;
4449f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    if (ar.exception == null && ar.result != null) {
4459f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = ar.result;
4464d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    } else {
4479f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
4489f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        if (ar.result == null) {
4499f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: Empty response");
4509f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else if (ar.exception instanceof CommandException) {
4519f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: CommandException: " +
4529f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                                    ar.exception);
4539f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else {
4549f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: exception:" + ar.exception);
4559f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        }
4564d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4574d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    synchronized (request) {
4584d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                        request.notifyAll();
4594d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4604d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
4614d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
462566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_OPEN_CHANNEL:
463566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
464eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
465eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccOpenLogicalChannel: No UICC");
466eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
467eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
468eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
469eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
470eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
471eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
472eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
473eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
474566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
475566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
476566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_OPEN_CHANNEL_DONE:
477566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
478566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
479da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    IccOpenLogicalChannelResponse openChannelResp;
480566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
481da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int[] result = (int[]) ar.result;
482da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int channelId = result[0];
483da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        byte[] selectResponse = null;
484da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (result.length > 1) {
485da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            selectResponse = new byte[result.length - 1];
486da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            for (int i = 1; i < result.length; ++i) {
487da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                selectResponse[i - 1] = (byte) result[i];
488da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
489da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
490da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(channelId,
491527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                            IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
492566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
493566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
494566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Empty response");
495566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
496da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.exception != null) {
497da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccOpenLogicalChannel: Exception: " + ar.exception);
498da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
499da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
500527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                        int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
501a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                        if (ar.exception instanceof CommandException) {
502a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                            CommandException.Error error =
503a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                                ((CommandException) (ar.exception)).getCommandError();
504a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                            if (error == CommandException.Error.MISSING_RESOURCE) {
505527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
506a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                            } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
507527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
508da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
509da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
510da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(
511da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
512566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
51382c8a46052629d1450320c116d14c7353bfe4ea1Shishir Agrawal                    request.result = openChannelResp;
514566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
515566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
516566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
517566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
518566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
519566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_CLOSE_CHANNEL:
520566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
521eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
522eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccCloseLogicalChannel: No UICC");
523eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
524eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
525eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
526eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
527eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
528eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
529eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
530eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
531566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
532566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
533566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_CLOSE_CHANNEL_DONE:
534e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "iccCloseLogicalChannel");
535e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
536e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
537e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_READ_ITEM:
538e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
539e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
540e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvReadItem((Integer) request.argument, onCompleted);
541e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
542e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
543e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_READ_ITEM_DONE:
544566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
545566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
546e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    if (ar.exception == null && ar.result != null) {
547e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ar.result;     // String
548566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
549e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = "";
550e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        if (ar.result == null) {
551e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Empty response");
552e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
553e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: CommandException: " +
554e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
555566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
556e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Unknown exception");
557566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
558566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
559566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
560566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
561566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
562566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
563566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
564e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_ITEM:
565e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
566e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
567e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
568e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
569e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
570e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
571e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_ITEM_DONE:
572e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteItem");
573e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
574e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
575e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_CDMA_PRL:
576e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
577e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
578e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
579e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
580e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
581e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_CDMA_PRL_DONE:
582e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteCdmaPrl");
583e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
584e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
585e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_RESET_CONFIG:
586e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
587e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
588e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
589e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
590e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
591e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_RESET_CONFIG_DONE:
592e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvResetConfig");
593e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
594e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
5957c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_GET_PREFERRED_NETWORK_TYPE:
5967c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
5977c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
59854788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
5997c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6007c27be317e8757948178815426d3a329c852b9eeJake Hamby
6017c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
6027c27be317e8757948178815426d3a329c852b9eeJake Hamby                    ar = (AsyncResult) msg.obj;
6037c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) ar.userObj;
6047c27be317e8757948178815426d3a329c852b9eeJake Hamby                    if (ar.exception == null && ar.result != null) {
6057c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = ar.result;     // Integer
6067c27be317e8757948178815426d3a329c852b9eeJake Hamby                    } else {
6077c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = -1;
6087c27be317e8757948178815426d3a329c852b9eeJake Hamby                        if (ar.result == null) {
6097c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Empty response");
6107c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else if (ar.exception instanceof CommandException) {
6117c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: CommandException: " +
6127c27be317e8757948178815426d3a329c852b9eeJake Hamby                                    ar.exception);
6137c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else {
6147c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Unknown exception");
6157c27be317e8757948178815426d3a329c852b9eeJake Hamby                        }
6167c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
6177c27be317e8757948178815426d3a329c852b9eeJake Hamby                    synchronized (request) {
6187c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.notifyAll();
6197c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
6207c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6217c27be317e8757948178815426d3a329c852b9eeJake Hamby
6227c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_SET_PREFERRED_NETWORK_TYPE:
6237c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
6247c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
6257c27be317e8757948178815426d3a329c852b9eeJake Hamby                    int networkType = (Integer) request.argument;
62654788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
6277c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6287c27be317e8757948178815426d3a329c852b9eeJake Hamby
6297c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
6307c27be317e8757948178815426d3a329c852b9eeJake Hamby                    handleNullReturnEvent(msg, "setPreferredNetworkType");
6317c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6327c27be317e8757948178815426d3a329c852b9eeJake Hamby
6334bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
6344bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)msg.obj;
6354bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
6364bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
6374bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
6384bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
6394bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
6404bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    ar = (AsyncResult)msg.obj;
6414bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)ar.userObj;
6424bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request.result = ar;
6434bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    synchronized (request) {
6444bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        request.notifyAll();
6454bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
6464bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
6474bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
64876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                case CMD_SET_VOICEMAIL_NUMBER:
64976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
65076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
65176d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    Pair<String, String> tagNum = (Pair<String, String>) request.argument;
652584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
653584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                            onCompleted);
65476d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    break;
65576d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
65676d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                case EVENT_SET_VOICEMAIL_NUMBER_DONE:
65776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    handleNullReturnEvent(msg, "setVoicemailNumber");
65876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    break;
65976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
66054788801de04c603a856596f4ae4377ab77a9821Stuart Scott                case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
66154788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    request = (MainThreadRequest) msg.obj;
66254788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
66354788801de04c603a856596f4ae4377ab77a9821Stuart Scott                            request);
66454788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
66554788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    break;
66654788801de04c603a856596f4ae4377ab77a9821Stuart Scott
66754788801de04c603a856596f4ae4377ab77a9821Stuart Scott                case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
66854788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
66954788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    break;
67054788801de04c603a856596f4ae4377ab77a9821Stuart Scott
671302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                case CMD_PERFORM_NETWORK_SCAN:
672302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    request = (MainThreadRequest) msg.obj;
673302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    onCompleted = obtainMessage(EVENT_PERFORM_NETWORK_SCAN_DONE, request);
674302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    getPhoneFromRequest(request).getAvailableNetworks(onCompleted);
675302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    break;
676302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal
677302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                case EVENT_PERFORM_NETWORK_SCAN_DONE:
678302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    ar = (AsyncResult) msg.obj;
679302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    request = (MainThreadRequest) ar.userObj;
680302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    CellNetworkScanResult cellScanResult;
681302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    if (ar.exception == null && ar.result != null) {
682302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        cellScanResult = new CellNetworkScanResult(
683302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                                CellNetworkScanResult.STATUS_SUCCESS,
684302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                                (List<OperatorInfo>) ar.result);
685302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    } else {
686302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        if (ar.result == null) {
687302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            loge("getCellNetworkScanResults: Empty response");
688302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        }
689302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        if (ar.exception != null) {
690302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            loge("getCellNetworkScanResults: Exception: " + ar.exception);
691302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        }
692302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
693302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        if (ar.exception instanceof CommandException) {
694302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            CommandException.Error error =
695302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                                ((CommandException) (ar.exception)).getCommandError();
696302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
697302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                                errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
698302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            } else if (error == CommandException.Error.GENERIC_FAILURE) {
699302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                                errorCode = CellNetworkScanResult.STATUS_RADIO_GENERIC_FAILURE;
700302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            }
701302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        }
702302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        cellScanResult = new CellNetworkScanResult(errorCode, null);
703302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    }
704302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    request.result = cellScanResult;
705302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    synchronized (request) {
706302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                        request.notifyAll();
707302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    }
708302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    break;
709302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal
710302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                case CMD_SET_NETWORK_SELECTION_MODE_MANUAL:
711302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    request = (MainThreadRequest) msg.obj;
71277ba317277863812508869705308373b42364e0aShishir Agrawal                    ManualNetworkSelectionArgument selArg =
71377ba317277863812508869705308373b42364e0aShishir Agrawal                            (ManualNetworkSelectionArgument) request.argument;
714302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE,
715302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                            request);
71677ba317277863812508869705308373b42364e0aShishir Agrawal                    getPhoneFromRequest(request).selectNetworkManually(selArg.operatorInfo,
71777ba317277863812508869705308373b42364e0aShishir Agrawal                            selArg.persistSelection, onCompleted);
718302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    break;
719302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal
720302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE:
721302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    handleNullReturnEvent(msg, "setNetworkSelectionModeManual");
722302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                    break;
723302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal
7247fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                case CMD_GET_MODEM_ACTIVITY_INFO:
7257fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    request = (MainThreadRequest) msg.obj;
7267fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
72761a60ad2e6944a80944898e636c2e9d9fd7b0e70Prerepa Viswanadham                    mPhone.getModemActivityInfo(onCompleted);
7287fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    break;
7297fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
7307fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
7317fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    ar = (AsyncResult) msg.obj;
7327fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    request = (MainThreadRequest) ar.userObj;
7337fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    if (ar.exception == null && ar.result != null) {
7347fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        request.result = ar.result;
7357fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    } else {
7367fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        if (ar.result == null) {
7377fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                            loge("queryModemActivityInfo: Empty response");
7387fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        } else if (ar.exception instanceof CommandException) {
7397fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                            loge("queryModemActivityInfo: CommandException: " +
7407fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                                    ar.exception);
7417fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        } else {
7427fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                            loge("queryModemActivityInfo: Unknown exception");
7437fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        }
7447fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    }
7457fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    synchronized (request) {
7467fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        request.notifyAll();
7477fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    }
7487fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    break;
7497fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
7507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                default:
7517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
7527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
7537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
7547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
755e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
756e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        private void handleNullReturnEvent(Message msg, String command) {
757e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            AsyncResult ar = (AsyncResult) msg.obj;
758e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            MainThreadRequest request = (MainThreadRequest) ar.userObj;
759e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            if (ar.exception == null) {
760e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = true;
761e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            } else {
762e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = false;
763e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                if (ar.exception instanceof CommandException) {
764e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": CommandException: " + ar.exception);
765e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                } else {
766e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": Unknown exception");
767e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                }
768e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
769e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            synchronized (request) {
770e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.notifyAll();
771e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
772e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        }
7737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread,
7777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * waits for the request to complete, and returns the result.
7787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequestAsync
7797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Object sendRequest(int command, Object argument) {
781500b0e04406d2995c1f29dea95c98cedaa669f74Santos Cordon        return sendRequest(command, argument, null);
78236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
78336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
78436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
78536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Posts the specified command to be executed on the main thread,
78636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * waits for the request to complete, and returns the result.
78736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @see #sendRequestAsync
78836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
78976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    private Object sendRequest(int command, Object argument, Integer subId) {
7907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
7917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            throw new RuntimeException("This method will deadlock if called from the main thread.");
7927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
79476d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        MainThreadRequest request = new MainThreadRequest(argument, subId);
7957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Message msg = mMainThreadHandler.obtainMessage(command, request);
7967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        msg.sendToTarget();
7977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Wait for the request to complete
7997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (request) {
8007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (request.result == null) {
8017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
8027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.wait();
8037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
8047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Do nothing, go back and wait until the request is complete
8057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
8067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return request.result;
8097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Asynchronous ("fire and forget") version of sendRequest():
8137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread, and
8147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * returns immediately.
8157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequest
8167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void sendRequestAsync(int command) {
8187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler.sendEmptyMessage(command);
8197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
822bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * Same as {@link #sendRequestAsync(int)} except it takes an argument.
823bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * @see {@link #sendRequest(int,Object)}
824bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     */
825bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    private void sendRequestAsync(int command, Object argument) {
826bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        MainThreadRequest request = new MainThreadRequest(argument);
827bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        Message msg = mMainThreadHandler.obtainMessage(command, request);
828bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        msg.sendToTarget();
829bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    }
830bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal
831bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    /**
8327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton PhoneInterfaceManager instance.
8337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
8347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
835194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
8367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (PhoneInterfaceManager.class) {
8377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
838194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal                sInstance = new PhoneInterfaceManager(app, phone);
8397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
8407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
8417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
8427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
8437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** Private constructor; @see init() */
847194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
8487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
8497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = phone;
8507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mCM = PhoneGlobals.getInstance().mCM;
851981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott        mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
8527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
8537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler = new MainThreadHandler();
854df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        mTelephonySharedPreferences =
85597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
856ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        mSubscriptionController = SubscriptionController.getInstance();
8573ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville
8587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        publish();
8597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void publish() {
8627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("publish: " + this);
8637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        ServiceManager.addService("phone", this);
8657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
867584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott    private Phone getPhoneFromRequest(MainThreadRequest request) {
868584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott        return (request.subId == null) ? mPhone : getPhone(request.subId);
869584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott    }
870584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott
87136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // returns phone associated with the subId.
872b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private Phone getPhone(int subId) {
873ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
87436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
8757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
8767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Implementation of the ITelephony interface.
8777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
8787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void dial(String number) {
880add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        dialForSubscriber(getPreferredVoiceSubscription(), number);
88136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
88236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
883b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void dialForSubscriber(int subId, String number) {
8847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("dial: " + number);
8857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: This is just a wrapper around the
8867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // ACTION_DIAL intent, which is available to any app since it puts up
8877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // the UI before it does anything.
8887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
8907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
8917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
8927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // PENDING: should we just silently fail if phone is offhook or ringing?
89536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        PhoneConstants.State state = mCM.getState(subId);
8967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
8977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
8987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.startActivity(intent);
9007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void call(String callingPackage, String number) {
904add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
90536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
90636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
907b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void callForSubscriber(int subId, String callingPackage, String number) {
9087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("call: " + number);
9097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // This is just a wrapper around the ACTION_CALL intent, but we still
9117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // need to do a permission check since we're calling startActivity()
9127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // from the context of the phone app.
9137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
9147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
9167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                != AppOpsManager.MODE_ALLOWED) {
9177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
9187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
9217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
9227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
9237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9250887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        boolean isValid = false;
9261c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final List<SubscriptionInfo> slist = getActiveSubscriptionInfoList();
9273ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville        if (slist != null) {
9283ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville            for (SubscriptionInfo subInfoRecord : slist) {
9293ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                if (subInfoRecord.getSubscriptionId() == subId) {
9303ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                    isValid = true;
9313ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                    break;
9323ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                }
9330887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            }
9340887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        }
9350887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        if (isValid == false) {
9360887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            return;
9370887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        }
9380887461919173015886ea69ef6c6afbe20ebf1dcWink Saville
9397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
94036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        intent.putExtra(SUBSCRIPTION_KEY, subId);
9417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
9427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.startActivity(intent);
9437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
9467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * End a call based on call state
9477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true is a call was ended
9487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
9497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean endCall() {
950add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return endCallForSubscriber(getDefaultSubscription());
95136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
95236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
95336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
95436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * End a call based on the call state of the subId
95536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true is a call was ended
95636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
957b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean endCallForSubscriber(int subId) {
9587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
959584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott        return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId));
9607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void answerRingingCall() {
963add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        answerRingingCallForSubscriber(getDefaultSubscription());
96436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
96536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
966b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void answerRingingCallForSubscriber(int subId) {
9677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("answerRingingCall...");
9687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
9697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // but that can probably wait till the big TelephonyManager API overhaul.
9707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.
9717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
972584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott        sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId));
9737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
9767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make the actual telephony calls to implement answerRingingCall().
9777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
9787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #answerRingingCall
9797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
9807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: it would be nice to return true if we answered the call, or
9817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * false if there wasn't actually a ringing incoming call, or some
9827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * other error occurred.  (In other words, pass back the return value
9837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
9847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * But that would require calling this method via sendRequest() rather
9857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * than sendRequestAsync(), and right now we don't actually *need* that
9867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * return value, so let's just return void for now.
9877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
988b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private void answerRingingCallInternal(int subId) {
9890887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
9907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (hasRingingCall) {
9910887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
9920887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
9937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (hasActiveCall && hasHoldingCall) {
9947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Both lines are in use!
9957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // TODO: provide a flag to let the caller specify what
9967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // policy to use if both lines are in use.  (The current
9977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // behavior is hardwired to "answer incoming, end ongoing",
9987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // which is how the CALL button is specced to behave.)
9997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
10007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
10017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
10027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // answerCall() will automatically hold the current active
10037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // call, if there is one.
10047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
10057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
10067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
10087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // No call was ringing.
10097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
10107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
10145422a8deb513e4466ec6cc1e640895a6b536fee0Santos Cordon     * This method is no longer used and can be removed once TelephonyManager stops referring to it.
10157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
10165422a8deb513e4466ec6cc1e640895a6b536fee0Santos Cordon    public void silenceRinger() {
10175422a8deb513e4466ec6cc1e640895a6b536fee0Santos Cordon        Log.e(LOG_TAG, "silenseRinger not supported");
10187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
102036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
102136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isOffhook(String callingPackage) {
102236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return isOffhookForSubscriber(getDefaultSubscription(), callingPackage);
102336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
102436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
102536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
102636b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isOffhookForSubscriber(int subId, String callingPackage) {
102736b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "isOffhookForSubscriber")) {
102836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return false;
102936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
103036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
1031356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1032356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1033356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return (phone.getState() == PhoneConstants.State.OFFHOOK);
1034356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1035356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1036356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
10377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
103936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
104036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isRinging(String callingPackage) {
104136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return (isRingingForSubscriber(getDefaultSubscription(), callingPackage));
104236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
104336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
104436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
104536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isRingingForSubscriber(int subId, String callingPackage) {
104636b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "isRingingForSubscriber")) {
104736b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return false;
104836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
104936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
1050356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1051356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1052356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return (phone.getState() == PhoneConstants.State.RINGING);
1053356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1054356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1055356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
10567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
105836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
105936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isIdle(String callingPackage) {
106036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return isIdleForSubscriber(getDefaultSubscription(), callingPackage);
106136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
106236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
106336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
106436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isIdleForSubscriber(int subId, String callingPackage) {
106536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "isIdleForSubscriber")) {
106636b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return false;
106736b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
106836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
1069356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1070356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1071356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return (phone.getState() == PhoneConstants.State.IDLE);
1072356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1073356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1074356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
10757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1077b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public boolean isSimPinEnabled(String callingPackage) {
1078b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "isSimPinEnabled")) {
1079b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return false;
1080b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
1081b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
10827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (PhoneGlobals.getInstance().isSimPinEnabled());
10837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean supplyPin(String pin) {
1086add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPinForSubscriber(getDefaultSubscription(), pin);
108736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
108836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1089b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean supplyPinForSubscriber(int subId, String pin) {
1090add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
10919de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
10929de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
10939de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
10949de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public boolean supplyPuk(String puk, String pin) {
1095add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
109636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
109736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1098b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
1099add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
11009de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
11019de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
11029de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
11039de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
11049de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPinReportResult(String pin) {
1105add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
110636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
110736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1108b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
11097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
111036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
11117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPin.start();
11127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPin.unlockSim(null, pin);
11137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11159de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
11169de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPukReportResult(String puk, String pin) {
1117add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
111836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
111936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1120b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
11217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
112236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
11237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPuk.start();
11247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPuk.unlockSim(puk, pin);
11257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
11289de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville     * Helper thread to turn async call to SimCard#supplyPin into
11297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * a synchronous one.
11307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
11317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static class UnlockSim extends Thread {
11327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private final IccCard mSimCard;
11347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private boolean mDone = false;
11369de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
11379de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mRetryCount = -1;
11387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For replies from SimCard interface
11407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private Handler mHandler;
11417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For async handler to identify request type
11437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private static final int SUPPLY_PIN_COMPLETE = 100;
11447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public UnlockSim(IccCard simCard) {
11467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mSimCard = simCard;
11477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
11507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void run() {
11517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.prepare();
11527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            synchronized (UnlockSim.this) {
11537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mHandler = new Handler() {
11547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    @Override
11557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    public void handleMessage(Message msg) {
11567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        AsyncResult ar = (AsyncResult) msg.obj;
11577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        switch (msg.what) {
11587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            case SUPPLY_PIN_COMPLETE:
11597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
11607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                synchronized (UnlockSim.this) {
11619de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    mRetryCount = msg.arg1;
11629de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    if (ar.exception != null) {
11639de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        if (ar.exception instanceof CommandException &&
11649de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                ((CommandException)(ar.exception)).getCommandError()
11659de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                == CommandException.Error.PASSWORD_INCORRECT) {
11669de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
11679de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        } else {
11689de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_GENERAL_FAILURE;
11699de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        }
11709de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    } else {
11719de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        mResult = PhoneConstants.PIN_RESULT_SUCCESS;
11729de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    }
11737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mDone = true;
11747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    UnlockSim.this.notifyAll();
11757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
11767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                break;
11777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
11787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
11797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                };
11807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                UnlockSim.this.notifyAll();
11817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
11827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.loop();
11837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /*
11867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Use PIN or PUK to unlock SIM card
11877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
11887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is null, unlock SIM card with PIN
11897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
11907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is not null, unlock SIM card with PUK and set PIN code
11917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
11929de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        synchronized int[] unlockSim(String puk, String pin) {
11937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (mHandler == null) {
11957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
11967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
11977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
11987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
11997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
12007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
12017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
12027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (puk == null) {
12047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPin(pin, callback);
12057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
12067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPuk(puk, pin, callback);
12077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
12087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (!mDone) {
12107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
12117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.d(LOG_TAG, "wait for done");
12127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
12137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
12147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Restore the interrupted status
12157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
12167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
12177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
12187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Log.d(LOG_TAG, "done");
12199de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            int[] resultArray = new int[2];
12209de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[0] = mResult;
12219de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[1] = mRetryCount;
12229de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            return resultArray;
12237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void updateServiceLocation() {
1227add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        updateServiceLocationForSubscriber(getDefaultSubscription());
122836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
122936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
123036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1231b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void updateServiceLocationForSubscriber(int subId) {
12327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: this call is harmless, and it's
12337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // needed for the ServiceState.requestStateUpdate() call (which is
12347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // already intentionally exposed to 3rd parties.)
1235356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1236356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1237356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.updateServiceLocation();
1238356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
12397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
124136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
124236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isRadioOn(String callingPackage) {
124336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return isRadioOnForSubscriber(getDefaultSubscription(), callingPackage);
124436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
124536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
124636b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
124736b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
124836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "isRadioOnForSubscriber")) {
124936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return false;
125036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
125136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return isRadioOnForSubscriber(subId);
125236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    }
125336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
125436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    private boolean isRadioOnForSubscriber(int subId) {
1255356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1256356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1257356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
1258356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1259356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1260356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
12617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void toggleRadioOnOff() {
1264add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        toggleRadioOnOffForSubscriber(getDefaultSubscription());
126536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
126636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
126736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1268b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void toggleRadioOnOffForSubscriber(int subId) {
12697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1270356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1271356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1272356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.setRadioPower(!isRadioOnForSubscriber(subId));
1273356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
12747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
127536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
12767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadio(boolean turnOn) {
1277add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return setRadioForSubscriber(getDefaultSubscription(), turnOn);
127836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
127936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1280b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean setRadioForSubscriber(int subId, boolean turnOn) {
12817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1282356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1283356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone == null) {
1284356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1285356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
1286356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if ((phone.getServiceState().getState() !=
128736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                ServiceState.STATE_POWER_OFF) != turnOn) {
1288add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville            toggleRadioOnOffForSubscriber(subId);
12897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
12917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
129236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
12931fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    public boolean needMobileRadioShutdown() {
12941fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        /*
12951fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         * If any of the Radios are available, it will need to be
12961fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         * shutdown. So return true if any Radio is available.
12971fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         */
12981fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
12991fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            Phone phone = PhoneFactory.getPhone(i);
13001fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            if (phone != null && phone.isRadioAvailable()) return true;
13011fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
13021fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
13031fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        return false;
13041fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
13051fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
13061fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    public void shutdownMobileRadios() {
13071fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
13081fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            logv("Shutting down Phone " + i);
13091fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            shutdownRadioUsingPhoneId(i);
13101fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
13111fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
13121fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
13131fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    private void shutdownRadioUsingPhoneId(int phoneId) {
13141fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        enforceModifyPermission();
13151fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        Phone phone = PhoneFactory.getPhone(phoneId);
13161fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        if (phone != null && phone.isRadioAvailable()) {
13171fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            phone.shutdownRadio();
13181fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
13191fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
13201fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
13217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadioPower(boolean turnOn) {
1322add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
132336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
132436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1325b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
13267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1327356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1328356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1329356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.setRadioPower(turnOn);
1330356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return true;
1331356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1332356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1333356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
13347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
133636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
1337356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
13387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean enableDataConnectivity() {
13397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1340ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        int subId = mSubscriptionController.getDefaultDataSubId();
1341356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1342356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1343356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.setDataEnabled(true);
1344356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return true;
1345356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1346356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1347356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
13487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
135036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
1351356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
13527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean disableDataConnectivity() {
13537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1354ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        int subId = mSubscriptionController.getDefaultDataSubId();
1355356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1356356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1357356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.setDataEnabled(false);
1358356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return true;
1359356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1360356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1361356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
13627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
136436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
1365356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
13667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isDataConnectivityPossible() {
1367ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        int subId = mSubscriptionController.getDefaultDataSubId();
1368356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1369356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1370356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.isDataConnectivityPossible();
1371356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1372356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1373356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
13747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean handlePinMmi(String dialString) {
1377add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
137836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
137936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1380b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean handlePinMmiForSubscriber(int subId, String dialString) {
13817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1382356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
1383356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
1384356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
138536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
13867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCallState() {
1389add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getCallStateForSubscriber(getDefaultSubscription());
139036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
139136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1392b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getCallStateForSubscriber(int subId) {
139336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
13947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1396356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
13977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataState() {
1398ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1399356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1400356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
1401356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1402356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return DefaultPhoneNotifier.convertDataState(PhoneConstants.DataState.DISCONNECTED);
1403356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
14047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1406356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
14077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataActivity() {
1408ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1409356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1410356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
1411356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1412356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return TelephonyManager.DATA_ACTIVITY_NONE;
1413356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
14147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
141764fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    public Bundle getCellLocation(String callingPackage) {
141864fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        enforceFineOrCoarseLocationPermission("getCellLocation");
141964fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
142064fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        // OP_COARSE_LOCATION controls both fine and coarse location.
142164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
142264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                callingPackage) != AppOpsManager.MODE_ALLOWED) {
14239acc70dcc5bab8df02211ad37a71a1a79c8d54e3Amit Mahajan            log("getCellLocation: returning null; mode != allowed");
142464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            return null;
14257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
14267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1427e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
14287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: is active user");
14297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Bundle data = new Bundle();
14302c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
1431356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            if (phone == null) {
1432356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe                return null;
1433356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            }
14342c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            phone.getCellLocation().fillInNotifierBundle(data);
14357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return data;
14367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
14379acc70dcc5bab8df02211ad37a71a1a79c8d54e3Amit Mahajan            log("getCellLocation: suppress non-active user");
14387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
14397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
14407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
144264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    private void enforceFineOrCoarseLocationPermission(String message) {
144364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        try {
144464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            mApp.enforceCallingOrSelfPermission(
144564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                    android.Manifest.permission.ACCESS_FINE_LOCATION, null);
144664fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        } catch (SecurityException e) {
144764fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
144864fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
144964fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            // is the weaker precondition
145064fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            mApp.enforceCallingOrSelfPermission(
145164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                    android.Manifest.permission.ACCESS_COARSE_LOCATION, message);
145264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        }
145364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    }
145464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
145564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
14567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void enableLocationUpdates() {
1458add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        enableLocationUpdatesForSubscriber(getDefaultSubscription());
145936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
146036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1461356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1462b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void enableLocationUpdatesForSubscriber(int subId) {
14637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
14647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
1465356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1466356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1467356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.enableLocationUpdates();
1468356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
14697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void disableLocationUpdates() {
1473add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        disableLocationUpdatesForSubscriber(getDefaultSubscription());
147436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
147536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1476356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1477b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void disableLocationUpdatesForSubscriber(int subId) {
14787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
14797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
1480356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1481356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1482356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            phone.disableLocationUpdates();
1483356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
14847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
14877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @SuppressWarnings("unchecked")
14887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
148964fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        enforceFineOrCoarseLocationPermission("getNeighboringCellInfo");
149064fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
149164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        // OP_COARSE_LOCATION controls both fine and coarse location.
149264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
149364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                callingPackage) != AppOpsManager.MODE_ALLOWED) {
149464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            return null;
14957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
14967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
14987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                callingPackage) != AppOpsManager.MODE_ALLOWED) {
14997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
15007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
150164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
1502e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
15037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: is active user");
15047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ArrayList<NeighboringCellInfo> cells = null;
15067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
15087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                cells = (ArrayList<NeighboringCellInfo>) sendRequest(
150936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                        CMD_HANDLE_NEIGHBORING_CELL, null, null);
15107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (RuntimeException e) {
151136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
15127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
15137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return cells;
15147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
15157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
15167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
15177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
15187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
152264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    public List<CellInfo> getAllCellInfo(String callingPackage) {
152364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        enforceFineOrCoarseLocationPermission("getAllCellInfo");
152464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
152564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        // OP_COARSE_LOCATION controls both fine and coarse location.
152664fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
152764fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                callingPackage) != AppOpsManager.MODE_ALLOWED) {
152864fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            return null;
15297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
15307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1531e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
15327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: is active user");
15332c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            List<CellInfo> cellInfos = new ArrayList<CellInfo>();
15342c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            for (Phone phone : PhoneFactory.getPhones()) {
1535d9eb7da8777390662732098edae8930fda567953Robert Greenwalt                final List<CellInfo> info = phone.getAllCellInfo();
1536d9eb7da8777390662732098edae8930fda567953Robert Greenwalt                if (info != null) cellInfos.addAll(phone.getAllCellInfo());
15372c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            }
15382c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            return cellInfos;
15397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
15407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
15417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
15427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
15437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1545bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    @Override
15467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void setCellInfoListRate(int rateInMillis) {
15477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setCellInfoListRate(rateInMillis);
15487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
15517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Internal helper methods.
15527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
15537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1554e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static boolean checkIfCallerIsSelfOrForegroundUser() {
15557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean ok;
15567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean self = Binder.getCallingUid() == Process.myUid();
15587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!self) {
15597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Get the caller's user id then clear the calling identity
15607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // which will be restored in the finally clause.
15617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int callingUser = UserHandle.getCallingUserId();
15627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            long ident = Binder.clearCallingIdentity();
15637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
15657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // With calling identity cleared the current user is the foreground user.
15667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                int foregroundUser = ActivityManager.getCurrentUser();
15677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = (foregroundUser == callingUser);
15687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) {
15697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
15707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            + " callingUser=" + callingUser + " ok=" + ok);
15717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
15727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (Exception ex) {
15737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
15747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = false;
15757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } finally {
15767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Binder.restoreCallingIdentity(ident);
15777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
15787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
15797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
15807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ok = true;
15817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
15827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
15837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return ok;
15847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the MODIFY_PHONE_STATE permission.
15887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
15897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
15907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceModifyPermission() {
15927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
15937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1596a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure either system app or the caller has carrier privilege.
1597a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1598a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission/privilege
1599a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1600a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceModifyPermissionOrCarrierPrivilege() {
1601f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        int permission = mApp.checkCallingOrSelfPermission(
1602f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                android.Manifest.permission.MODIFY_PHONE_STATE);
1603f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (permission == PackageManager.PERMISSION_GRANTED) {
1604f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            return;
1605f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        }
1606f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal
1607f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        log("No modify permission, check carrier privilege next.");
16085e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        if (getCarrierPrivilegeStatus() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1609f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1610f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No modify permission or carrier privilege.");
1611a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1612a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1613a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1614a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
1615a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure the caller has carrier privilege.
1616a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1617a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission
1618a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1619a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceCarrierPrivilege() {
16205e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        if (getCarrierPrivilegeStatus() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1621f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1622f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No Carrier Privilege.");
1623a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1624a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1625a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1626a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
16277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the CALL_PHONE permission.
16287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
16297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
16307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
16317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceCallPermission() {
16327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
16337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16358eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    private void enforceConnectivityInternalPermission() {
16368eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott        mApp.enforceCallingOrSelfPermission(
16378eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott                android.Manifest.permission.CONNECTIVITY_INTERNAL,
16388eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott                "ConnectivityService");
16398eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    }
16408eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott
16417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private String createTelUrl(String number) {
16427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TextUtils.isEmpty(number)) {
16437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
16447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
16457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1646e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return "tel:" + number;
16477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1649f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void log(String msg) {
16507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
16517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16531fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    private static void logv(String msg) {
16541fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
16551fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
16561fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
1657f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void loge(String msg) {
16587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
16597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
166136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
16627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getActivePhoneType() {
1663add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getActivePhoneTypeForSubscriber(getDefaultSubscription());
166436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
166536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1666356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1667b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getActivePhoneTypeForSubscriber(int subId) {
1668356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1669356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone == null) {
1670356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return PhoneConstants.PHONE_TYPE_NONE;
1671356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1672356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return getPhone(subId).getPhoneType();
1673356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
16747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
16777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon index to display
16787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
167936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
168036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getCdmaEriIconIndex(String callingPackage) {
168136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return getCdmaEriIconIndexForSubscriber(getDefaultSubscription(), callingPackage);
168236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
168336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1684356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
168536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
168636b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
168736b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return -1;
168836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
1689356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1690356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1691356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getCdmaEriIconIndex();
1692356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1693356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return -1;
1694356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
16957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
16987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon mode,
16997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 0 - ON
17007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 1 - FLASHING
17017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
170236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
170336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getCdmaEriIconMode(String callingPackage) {
170436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return getCdmaEriIconModeForSubscriber(getDefaultSubscription(), callingPackage);
170536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
170636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1707356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
170836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
170936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
171036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return -1;
171136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
1712356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1713356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1714356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getCdmaEriIconMode();
1715356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1716356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return -1;
1717356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
17187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
17197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
17207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
17217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI text,
17227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
172336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
172436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public String getCdmaEriText(String callingPackage) {
172536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return getCdmaEriTextForSubscriber(getDefaultSubscription(), callingPackage);
172636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
172736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1728356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
172936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
173036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
173136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return null;
173236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
1733356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1734356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1735356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getCdmaEriText();
1736356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1737356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return null;
1738356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
17397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
17407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
17417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1742ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     * Returns the CDMA MDN.
1743ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     */
1744356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1745b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public String getCdmaMdn(int subId) {
1746ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1747356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1748356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
1749356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getLine1Number();
1750ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        } else {
1751ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return null;
1752ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        }
1753ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    }
1754ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu
1755ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    /**
1756ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     * Returns the CDMA MIN.
1757ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     */
1758356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1759b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public String getCdmaMin(int subId) {
1760ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1761356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1762356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1763356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getCdmaMin();
1764ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        } else {
1765ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return null;
1766ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        }
1767ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    }
1768ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu
1769ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    /**
17707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns true if CDMA provisioning needs to run.
17717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
17727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean needsOtaServiceProvisioning() {
17737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.needsOtaServiceProvisioning();
17747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
17757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
17767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
177776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal     * Sets the voice mail number of a given subId.
177876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal     */
177976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    @Override
178076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
17815e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        enforceCarrierPrivilege();
178276d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
178376d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                new Pair<String, String>(alphaTag, number), new Integer(subId));
178476d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        return success;
178576d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    }
178676d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
178776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    /**
17887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the unread count of voicemails
17897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
17907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceMessageCount() {
1791add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getVoiceMessageCountForSubscriber(getDefaultSubscription());
179236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
179336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
179436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
179536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the unread count of voicemails for a subId
179636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
1797356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1798b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getVoiceMessageCountForSubscriber( int subId) {
1799356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1800356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1801356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getVoiceMessageCount();
1802356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1803356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return 0;
1804356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
18057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
18067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
18077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1808a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt     * Returns the data network type.
1809a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt     * Legacy call, permission-free.
18107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
18117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
18127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
18137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
1814a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt    public int getNetworkType() {
1815a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt        final Phone phone = getPhone(getDefaultSubscription());
1816a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt        if (phone != null) {
1817a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt            return phone.getServiceState().getDataNetworkType();
1818a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt        } else {
1819a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1820a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt        }
182136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
182236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
182336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
182436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the network type for a subId
182536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
182636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
182736b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
182836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
182936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
183036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
1831a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt
1832356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
183336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (phone != null) {
1834356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getServiceState().getDataNetworkType();
1835356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1836356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1837356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
18387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
18397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
18407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
18417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
18427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
18437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
184436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getDataNetworkType(String callingPackage) {
184536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return getDataNetworkTypeForSubscriber(getDefaultSubscription(), callingPackage);
184636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
184736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
184836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
184936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the data network type for a subId
185036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
185136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
185236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
185336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
185436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
185536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
185636b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
1857356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1858356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1859356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getServiceState().getDataNetworkType();
1860356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1861356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1862356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
18637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
18647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
18657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
186636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the Voice network type for a subId
186736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
186836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
1869a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt    public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
1870a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt        if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
1871a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1872a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt        }
1873a5dcfcb1c18056def5df69b0ac963fee0a5be98cRobert Greenwalt
1874356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1875356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone != null) {
1876356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getServiceState().getVoiceNetworkType();
1877356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1878356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
1879356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
18807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
18817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
18827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
18837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true if a ICC card is present
18847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
18857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean hasIccCard() {
188636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME Make changes to pass defaultSimId of type int
1887a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription()));
188836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
188936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
189036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
189136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true if a ICC card is present for a slotId
189236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
1893356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
1894b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean hasIccCardUsingSlotId(int slotId) {
1895a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId);
1896356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId[0]);
1897356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (subId != null && phone != null) {
1898356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getIccCard().hasIccCard();
1899a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        } else {
1900a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan            return false;
1901a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        }
19027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
19037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
19047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
19057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Return if the current radio is LTE on CDMA. This
19067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * is a tri-state return value as for a period of time
19077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * the mode may be unknown.
19087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
190936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt     * @param callingPackage the name of the package making the call.
19107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1911e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * or {@link Phone#LTE_ON_CDMA_TRUE}
19127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
191336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    @Override
191436b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getLteOnCdmaMode(String callingPackage) {
191536b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        return getLteOnCdmaModeForSubscriber(getDefaultSubscription(), callingPackage);
191636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
191736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1918356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe    @Override
191936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
192036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
192136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
192236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
192336b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
1924356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
1925356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone == null) {
1926356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
1927356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        } else {
1928356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return phone.getLteOnCdmaMode();
1929356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
193036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
193136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
193236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setPhone(Phone phone) {
193336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone = phone;
193436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
193536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
193636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
193736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
193836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default subId, 0 in the case of single standby.
193936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
1940b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private int getDefaultSubscription() {
1941ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        return mSubscriptionController.getDefaultSubId();
194236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
194336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1944b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private int getPreferredVoiceSubscription() {
1945ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        return mSubscriptionController.getDefaultVoiceSubId();
19467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1947f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1948f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1949f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1950f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1951f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public int getWhenToMakeWifiCalls() {
1952d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1953d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
1954f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
1955f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1956f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1957f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1958f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1959f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public void setWhenToMakeWifiCalls(int preference) {
1960d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1961d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        Settings.System.putInt(mPhone.getContext().getContentResolver(),
1962d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
1963f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    }
1964f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad
1965d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal    private static int getWhenToMakeWifiCallsDefaultPreference() {
1966da120f4e3d32ca97c5b4c21d6c505d834a29ab8dSantos Cordon        // TODO: Use a build property to choose this value.
19679829e880f73f76119ba76ba032db42aad042858fEvan Charlton        return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
1968f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
196969f68120b94cecb2d87fe856bc115714b4e77bcdShishir Agrawal
1970566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1971da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
1972a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1973566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1974566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + AID);
1975da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1976da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            CMD_OPEN_CHANNEL, AID);
1977da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + response);
1978da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return response;
1979566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1980566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1981566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1982566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public boolean iccCloseLogicalChannel(int channel) {
1983a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1984566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1985566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + channel);
1986566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1987566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return false;
1988566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1989e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
1990566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + success);
1991566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return success;
1992566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1993566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1994566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1995566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public String iccTransmitApduLogicalChannel(int channel, int cla,
1996566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            int command, int p1, int p2, int p3, String data) {
1997a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1998566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1999566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) {
2000566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
2001566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
2002566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " data=" + data);
2003566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
2004566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
2005566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
2006566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            return "";
2007566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
2008566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
2009da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
2010566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
2011566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccTransmitApduLogicalChannel: " + response);
2012566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
2013566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // Append the returned status code to the end of the response payload.
2014566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        String s = Integer.toHexString(
2015566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
20165ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        if (response.payload != null) {
20175ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal            s = IccUtils.bytesToHexString(response.payload) + s;
20185ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        }
2019566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return s;
2020566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
2021e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
2022c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    @Override
2023da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
2024da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                int p3, String data) {
2025da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
2026da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2027da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
2028da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
2029da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
2030da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
2031da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2032da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
2033da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
2034da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccTransmitApduBasicChannel: " + response);
2035da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2036da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        // Append the returned status code to the end of the response payload.
2037da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        String s = Integer.toHexString(
2038da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
20395ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        if (response.payload != null) {
20405ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal            s = IccUtils.bytesToHexString(response.payload) + s;
20415ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        }
2042da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return s;
2043da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
2044da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2045da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
2046da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
2047da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            String filePath) {
2048da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
2049da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2050da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
2051da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("Exchange SIM_IO " + fileID + ":" + command + " " +
2052da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                p1 + " " + p2 + " " + p3 + ":" + filePath);
2053da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
2054da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2055da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response =
2056da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
20573edf3789a6e8b6b9ac28b7dfb24d6d7b00b3b554Yong Jiang                    new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath));
2058da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2059da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
2060da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal          log("Exchange SIM_IO [R]" + response);
2061da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
2062da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2063da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        byte[] result = null;
2064da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        int length = 2;
2065da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (response.payload != null) {
2066da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            length = 2 + response.payload.length;
2067da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
2068da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            System.arraycopy(response.payload, 0, result, 0, response.payload.length);
2069da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        } else {
2070da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
2071da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
2072da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2073da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 1] = (byte) response.sw2;
2074da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 2] = (byte) response.sw1;
2075da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return result;
2076da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
2077da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
2078da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
2079c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    public String sendEnvelopeWithStatus(String content) {
2080a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2081c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
2082c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
2083c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        if (response.payload == null) {
2084c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton          return "";
2085c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        }
2086c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
2087c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        // Append the returned status code to the end of the response payload.
2088c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        String s = Integer.toHexString(
2089c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
2090c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        s = IccUtils.bytesToHexString(response.payload) + s;
2091c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        return s;
2092c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    }
2093c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
2094e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
2095e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2096e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2097e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
2098e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
2099e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return the NV item as a String, or null on error.
2100e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
2101e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
2102e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public String nvReadItem(int itemID) {
2103a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2104e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID);
2105e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
2106e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
2107e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return value;
2108e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
2109e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
2110e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
2111e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
2112e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
2113e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
2114e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
2115e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemValue the value to write, as a String
2116e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
2117e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
2118e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
2119e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteItem(int itemID, String itemValue) {
2120a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2121e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
2122e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
2123e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                new Pair<Integer, String>(itemID, itemValue));
2124e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
2125e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
2126e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
2127e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
2128e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
2129e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
2130e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
2131e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
2132e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param preferredRoamingList byte array containing the new PRL
2133e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
2134e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
2135e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
2136e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
2137a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2138e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
2139e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
2140e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
2141e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
2142e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
2143e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
2144e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
2145e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Perform the specified type of NV config reset.
2146e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
2147e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
2148e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
2149e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
2150e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
2151e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
2152e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvResetConfig(int resetType) {
2153a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2154e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType);
2155e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
2156e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
2157e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
2158e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
21597c27be317e8757948178815426d3a329c852b9eeJake Hamby
21607c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
216136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
216236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default sim, 0 in the case of single standby.
216336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
216436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDefaultSim() {
216536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        //TODO Need to get it from Telephony Devcontroller
216636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return 0;
216736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
216836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
2169b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String[] getPcscfAddress(String apnType, String callingPackage) {
2170b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
2171b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return new String[0];
2172b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2173b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
2174b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
217587fca6f34c10e43e4dcfdd3f4e35bd4050e19582ram        return mPhone.getPcscfAddress(apnType);
217636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
217736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
217836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setImsRegistrationState(boolean registered) {
217936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceModifyPermission();
218036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone.setImsRegistrationState(registered);
218136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
218236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
218336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
218454788801de04c603a856596f4ae4377ab77a9821Stuart Scott     * Set the network selection mode to automatic.
218554788801de04c603a856596f4ae4377ab77a9821Stuart Scott     *
218654788801de04c603a856596f4ae4377ab77a9821Stuart Scott     */
218754788801de04c603a856596f4ae4377ab77a9821Stuart Scott    @Override
218854788801de04c603a856596f4ae4377ab77a9821Stuart Scott    public void setNetworkSelectionModeAutomatic(int subId) {
218954788801de04c603a856596f4ae4377ab77a9821Stuart Scott        enforceModifyPermissionOrCarrierPrivilege();
219054788801de04c603a856596f4ae4377ab77a9821Stuart Scott        if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
219154788801de04c603a856596f4ae4377ab77a9821Stuart Scott        sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
219254788801de04c603a856596f4ae4377ab77a9821Stuart Scott    }
219354788801de04c603a856596f4ae4377ab77a9821Stuart Scott
219454788801de04c603a856596f4ae4377ab77a9821Stuart Scott    /**
2195302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal     * Set the network selection mode to manual with the selected carrier.
2196302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal     */
2197302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    @Override
219877ba317277863812508869705308373b42364e0aShishir Agrawal    public boolean setNetworkSelectionModeManual(int subId, OperatorInfo operator,
219977ba317277863812508869705308373b42364e0aShishir Agrawal            boolean persistSelection) {
2200302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
2201302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal        if (DBG) log("setNetworkSelectionModeManual: subId:" + subId + " operator:" + operator);
220277ba317277863812508869705308373b42364e0aShishir Agrawal        ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operator,
220377ba317277863812508869705308373b42364e0aShishir Agrawal                persistSelection);
220477ba317277863812508869705308373b42364e0aShishir Agrawal        return (Boolean) sendRequest(CMD_SET_NETWORK_SELECTION_MODE_MANUAL, arg, subId);
2205302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    }
2206302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal
2207302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    /**
2208302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal     * Scans for available networks.
2209302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal     */
2210302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    @Override
2211302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    public CellNetworkScanResult getCellNetworkScanResults(int subId) {
2212302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
2213302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal        if (DBG) log("getCellNetworkScanResults: subId " + subId);
2214302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal        CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
2215302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal                CMD_PERFORM_NETWORK_SCAN, null, subId);
2216302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal        return result;
2217302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    }
2218302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal
2219302c8699cd4389dbb3ec9b2d23748f3f0d51a8daShishir Agrawal    /**
222084d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Get the calculated preferred network type.
222184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Used for debugging incorrect network type.
222284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     *
222384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * @return the preferred network type, defined in RILConstants.java.
222484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     */
222584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    @Override
2226b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public int getCalculatedPreferredNetworkType(String callingPackage) {
2227b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
2228b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return RILConstants.PREFERRED_NETWORK_MODE;
2229b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2230b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
223143330e02af9431ac18a9b9d6c09610f910b8c0f2Amit Mahajan        return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
223284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    }
223384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu
223484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    /**
22357c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Get the preferred network type.
22367c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
22377c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
22387c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return the preferred network type, defined in RILConstants.java.
22397c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
22407c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
224154788801de04c603a856596f4ae4377ab77a9821Stuart Scott    public int getPreferredNetworkType(int subId) {
2242a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
22437c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType");
224454788801de04c603a856596f4ae4377ab77a9821Stuart Scott        int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
22457c27be317e8757948178815426d3a329c852b9eeJake Hamby        int networkType = (result != null ? result[0] : -1);
22467c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType: " + networkType);
22477c27be317e8757948178815426d3a329c852b9eeJake Hamby        return networkType;
22487c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
22497c27be317e8757948178815426d3a329c852b9eeJake Hamby
22507c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
22517c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Set the preferred network type.
22527c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
22537c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
22547c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @param networkType the preferred network type, defined in RILConstants.java.
22557c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return true on success; false on any failure.
22567c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
22577c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
225854788801de04c603a856596f4ae4377ab77a9821Stuart Scott    public boolean setPreferredNetworkType(int subId, int networkType) {
2259a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
226054788801de04c603a856596f4ae4377ab77a9821Stuart Scott        if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
226154788801de04c603a856596f4ae4377ab77a9821Stuart Scott        Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
22627c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
226380bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        if (success) {
226480bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
226554788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
226680bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        }
22677c27be317e8757948178815426d3a329c852b9eeJake Hamby        return success;
22687c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
2269ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
2270ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
2271475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
2272475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
2273475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * tethering.
2274475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     *
2275475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * @return 0: Not required. 1: required. 2: Not set.
2276475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * @hide
2277475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     */
2278475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    @Override
2279475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    public int getTetherApnRequired() {
2280475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2281475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2282475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu                Settings.Global.TETHER_DUN_REQUIRED, 2);
2283475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2284475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        // config_tether_apndata.
2285475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2286475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu            dunRequired = 1;
2287475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        }
2288475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        return dunRequired;
2289475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    }
2290475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu
2291475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    /**
2292ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Set mobile data enabled
2293ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Used by the user through settings etc to turn on/off mobile data
2294ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
2295ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @param enable {@code true} turn turn data on, else {@code false}
2296ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
2297ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
2298e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville    public void setDataEnabled(int subId, boolean enable) {
2299ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        enforceModifyPermission();
2300e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        int phoneId = mSubscriptionController.getPhoneId(subId);
2301e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2302e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        Phone phone = PhoneFactory.getPhone(phoneId);
2303e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        if (phone != null) {
2304e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            log("setDataEnabled: subId=" + subId + " enable=" + enable);
2305e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            phone.setDataEnabled(enable);
2306e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        } else {
2307e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            loge("setDataEnabled: no phone for subId=" + subId);
2308e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        }
2309ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
2310ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
2311ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
2312646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Get whether mobile data is enabled.
2313646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     *
2314646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Note that this used to be available from ConnectivityService, gated by
2315646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * ACCESS_NETWORK_STATE permission, so this will accept either that or
2316646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * our MODIFY_PHONE_STATE.
2317ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
2318ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @return {@code true} if data is enabled else {@code false}
2319ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
2320ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
2321e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville    public boolean getDataEnabled(int subId) {
2322646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        try {
2323646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2324646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
2325646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        } catch (Exception e) {
2326646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
2327646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
2328646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        }
2329e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        int phoneId = mSubscriptionController.getPhoneId(subId);
2330e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2331e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        Phone phone = PhoneFactory.getPhone(phoneId);
2332e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        if (phone != null) {
2333e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            boolean retVal = phone.getDataEnabled();
2334e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
2335e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            return retVal;
2336e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        } else {
2337e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
2338e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            return false;
2339e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        }
2340ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
234160f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal
234260f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    @Override
23435e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal    public int getCarrierPrivilegeStatus() {
234421409250c4001605606a37c3903dc22805410900Shishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
2345eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
23465e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal            loge("getCarrierPrivilegeStatus: No UICC");
2347eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2348eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
2349eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatusForCurrentTransaction(
2350f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                mPhone.getContext().getPackageManager());
235160f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    }
23522934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu
23532934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    @Override
235450ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    public int checkCarrierPrivilegesForPackage(String pkgName) {
235521409250c4001605606a37c3903dc22805410900Shishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
2356eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
2357eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("checkCarrierPrivilegesForPackage: No UICC");
2358eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2359eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
236050ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
236150ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    }
236250ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson
236350ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    @Override
236450ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
236550ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
236650ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
236750ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            UiccCard card = UiccController.getInstance().getUiccCard(i);
236850ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            if (card == null) {
23697d320dff9d5b30b7b8a2dc9ef7574dc9bb8571b8Jonathan Basseri              // No UICC in that slot.
237050ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson              continue;
237150ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            }
237250ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson
237350ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            result = card.getCarrierPrivilegeStatus(
237450ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson                mPhone.getContext().getPackageManager(), pkgName);
237550ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
237650ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson                break;
237750ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            }
237850ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        }
237950ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson
238050ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        return result;
23812934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    }
238289e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
238389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
2384e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu    public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2385e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2386e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu            loge("phoneId " + phoneId + " is not valid.");
2387e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu            return null;
2388e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu        }
2389e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu        UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
2390eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        if (card == null) {
2391af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero            loge("getCarrierPackageNamesForIntent: No UICC");
2392eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            return null ;
2393eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        }
2394af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero        return card.getCarrierPackageNamesForIntent(
2395483aff78d6bada4c2f4d28f804935d24c8173fceSvetoslav                mPhone.getContext().getPackageManager(), intent);
2396eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    }
2397eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal
2398b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private String getIccId(int subId) {
2399356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
2400356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        UiccCard card = phone == null ? null : phone.getUiccCard();
240197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (card == null) {
240297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            loge("getIccId: No UICC");
240397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return null;
240497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
240597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = card.getIccId();
240697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (TextUtils.isEmpty(iccId)) {
240797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            loge("getIccId: ICC ID is null or empty.");
240897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return null;
240997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
241097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return iccId;
241197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    }
241297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
2413eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    @Override
241485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
241585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            String number) {
24165e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        enforceCarrierPrivilege();
241797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
241885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String iccId = getIccId(subId);
2419356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final Phone phone = getPhone(subId);
2420356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        if (phone == null) {
2421356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe            return false;
2422356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        }
2423356d76380ebed2bdb3b2abac40e55c073ceefb83Sanket Padawe        final String subscriberId = phone.getSubscriberId();
242485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
242585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        if (DBG_MERGE) {
242685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
242785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    + subscriberId + " to " + number);
242885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
242985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
2430495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        if (TextUtils.isEmpty(iccId)) {
2431495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            return false;
2432495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        }
243397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
243485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
243585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
243685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2437495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        if (alphaTag == null) {
2438495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.remove(alphaTagPrefKey);
2439495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        } else {
2440495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.putString(alphaTagPrefKey, alphaTag);
244197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
2442495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal
244385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Record both the line number and IMSI for this ICCID, since we need to
244485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // track all merged IMSIs based on line number
244585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
244685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2447495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        if (number == null) {
2448495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.remove(numberPrefKey);
244985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            editor.remove(subscriberPrefKey);
2450495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        } else {
2451495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.putString(numberPrefKey, number);
245285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            editor.putString(subscriberPrefKey, subscriberId);
2453495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        }
245485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
2455495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        editor.commit();
2456495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        return true;
24577226c84acb402f96e527650347391fa025294350Derek Tan    }
24587226c84acb402f96e527650347391fa025294350Derek Tan
24597226c84acb402f96e527650347391fa025294350Derek Tan    @Override
2460b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String getLine1NumberForDisplay(int subId, String callingPackage) {
2461fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki        // This is open to apps with WRITE_SMS.
2462fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki        if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
2463b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return null;
2464b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
246597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
246697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
246797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
246897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2469df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee            return mTelephonySharedPreferences.getString(numberPrefKey, null);
24707226c84acb402f96e527650347391fa025294350Derek Tan        }
247197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return null;
24727226c84acb402f96e527650347391fa025294350Derek Tan    }
24737226c84acb402f96e527650347391fa025294350Derek Tan
24747226c84acb402f96e527650347391fa025294350Derek Tan    @Override
2475b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2476b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2477b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return null;
2478b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
247997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
248097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
248197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
248297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2483df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee            return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
24847226c84acb402f96e527650347391fa025294350Derek Tan        }
248597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return null;
24867226c84acb402f96e527650347391fa025294350Derek Tan    }
2487b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal
2488b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    @Override
24898e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov    public String[] getMergedSubscriberIds(String callingPackage) {
24908e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
24918e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov            return null;
24928e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        }
249385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final Context context = mPhone.getContext();
249485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
249585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final SubscriptionManager sub = SubscriptionManager.from(context);
249685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
249785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Figure out what subscribers are currently active
249885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final ArraySet<String> activeSubscriberIds = new ArraySet<>();
24998e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        // Clear calling identity, when calling TelephonyManager, because callerUid must be
25008e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        // the process, where TelephonyManager was instantiated. Otherwise AppOps check will fail.
25018e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        final long identity  = Binder.clearCallingIdentity();
25028e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        try {
25038e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov            final int[] subIds = sub.getActiveSubscriptionIdList();
25048e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov            for (int subId : subIds) {
25058e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov                activeSubscriberIds.add(tele.getSubscriberId(subId));
25068e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov            }
25078e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov        } finally {
25088e53b0bd5f402210bd0187da70a6b2ecc14a296bFyodor Kupolov            Binder.restoreCallingIdentity(identity);
250985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
251085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
251185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // First pass, find a number override for an active subscriber
251285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        String mergeNumber = null;
251385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
251485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        for (String key : prefs.keySet()) {
251585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
251685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                final String subscriberId = (String) prefs.get(key);
251785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                if (activeSubscriberIds.contains(subscriberId)) {
251885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
251985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
252085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    mergeNumber = (String) prefs.get(numberKey);
252185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    if (DBG_MERGE) {
252285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                        Slog.d(LOG_TAG, "Found line number " + mergeNumber
252385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                                + " for active subscriber " + subscriberId);
252485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    }
252585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    if (!TextUtils.isEmpty(mergeNumber)) {
252685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                        break;
252785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    }
252885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                }
252985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            }
253085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
253185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
253285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Shortcut when no active merged subscribers
253385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        if (TextUtils.isEmpty(mergeNumber)) {
253485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            return null;
253585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
253685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
253785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Second pass, find all subscribers under that line override
253885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final ArraySet<String> result = new ArraySet<>();
253985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        for (String key : prefs.keySet()) {
254085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
254185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                final String number = (String) prefs.get(key);
254285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                if (mergeNumber.equals(number)) {
254385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
254485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
254585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String subscriberId = (String) prefs.get(subscriberKey);
254685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    if (!TextUtils.isEmpty(subscriberId)) {
254785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                        result.add(subscriberId);
254885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    }
254985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                }
255085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            }
255185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
255285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
255385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String[] resultArray = result.toArray(new String[result.size()]);
255485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        Arrays.sort(resultArray);
255585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        if (DBG_MERGE) {
255685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
255785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
255885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        return resultArray;
255985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    }
256085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
256185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    @Override
2562a3dfd75141d37ae7e170eeb200374f62235b092eShishir Agrawal    public boolean setOperatorBrandOverride(String brand) {
25635e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        enforceCarrierPrivilege();
2564a3dfd75141d37ae7e170eeb200374f62235b092eShishir Agrawal        return mPhone.setOperatorBrandOverride(brand);
2565b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    }
25664bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
25674bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    @Override
2568621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal    public boolean setRoamingOverride(List<String> gsmRoamingList,
2569621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal            List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2570621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal            List<String> cdmaNonRoamingList) {
2571621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal        enforceCarrierPrivilege();
2572621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal        return mPhone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
2573621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal                cdmaNonRoamingList);
2574621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal    }
2575621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal
2576621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal    @Override
25774bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
25784bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        enforceModifyPermission();
25794bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
25804bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        int returnValue = 0;
25814bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        try {
25824bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
25834bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(result.exception == null) {
25844bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if (result.result != null) {
25854bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    byte[] responseData = (byte[])(result.result);
25864bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    if(responseData.length > oemResp.length) {
25874bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
25884bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                responseData.length +  "bytes. Buffer Size is " +
25894bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                oemResp.length + "bytes.");
25904bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
25914bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
25924bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    returnValue = responseData.length;
25934bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                }
25944bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            } else {
25954bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                CommandException ex = (CommandException) result.exception;
25964bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                returnValue = ex.getCommandError().ordinal();
25974bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if(returnValue > 0) returnValue *= -1;
25984bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            }
25994bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        } catch (RuntimeException e) {
26004bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
26014bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
26024bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(returnValue > 0) returnValue *= -1;
26034bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        }
26044bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
26054bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        return returnValue;
26064bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    }
26075d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville
26085d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    @Override
26095d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    public void setRadioCapability(RadioAccessFamily[] rafs) {
26105d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        try {
26115d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville            ProxyController.getInstance().setRadioCapability(rafs);
26125d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        } catch (RuntimeException e) {
26135d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville            Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
26145d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        }
26155d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    }
26165d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville
26175d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    @Override
261836b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt    public int getRadioAccessFamily(int phoneId, String callingPackage) {
261936b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
262036b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt            return RadioAccessFamily.RAF_UNKNOWN;
262136b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt        }
262236b23afecddd082056dc1ce65e38c38f2805ca84Robert Greenwalt
26235d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        return ProxyController.getInstance().getRadioAccessFamily(phoneId);
26245d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    }
2625df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee
2626df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    @Override
2627df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    public void enableVideoCalling(boolean enable) {
2628df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        enforceModifyPermission();
2629df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2630df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        editor.putBoolean(PREF_ENABLE_VIDEO_CALLING, enable);
2631df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        editor.commit();
2632df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    }
2633df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee
2634df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    @Override
2635b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public boolean isVideoCallingEnabled(String callingPackage) {
2636b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
2637b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return false;
2638b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2639b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
264077527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // Check the user preference and the  system-level IMS setting. Even if the user has
264177527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // enabled video calling, if IMS is disabled we aren't able to support video calling.
264277527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // In the long run, we may instead need to check if there exists a connection service
264377527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // which can support video calling.
2644312e8177b25ab359627685d449e0a5fdb539809fAndrew Lee        return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
2645312e8177b25ab359627685d449e0a5fdb539809fAndrew Lee                && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
2646312e8177b25ab359627685d449e0a5fdb539809fAndrew Lee                && mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true);
2647df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    }
2648afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com
2649a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    @Override
2650a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    public boolean canChangeDtmfToneLength() {
26519504c6b5c5c7072f72d8a9e6df59dbda8a6ccbe4Jonathan Basseri        return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
2652a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    }
2653a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee
2654a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    @Override
2655a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    public boolean isWorldPhone() {
26569504c6b5c5c7072f72d8a9e6df59dbda8a6ccbe4Jonathan Basseri        return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
2657a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    }
2658a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee
26599431b838f89399db2278c0436bd2817322a45f74Andrew Lee    @Override
26609431b838f89399db2278c0436bd2817322a45f74Andrew Lee    public boolean isTtyModeSupported() {
26619431b838f89399db2278c0436bd2817322a45f74Andrew Lee        TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
26629431b838f89399db2278c0436bd2817322a45f74Andrew Lee        TelephonyManager telephonyManager =
26639431b838f89399db2278c0436bd2817322a45f74Andrew Lee                (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
26649431b838f89399db2278c0436bd2817322a45f74Andrew Lee        return !telephonyManager.isMultiSimEnabled() && telecomManager.isTtySupported();
26659431b838f89399db2278c0436bd2817322a45f74Andrew Lee    }
26669431b838f89399db2278c0436bd2817322a45f74Andrew Lee
26679431b838f89399db2278c0436bd2817322a45f74Andrew Lee    @Override
26689431b838f89399db2278c0436bd2817322a45f74Andrew Lee    public boolean isHearingAidCompatibilitySupported() {
26699431b838f89399db2278c0436bd2817322a45f74Andrew Lee        return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
26709431b838f89399db2278c0436bd2817322a45f74Andrew Lee    }
26719431b838f89399db2278c0436bd2817322a45f74Andrew Lee
26727310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe    /**
26737310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     * Returns the unique device ID of phone, for example, the IMEI for
26747310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     * GSM and the MEID for CDMA phones. Return null if device ID is not available.
26757310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     *
26767310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     * <p>Requires Permission:
26777310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
26787310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     */
26797310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe    @Override
2680b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String getDeviceId(String callingPackage) {
2681b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getDeviceId")) {
2682b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return null;
2683b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2684b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
26857310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        final Phone phone = PhoneFactory.getPhone(0);
26867310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        if (phone != null) {
26877310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe            return phone.getDeviceId();
26887310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        } else {
26897310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe            return null;
26907310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        }
26917310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe    }
26927310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe
2693afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com    /*
2694afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com     * {@hide}
2695afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com     * Returns the IMS Registration Status
2696afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com     */
26977a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    @Override
2698afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com    public boolean isImsRegistered() {
2699afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com        return mPhone.isImsRegistered();
2700afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com    }
27017a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon
27027a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    @Override
27037a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
27047a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon        return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
27057a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    }
2706dcfc793ddff32e3fd5ab49db2647d7b08fc4d29cNathan Harold
2707c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    /*
2708c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * {@hide}
2709c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * Returns the IMS Registration Status
2710c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     */
27113b7a1bce40307becff28763f505faeffa927d577Etan Cohen    public boolean isWifiCallingAvailable() {
2712c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold        return mPhone.isWifiCallingEnabled();
2713c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    }
2714c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold
2715c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    /*
2716c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * {@hide}
2717c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * Returns the IMS Registration Status
2718c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     */
27193b7a1bce40307becff28763f505faeffa927d577Etan Cohen    public boolean isVolteAvailable() {
2720c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold        return mPhone.isVolteEnabled();
2721c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    }
2722b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
27233b7a1bce40307becff28763f505faeffa927d577Etan Cohen    /*
27243b7a1bce40307becff28763f505faeffa927d577Etan Cohen     * {@hide} Returns the IMS Registration Status
27253b7a1bce40307becff28763f505faeffa927d577Etan Cohen     */
27263b7a1bce40307becff28763f505faeffa927d577Etan Cohen    public boolean isVideoTelephonyAvailable() {
27273b7a1bce40307becff28763f505faeffa927d577Etan Cohen        return mPhone.isVideoEnabled();
27283b7a1bce40307becff28763f505faeffa927d577Etan Cohen    }
27293b7a1bce40307becff28763f505faeffa927d577Etan Cohen
2730b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    private boolean canReadPhoneState(String callingPackage, String message) {
2731921655c60d4b464b8f4add98e0e5fb3ca48cccd4Etan Cohen        try {
273283ea23b90597f39f5f8f899023ae099eab0e98e2Amit Mahajan            mApp.enforceCallingOrSelfPermission(
2733921655c60d4b464b8f4add98e0e5fb3ca48cccd4Etan Cohen                    android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
2734921655c60d4b464b8f4add98e0e5fb3ca48cccd4Etan Cohen
273583ea23b90597f39f5f8f899023ae099eab0e98e2Amit Mahajan            // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
2736921655c60d4b464b8f4add98e0e5fb3ca48cccd4Etan Cohen            return true;
2737785783f758260e5d23633317f1a286a89d66090dAmit Mahajan        } catch (SecurityException e) {
2738785783f758260e5d23633317f1a286a89d66090dAmit Mahajan            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
2739785783f758260e5d23633317f1a286a89d66090dAmit Mahajan                    message);
2740921655c60d4b464b8f4add98e0e5fb3ca48cccd4Etan Cohen        }
2741b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
2742b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
2743b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov                callingPackage) != AppOpsManager.MODE_ALLOWED) {
2744b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return false;
2745b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2746b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
2747b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        return true;
2748b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    }
27498eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott
2750fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki    /**
2751fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki     * Besides READ_PHONE_STATE, WRITE_SMS also allows apps to get phone numbers.
2752fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki     */
2753fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki    private boolean canReadPhoneNumber(String callingPackage, String message) {
2754e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki        // Default SMS app can always read it.
2755e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki        if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
2756e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
2757e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki            return true;
2758e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki        }
2759e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki        try {
2760e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki            return canReadPhoneState(callingPackage, message);
2761e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki        } catch (SecurityException e) {
2762e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki            // Can be read with READ_SMS too.
2763e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
2764e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki            return mAppOps.noteOp(AppOpsManager.OP_READ_SMS,
2765e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki                    Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED;
2766e4072d10b761c7e167c4f9b5d7570c6417c1d054Makoto Onuki        }
2767fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki    }
2768fee69345c86d13b46e9e1d1e36178ebef17538eeMakoto Onuki
27698eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    @Override
27708eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    public void factoryReset(int subId) {
27718eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott        enforceConnectivityInternalPermission();
2772981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
2773981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott            return;
2774981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott        }
2775981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott
2776cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov        final long identity = Binder.clearCallingIdentity();
2777cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov        try {
2778981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott            if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
2779981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott                    UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
2780cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Enable data
2781cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                setDataEnabled(subId, true);
2782cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Set network selection mode to automatic
2783cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                setNetworkSelectionModeAutomatic(subId);
2784cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Set preferred mobile network type to the best available
2785cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
2786cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Turn off roaming
2787cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                SubscriptionManager.from(mApp).setDataRoaming(0, subId);
2788cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov            }
2789cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov        } finally {
2790cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov            Binder.restoreCallingIdentity(identity);
27918eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott        }
27928eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    }
27931c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
27941c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    @Override
27951c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    public String getLocaleFromDefaultSim() {
27961c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // We query all subscriptions instead of just the active ones, because
27971c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // this might be called early on in the provisioning flow when the
27981c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // subscriptions potentially aren't active yet.
27991c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
28001c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (slist == null || slist.isEmpty()) {
28011c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return null;
28021c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
28031c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
28041c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // This function may be called very early, say, from the setup wizard, at
28051c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // which point we won't have a default subscription set. If that's the case
28061c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // we just choose the first, which will be valid in "most cases".
28071c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final int defaultSubId = getDefaultSubscription();
28081c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        SubscriptionInfo info = null;
28091c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
28101c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            info = slist.get(0);
28111c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        } else {
28121c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            for (SubscriptionInfo item : slist) {
28131c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                if (item.getSubscriptionId() == defaultSubId) {
28141c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    info = item;
28151c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    break;
28161c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                }
28171c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            }
28181c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
28191c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            if (info == null) {
28201c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                return null;
28211c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            }
28221c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
28231c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
28241c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // Try and fetch the locale from the carrier properties or from the SIM language
28251c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // preferences (EF-PL and EF-LI)...
2826183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill        final int mcc = info.getMcc();
28271c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final Phone defaultPhone = getPhone(info.getSubscriptionId());
2828011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath        String simLanguage = null;
28291c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (defaultPhone != null) {
28301c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
28311c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            if (localeFromDefaultSim != null) {
2832011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath                if (!localeFromDefaultSim.getCountry().isEmpty()) {
2833183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill                    if (DBG) log("Using locale from default SIM:" + localeFromDefaultSim);
2834183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill                    return localeFromDefaultSim.toLanguageTag();
2835011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath                } else {
2836011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath                    simLanguage = localeFromDefaultSim.getLanguage();
2837183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill                }
28381c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            }
28391c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
28401c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
2841011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath        // The SIM language preferences only store a language (e.g. fr = French), not an
2842011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath        // exact locale (e.g. fr_FR = French/France). So, if the locale returned from
2843011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath        // the SIM and carrier preferences does not include a country we add the country
2844011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath        // determined from the SIM MCC to provide an exact locale.
2845011676f979e1f0c8fd2d042a38e21cde5852789eNarayan Kamath        final Locale mccLocale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc, simLanguage);
2846183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill        if (mccLocale != null) {
2847183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill            if (DBG) log("No locale from default SIM, using mcc locale:" + mccLocale);
2848183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill            return mccLocale.toLanguageTag();
28491c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
28501c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
2851183b2de07cb23d8bdf68d14e25cdae96c905b37bTony Hill        if (DBG) log("No locale found - returning null");
28521c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        return null;
28531c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    }
28541c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
28551c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    private List<SubscriptionInfo> getAllSubscriptionInfoList() {
28561c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final long identity = Binder.clearCallingIdentity();
28571c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        try {
28581c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return mSubscriptionController.getAllSubInfoList(
28591c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    mPhone.getContext().getOpPackageName());
28601c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        } finally {
28611c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            Binder.restoreCallingIdentity(identity);
28621c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
28631c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    }
28641c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
28651c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
28661c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final long identity = Binder.clearCallingIdentity();
28671c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        try {
28681c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return mSubscriptionController.getActiveSubscriptionInfoList(
28691c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    mPhone.getContext().getOpPackageName());
28701c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        } finally {
28711c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            Binder.restoreCallingIdentity(identity);
28721c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
28731c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    }
28747fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
28757fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    /**
28767fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham     * {@hide}
28777fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham     * Returns the modem stats
28787fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham     */
28797fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    @Override
28807fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    public ModemActivityInfo getModemActivityInfo() {
28817fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham        return (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
28827fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    }
28837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
2884