PhoneInterfaceManager.java revision 61a60ad2e6944a80944898e636c2e9d9fd7b0e70
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;
60566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.CommandException;
617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.DefaultPhoneNotifier;
627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.ITelephony;
63e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.telephony.IccCard;
641c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamathimport com.android.internal.telephony.MccTable;
657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.Phone;
6636469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport com.android.internal.telephony.PhoneFactory;
675d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Savilleimport com.android.internal.telephony.ProxyController;
687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport com.android.internal.telephony.PhoneConstants;
69b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganovimport com.android.internal.telephony.RILConstants;
70ac1bdfd36366426513d51bd2c4b107b00533889eWink Savilleimport com.android.internal.telephony.SubscriptionController;
71566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccIoResult;
72566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.IccUtils;
73eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawalimport com.android.internal.telephony.uicc.UiccCard;
74566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawalimport com.android.internal.telephony.uicc.UiccController;
75e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport com.android.internal.util.HexDump;
767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7736469e74b7c79ed84148754190c38196eb9a2c49Wink Savilleimport static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
7836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordonimport java.util.ArrayList;
8085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport java.util.Arrays;
81621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawalimport java.util.HashMap;
82621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawalimport java.util.Iterator;
83e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hambyimport java.util.List;
841c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamathimport java.util.Locale;
8585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport java.util.Map;
8685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkeyimport java.util.Objects;
877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon/**
897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon * Implementation of the ITelephony interface.
907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon */
91117fee7467c140dccdc66972f60031dae2d55b35Santos Cordonpublic class PhoneInterfaceManager extends ITelephony.Stub {
927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final String LOG_TAG = "PhoneInterfaceManager";
937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final boolean DBG_LOC = false;
9585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    private static final boolean DBG_MERGE = false;
967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Message codes used with mMainThreadHandler
987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_PIN_MMI = 1;
997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_HANDLE_NEIGHBORING_CELL = 2;
1007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int EVENT_NEIGHBORING_CELL_DONE = 3;
1017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_ANSWER_RINGING_CALL = 4;
1027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final int CMD_END_CALL = 5;  // not used yet
103da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int CMD_TRANSMIT_APDU_LOGICAL_CHANNEL = 7;
104da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 8;
105566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_OPEN_CHANNEL = 9;
106566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_OPEN_CHANNEL_DONE = 10;
107566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int CMD_CLOSE_CHANNEL = 11;
108566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final int EVENT_CLOSE_CHANNEL_DONE = 12;
109e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_READ_ITEM = 13;
110e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_READ_ITEM_DONE = 14;
111e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_ITEM = 15;
112e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_ITEM_DONE = 16;
113e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_WRITE_CDMA_PRL = 17;
114e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_WRITE_CDMA_PRL_DONE = 18;
115e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int CMD_NV_RESET_CONFIG = 19;
116e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static final int EVENT_NV_RESET_CONFIG_DONE = 20;
1177c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_GET_PREFERRED_NETWORK_TYPE = 21;
1187c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_GET_PREFERRED_NETWORK_TYPE_DONE = 22;
1197c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int CMD_SET_PREFERRED_NETWORK_TYPE = 23;
1207c27be317e8757948178815426d3a329c852b9eeJake Hamby    private static final int EVENT_SET_PREFERRED_NETWORK_TYPE_DONE = 24;
12135b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int CMD_SEND_ENVELOPE = 25;
12235b5945231af96ad0d7ebf4cfcaafeb677d8c75cSailesh Nepal    private static final int EVENT_SEND_ENVELOPE_DONE = 26;
1236b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_INVOKE_OEM_RIL_REQUEST_RAW = 27;
1246b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE = 28;
1256b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_TRANSMIT_APDU_BASIC_CHANNEL = 29;
1266b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 30;
1276b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int CMD_EXCHANGE_SIM_IO = 31;
1286b088eef6c47d96b9b2a0097e3b8ee8b4332f068Derek Tan    private static final int EVENT_EXCHANGE_SIM_IO_DONE = 32;
12976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    private static final int CMD_SET_VOICEMAIL_NUMBER = 33;
13076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    private static final int EVENT_SET_VOICEMAIL_NUMBER_DONE = 34;
13154788801de04c603a856596f4ae4377ab77a9821Stuart Scott    private static final int CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC = 35;
13254788801de04c603a856596f4ae4377ab77a9821Stuart Scott    private static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE = 36;
1337fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    private static final int CMD_GET_MODEM_ACTIVITY_INFO = 37;
1347fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    private static final int EVENT_GET_MODEM_ACTIVITY_INFO_DONE = 38;
1357fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
1367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** The singleton instance. */
1387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static PhoneInterfaceManager sInstance;
1397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1403ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private PhoneGlobals mApp;
1413ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private Phone mPhone;
1423ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private CallManager mCM;
143981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott    private UserManager mUserManager;
1443ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private AppOpsManager mAppOps;
1453ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private MainThreadHandler mMainThreadHandler;
146ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville    private SubscriptionController mSubscriptionController;
1473ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville    private SharedPreferences mTelephonySharedPreferences;
1487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
15097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
15185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    private static final String PREF_CARRIERS_SUBSCRIBER_PREFIX = "carrier_subscriber_";
152df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    private static final String PREF_ENABLE_VIDEO_CALLING = "enable_video_calling";
15389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
15489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    /**
155566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     * A request object to use for transmitting data to an ICC.
156566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal     */
157566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    private static final class IccAPDUArgument {
158566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public int channel, cla, command, p1, p2, p3;
159566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public String data;
160566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
161566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        public IccAPDUArgument(int channel, int cla, int command,
162566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                int p1, int p2, int p3, String data) {
163566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.channel = channel;
164566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.cla = cla;
165566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.command = command;
166566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p1 = p1;
167566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p2 = p2;
168566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.p3 = p3;
169566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            this.data = data;
170566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
171566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
172566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
173566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
1747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
1757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request after sending. The main thread will notify the request when it is complete.
1767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
1777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static final class MainThreadRequest {
1787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The argument to use for the request */
1797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object argument;
1807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /** The result of the request that is run on the main thread */
1817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public Object result;
18276d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        /** The subscriber id that this request applies to. Null if default. */
18376d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        public Integer subId;
1847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public MainThreadRequest(Object argument) {
1867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            this.argument = argument;
1877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
18876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
18976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        public MainThreadRequest(Object argument, Integer subId) {
19076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal            this.argument = argument;
19176d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal            this.subId = subId;
19276d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        }
1937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
195cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    private static final class IncomingThirdPartyCallArgs {
196cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final ComponentName component;
197cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callId;
198cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public final String callerDisplayName;
199cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
200cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        public IncomingThirdPartyCallArgs(ComponentName component, String callId,
201cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal                String callerDisplayName) {
202cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.component = component;
203cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callId = callId;
204cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal            this.callerDisplayName = callerDisplayName;
205cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal        }
206cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal    }
207cc0375f8f26f868a55c36616921f4c572347062bSailesh Nepal
2087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
2097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * A handler that processes messages on the main thread in the phone process. Since many
2107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * of the Phone calls are not thread safe this is needed to shuttle the requests from the
2117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * inbound binder threads to the main thread in the phone process.  The Binder thread
2127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * may provide a {@link MainThreadRequest} object in the msg.obj field that they are waiting
2137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * on, which will be notified when the operation completes and will contain the result of the
2147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * request.
2157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
2167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * <p>If a MainThreadRequest object is provided in the msg.obj field,
2177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * note that request.result must be set to something non-null for the calling thread to
2187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * unblock.
2197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
2207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private final class MainThreadHandler extends Handler {
2217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
2227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void handleMessage(Message msg) {
2237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            MainThreadRequest request;
2247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message onCompleted;
2257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            AsyncResult ar;
22621409250c4001605606a37c3903dc22805410900Shishir Agrawal            UiccCard uiccCard = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
227da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            IccAPDUArgument iccArgument;
2287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            switch (msg.what) {
2307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_PIN_MMI:
2317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
232584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    request.result = getPhoneFromRequest(request).handlePinMmi(
233584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                            (String) request.argument);
2347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_HANDLE_NEIGHBORING_CELL:
2417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
2427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE,
2437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            request);
2447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    mPhone.getNeighboringCids(onCompleted);
2457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case EVENT_NEIGHBORING_CELL_DONE:
2487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    ar = (AsyncResult) msg.obj;
2497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) ar.userObj;
2507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (ar.exception == null && ar.result != null) {
2517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.result = ar.result;
2527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // create an empty list to notify the waiting thread
254e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = new ArrayList<NeighboringCellInfo>(0);
2557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2567d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2577d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_ANSWER_RINGING_CALL:
2630887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                    request = (MainThreadRequest) msg.obj;
264584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    int answer_subId = request.subId;
2650887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                    answerRingingCallInternal(answer_subId);
2667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
2687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                case CMD_END_CALL:
2697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request = (MainThreadRequest) msg.obj;
270584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    int end_subId = request.subId;
2710887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                    final boolean hungUp;
272ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    Phone phone = getPhone(end_subId);
273ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    if (phone == null) {
274ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                        if (DBG) log("CMD_END_CALL: no phone for id: " + end_subId);
275ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                        break;
276ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    }
277ae4e36d0e6edc3a912e822e844ab362dd7469491Anthony Lee                    int phoneType = phone.getPhoneType();
2787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
2797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // CDMA: If the user presses the Power button we treat it as
2807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // ending the complete call session
2810887461919173015886ea69ef6c6afbe20ebf1dcWink Saville                        hungUp = PhoneUtils.hangupRingingAndActive(getPhone(end_subId));
2827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
2837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        // GSM: End the call as per the Phone state
2847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        hungUp = PhoneUtils.hangup(mCM);
2857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    } else {
2867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
2877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
2897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.result = hungUp;
2907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Wake up the requesting thread
2917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    synchronized (request) {
2927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        request.notifyAll();
2937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
2947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
2957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
296da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_LOGICAL_CHANNEL:
297566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
298da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
299eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
300eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccTransmitApduLogicalChannel: No UICC");
301eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
302eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
303eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
304eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
305eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
306da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE,
307da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
308eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccTransmitApduLogicalChannel(
309da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.channel, iccArgument.cla, iccArgument.command,
310da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p1, iccArgument.p2, iccArgument.p3, iccArgument.data,
311566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            onCompleted);
312eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
313566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
314566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
315da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
316566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
317566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
318566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
319566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = ar.result;
320566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
321566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
322566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
323566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Empty response");
324e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
325566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: CommandException: " +
326e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
327566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
328566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccTransmitApduLogicalChannel: Unknown exception");
329566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
330566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
331566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
332566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
333566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
334566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
335566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
336da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_TRANSMIT_APDU_BASIC_CHANNEL:
337da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
338da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
339da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
340da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccTransmitApduBasicChannel: No UICC");
341da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
342da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
343da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
344da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
345da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
346da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE,
347da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request);
348da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccTransmitApduBasicChannel(
349da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.cla, iccArgument.command, iccArgument.p1, iccArgument.p2,
350da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            iccArgument.p3, iccArgument.data, onCompleted);
351da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
352da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
353da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
354da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
355da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
356da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
357da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
358da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
359da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
360da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
361da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.result == null) {
362da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Empty response");
363da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else if (ar.exception instanceof CommandException) {
364da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: CommandException: " +
365da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                    ar.exception);
366da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        } else {
367da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccTransmitApduBasicChannel: Unknown exception");
368da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
369da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
370da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
371da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
372da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
373da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
374da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
375da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case CMD_EXCHANGE_SIM_IO:
376da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
377da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    iccArgument = (IccAPDUArgument) request.argument;
378da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (uiccCard == null) {
379da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        loge("iccExchangeSimIO: No UICC");
380da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
381da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        synchronized (request) {
382da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            request.notifyAll();
383da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
384da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
385da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        onCompleted = obtainMessage(EVENT_EXCHANGE_SIM_IO_DONE,
386da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                request);
387da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        uiccCard.iccExchangeSimIO(iccArgument.cla, /* fileID */
388da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.command, iccArgument.p1, iccArgument.p2, iccArgument.p3,
389da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                iccArgument.data, onCompleted);
390da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
391da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
392da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
393da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                case EVENT_EXCHANGE_SIM_IO_DONE:
394da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    ar = (AsyncResult) msg.obj;
395da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
396da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
397da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = ar.result;
398da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    } else {
399da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.result = new IccIoResult(0x6f, 0, (byte[])null);
400da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
401da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    synchronized (request) {
402da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        request.notifyAll();
403da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    }
404da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    break;
405da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
4064d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case CMD_SEND_ENVELOPE:
4074d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) msg.obj;
408eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
409eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("sendEnvelopeWithStatus: No UICC");
410eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
411eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
412eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
413eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
414eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
415eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_SEND_ENVELOPE_DONE, request);
416eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.sendEnvelopeWithStatus((String)request.argument, onCompleted);
417eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
4184d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
4194d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
4204d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                case EVENT_SEND_ENVELOPE_DONE:
4214d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    ar = (AsyncResult) msg.obj;
4224d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    request = (MainThreadRequest) ar.userObj;
4239f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                    if (ar.exception == null && ar.result != null) {
4249f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = ar.result;
4254d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    } else {
4269f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
4279f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        if (ar.result == null) {
4289f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: Empty response");
4299f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else if (ar.exception instanceof CommandException) {
4309f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: CommandException: " +
4319f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                                    ar.exception);
4329f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        } else {
4339f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                            loge("sendEnvelopeWithStatus: exception:" + ar.exception);
4349f9877db9261aac66cfabf85b745440cfd970b9cShishir Agrawal                        }
4354d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4364d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    synchronized (request) {
4374d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                        request.notifyAll();
4384d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    }
4394d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan                    break;
4404d5e5c1b4742ed532fd2963e3d08b913ac565d16Derek Tan
441566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_OPEN_CHANNEL:
442566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
443eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
444eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccOpenLogicalChannel: No UICC");
445eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
446eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
447eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
448eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
449eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
450eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_OPEN_CHANNEL_DONE, request);
451eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccOpenLogicalChannel((String)request.argument, onCompleted);
452eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
453566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
454566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
455566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_OPEN_CHANNEL_DONE:
456566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
457566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
458da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    IccOpenLogicalChannelResponse openChannelResp;
459566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    if (ar.exception == null && ar.result != null) {
460da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int[] result = (int[]) ar.result;
461da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        int channelId = result[0];
462da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        byte[] selectResponse = null;
463da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (result.length > 1) {
464da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            selectResponse = new byte[result.length - 1];
465da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            for (int i = 1; i < result.length; ++i) {
466da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                                selectResponse[i - 1] = (byte) result[i];
467da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
468da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
469da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(channelId,
470527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                            IccOpenLogicalChannelResponse.STATUS_NO_ERROR, selectResponse);
471566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
472566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        if (ar.result == null) {
473566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                            loge("iccOpenLogicalChannel: Empty response");
474566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
475da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        if (ar.exception != null) {
476da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            loge("iccOpenLogicalChannel: Exception: " + ar.exception);
477da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
478da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
479527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                        int errorCode = IccOpenLogicalChannelResponse.STATUS_UNKNOWN_ERROR;
480a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                        if (ar.exception instanceof CommandException) {
481a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                            CommandException.Error error =
482a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                                ((CommandException) (ar.exception)).getCommandError();
483a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                            if (error == CommandException.Error.MISSING_RESOURCE) {
484527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.STATUS_MISSING_RESOURCE;
485a754ba14f729744f3261113d5e355b86d5c846d3Junda Liu                            } else if (error == CommandException.Error.NO_SUCH_ELEMENT) {
486527e8bf2bd43c5bfdb2ac7ea8cf05413c1faaeb5Shishir Agrawal                                errorCode = IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT;
487da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            }
488da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        }
489da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                        openChannelResp = new IccOpenLogicalChannelResponse(
490da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                            IccOpenLogicalChannelResponse.INVALID_CHANNEL, errorCode, null);
491566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
49282c8a46052629d1450320c116d14c7353bfe4ea1Shishir Agrawal                    request.result = openChannelResp;
493566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
494566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
495566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
496566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
497566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
498566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case CMD_CLOSE_CHANNEL:
499566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
500eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    if (uiccCard == null) {
501eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        loge("iccCloseLogicalChannel: No UICC");
502eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
503eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        synchronized (request) {
504eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                            request.notifyAll();
505eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        }
506eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    } else {
507eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
508eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                        uiccCard.iccCloseLogicalChannel((Integer) request.argument, onCompleted);
509eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal                    }
510566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
511566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
512566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                case EVENT_CLOSE_CHANNEL_DONE:
513e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "iccCloseLogicalChannel");
514e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
515e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
516e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_READ_ITEM:
517e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
518e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_READ_ITEM_DONE, request);
519e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvReadItem((Integer) request.argument, onCompleted);
520e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
521e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
522e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_READ_ITEM_DONE:
523566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    ar = (AsyncResult) msg.obj;
524566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    request = (MainThreadRequest) ar.userObj;
525e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    if (ar.exception == null && ar.result != null) {
526e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = ar.result;     // String
527566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    } else {
528e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        request.result = "";
529e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        if (ar.result == null) {
530e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Empty response");
531e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                        } else if (ar.exception instanceof CommandException) {
532e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: CommandException: " +
533e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                                    ar.exception);
534566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        } else {
535e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                            loge("nvReadItem: Unknown exception");
536566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        }
537566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
538566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    synchronized (request) {
539566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                        request.notifyAll();
540566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    }
541566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    break;
542566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
543e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_ITEM:
544e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
545e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_ITEM_DONE, request);
546e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    Pair<Integer, String> idValue = (Pair<Integer, String>) request.argument;
547e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteItem(idValue.first, idValue.second, onCompleted);
548e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
549e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
550e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_ITEM_DONE:
551e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteItem");
552e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
553e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
554e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_WRITE_CDMA_PRL:
555e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
556e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_WRITE_CDMA_PRL_DONE, request);
557e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvWriteCdmaPrl((byte[]) request.argument, onCompleted);
558e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
559e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
560e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_WRITE_CDMA_PRL_DONE:
561e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvWriteCdmaPrl");
562e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
563e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
564e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case CMD_NV_RESET_CONFIG:
565e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    request = (MainThreadRequest) msg.obj;
566e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    onCompleted = obtainMessage(EVENT_NV_RESET_CONFIG_DONE, request);
567e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    mPhone.nvResetConfig((Integer) request.argument, onCompleted);
568e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
569e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
570e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                case EVENT_NV_RESET_CONFIG_DONE:
571e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    handleNullReturnEvent(msg, "nvResetConfig");
572e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    break;
573e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
5747c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_GET_PREFERRED_NETWORK_TYPE:
5757c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
5767c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_GET_PREFERRED_NETWORK_TYPE_DONE, request);
57754788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    getPhoneFromRequest(request).getPreferredNetworkType(onCompleted);
5787c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
5797c27be317e8757948178815426d3a329c852b9eeJake Hamby
5807c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_GET_PREFERRED_NETWORK_TYPE_DONE:
5817c27be317e8757948178815426d3a329c852b9eeJake Hamby                    ar = (AsyncResult) msg.obj;
5827c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) ar.userObj;
5837c27be317e8757948178815426d3a329c852b9eeJake Hamby                    if (ar.exception == null && ar.result != null) {
5847c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = ar.result;     // Integer
5857c27be317e8757948178815426d3a329c852b9eeJake Hamby                    } else {
5867c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.result = -1;
5877c27be317e8757948178815426d3a329c852b9eeJake Hamby                        if (ar.result == null) {
5887c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Empty response");
5897c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else if (ar.exception instanceof CommandException) {
5907c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: CommandException: " +
5917c27be317e8757948178815426d3a329c852b9eeJake Hamby                                    ar.exception);
5927c27be317e8757948178815426d3a329c852b9eeJake Hamby                        } else {
5937c27be317e8757948178815426d3a329c852b9eeJake Hamby                            loge("getPreferredNetworkType: Unknown exception");
5947c27be317e8757948178815426d3a329c852b9eeJake Hamby                        }
5957c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
5967c27be317e8757948178815426d3a329c852b9eeJake Hamby                    synchronized (request) {
5977c27be317e8757948178815426d3a329c852b9eeJake Hamby                        request.notifyAll();
5987c27be317e8757948178815426d3a329c852b9eeJake Hamby                    }
5997c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6007c27be317e8757948178815426d3a329c852b9eeJake Hamby
6017c27be317e8757948178815426d3a329c852b9eeJake Hamby                case CMD_SET_PREFERRED_NETWORK_TYPE:
6027c27be317e8757948178815426d3a329c852b9eeJake Hamby                    request = (MainThreadRequest) msg.obj;
6037c27be317e8757948178815426d3a329c852b9eeJake Hamby                    onCompleted = obtainMessage(EVENT_SET_PREFERRED_NETWORK_TYPE_DONE, request);
6047c27be317e8757948178815426d3a329c852b9eeJake Hamby                    int networkType = (Integer) request.argument;
60554788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    getPhoneFromRequest(request).setPreferredNetworkType(networkType, onCompleted);
6067c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6077c27be317e8757948178815426d3a329c852b9eeJake Hamby
6087c27be317e8757948178815426d3a329c852b9eeJake Hamby                case EVENT_SET_PREFERRED_NETWORK_TYPE_DONE:
6097c27be317e8757948178815426d3a329c852b9eeJake Hamby                    handleNullReturnEvent(msg, "setPreferredNetworkType");
6107c27be317e8757948178815426d3a329c852b9eeJake Hamby                    break;
6117c27be317e8757948178815426d3a329c852b9eeJake Hamby
6124bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case CMD_INVOKE_OEM_RIL_REQUEST_RAW:
6134bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)msg.obj;
6144bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE, request);
6154bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    mPhone.invokeOemRilRequestRaw((byte[])request.argument, onCompleted);
6164bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
6174bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
6184bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                case EVENT_INVOKE_OEM_RIL_REQUEST_RAW_DONE:
6194bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    ar = (AsyncResult)msg.obj;
6204bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request = (MainThreadRequest)ar.userObj;
6214bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    request.result = ar;
6224bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    synchronized (request) {
6234bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        request.notifyAll();
6244bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
6254bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    break;
6264bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
62776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                case CMD_SET_VOICEMAIL_NUMBER:
62876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    request = (MainThreadRequest) msg.obj;
62976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    onCompleted = obtainMessage(EVENT_SET_VOICEMAIL_NUMBER_DONE, request);
63076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    Pair<String, String> tagNum = (Pair<String, String>) request.argument;
631584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                    getPhoneFromRequest(request).setVoiceMailNumber(tagNum.first, tagNum.second,
632584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott                            onCompleted);
63376d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    break;
63476d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
63576d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                case EVENT_SET_VOICEMAIL_NUMBER_DONE:
63676d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    handleNullReturnEvent(msg, "setVoicemailNumber");
63776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                    break;
63876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
63954788801de04c603a856596f4ae4377ab77a9821Stuart Scott                case CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC:
64054788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    request = (MainThreadRequest) msg.obj;
64154788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    onCompleted = obtainMessage(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE,
64254788801de04c603a856596f4ae4377ab77a9821Stuart Scott                            request);
64354788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    getPhoneFromRequest(request).setNetworkSelectionModeAutomatic(onCompleted);
64454788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    break;
64554788801de04c603a856596f4ae4377ab77a9821Stuart Scott
64654788801de04c603a856596f4ae4377ab77a9821Stuart Scott                case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_DONE:
64754788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    handleNullReturnEvent(msg, "setNetworkSelectionModeAutomatic");
64854788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    break;
64954788801de04c603a856596f4ae4377ab77a9821Stuart Scott
6507fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                case CMD_GET_MODEM_ACTIVITY_INFO:
6517fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    request = (MainThreadRequest) msg.obj;
6527fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    onCompleted = obtainMessage(EVENT_GET_MODEM_ACTIVITY_INFO_DONE, request);
65361a60ad2e6944a80944898e636c2e9d9fd7b0e70Prerepa Viswanadham                    mPhone.getModemActivityInfo(onCompleted);
6547fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    break;
6557fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
6567fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                case EVENT_GET_MODEM_ACTIVITY_INFO_DONE:
6577fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    ar = (AsyncResult) msg.obj;
6587fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    request = (MainThreadRequest) ar.userObj;
6597fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    if (ar.exception == null && ar.result != null) {
6607fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        request.result = ar.result;
6617fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    } else {
6627fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        if (ar.result == null) {
6637fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                            loge("queryModemActivityInfo: Empty response");
6647fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        } else if (ar.exception instanceof CommandException) {
6657fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                            loge("queryModemActivityInfo: CommandException: " +
6667fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                                    ar.exception);
6677fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        } else {
6687fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                            loge("queryModemActivityInfo: Unknown exception");
6697fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        }
6707fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    }
6717fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    synchronized (request) {
6727fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                        request.notifyAll();
6737fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    }
6747fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham                    break;
6757fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
6767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                default:
6777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
6787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    break;
6797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
6807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
681e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
682e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        private void handleNullReturnEvent(Message msg, String command) {
683e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            AsyncResult ar = (AsyncResult) msg.obj;
684e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            MainThreadRequest request = (MainThreadRequest) ar.userObj;
685e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            if (ar.exception == null) {
686e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = true;
687e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            } else {
688e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.result = false;
689e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                if (ar.exception instanceof CommandException) {
690e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": CommandException: " + ar.exception);
691e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                } else {
692e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                    loge(command + ": Unknown exception");
693e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                }
694e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
695e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            synchronized (request) {
696e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                request.notifyAll();
697e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby            }
698e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        }
6997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread,
7037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * waits for the request to complete, and returns the result.
7047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequestAsync
7057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private Object sendRequest(int command, Object argument) {
707500b0e04406d2995c1f29dea95c98cedaa669f74Santos Cordon        return sendRequest(command, argument, null);
70836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
70936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
71036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
71136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Posts the specified command to be executed on the main thread,
71236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * waits for the request to complete, and returns the result.
71336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @see #sendRequestAsync
71436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
71576d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    private Object sendRequest(int command, Object argument, Integer subId) {
7167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
7177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            throw new RuntimeException("This method will deadlock if called from the main thread.");
7187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
72076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        MainThreadRequest request = new MainThreadRequest(argument, subId);
7217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Message msg = mMainThreadHandler.obtainMessage(command, request);
7227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        msg.sendToTarget();
7237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // Wait for the request to complete
7257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (request) {
7267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (request.result == null) {
7277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
7287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    request.wait();
7297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
7307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Do nothing, go back and wait until the request is complete
7317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
7327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
7337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return request.result;
7357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
7387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Asynchronous ("fire and forget") version of sendRequest():
7397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Posts the specified command to be executed on the main thread, and
7407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * returns immediately.
7417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #sendRequest
7427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
7437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void sendRequestAsync(int command) {
7447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler.sendEmptyMessage(command);
7457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
748bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * Same as {@link #sendRequestAsync(int)} except it takes an argument.
749bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     * @see {@link #sendRequest(int,Object)}
750bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal     */
751bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    private void sendRequestAsync(int command, Object argument) {
752bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        MainThreadRequest request = new MainThreadRequest(argument);
753bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        Message msg = mMainThreadHandler.obtainMessage(command, request);
754bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal        msg.sendToTarget();
755bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    }
756bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal
757bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    /**
7587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Initialize the singleton PhoneInterfaceManager instance.
7597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This is only done once, at startup, from PhoneApp.onCreate().
7607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
761194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    /* package */ static PhoneInterfaceManager init(PhoneGlobals app, Phone phone) {
7627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        synchronized (PhoneInterfaceManager.class) {
7637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (sInstance == null) {
764194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal                sInstance = new PhoneInterfaceManager(app, phone);
7657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
7667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
7677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
7687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return sInstance;
7697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
7707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /** Private constructor; @see init() */
773194161ed3aef6bdeeecd6153403269bbd01314a5Sailesh Nepal    private PhoneInterfaceManager(PhoneGlobals app, Phone phone) {
7747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp = app;
7757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone = phone;
7767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mCM = PhoneGlobals.getInstance().mCM;
777981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott        mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
7787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
7797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mMainThreadHandler = new MainThreadHandler();
780df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        mTelephonySharedPreferences =
78197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan                PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
782ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        mSubscriptionController = SubscriptionController.getInstance();
7833ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville
7847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        publish();
7857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void publish() {
7887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("publish: " + this);
7897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
7907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        ServiceManager.addService("phone", this);
7917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
7927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
793584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott    private Phone getPhoneFromRequest(MainThreadRequest request) {
794584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott        return (request.subId == null) ? mPhone : getPhone(request.subId);
795584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott    }
796584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott
79736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // returns phone associated with the subId.
798b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private Phone getPhone(int subId) {
799ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
80036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
8017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
8027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Implementation of the ITelephony interface.
8037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
8047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void dial(String number) {
806add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        dialForSubscriber(getPreferredVoiceSubscription(), number);
80736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
80836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
809b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void dialForSubscriber(int subId, String number) {
8107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("dial: " + number);
8117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: This is just a wrapper around the
8127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // ACTION_DIAL intent, which is available to any app since it puts up
8137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // the UI before it does anything.
8147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
8167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
8177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
8187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // PENDING: should we just silently fail if phone is offhook or ringing?
82136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        PhoneConstants.State state = mCM.getState(subId);
8227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (state != PhoneConstants.State.OFFHOOK && state != PhoneConstants.State.RINGING) {
8237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Intent  intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
8247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mApp.startActivity(intent);
8267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void call(String callingPackage, String number) {
830add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        callForSubscriber(getPreferredVoiceSubscription(), callingPackage, number);
83136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
83236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
833b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void callForSubscriber(int subId, String callingPackage, String number) {
8347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("call: " + number);
8357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // This is just a wrapper around the ACTION_CALL intent, but we still
8377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // need to do a permission check since we're calling startActivity()
8387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // from the context of the phone app.
8397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
8407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage)
8427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                != AppOpsManager.MODE_ALLOWED) {
8437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
8447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        String url = createTelUrl(number);
8477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (url == null) {
8487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
8497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
8507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8510887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        boolean isValid = false;
8521c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final List<SubscriptionInfo> slist = getActiveSubscriptionInfoList();
8533ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville        if (slist != null) {
8543ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville            for (SubscriptionInfo subInfoRecord : slist) {
8553ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                if (subInfoRecord.getSubscriptionId() == subId) {
8563ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                    isValid = true;
8573ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                    break;
8583ab207e3711ebd717f9cfe7412018c51ae1c8131Wink Saville                }
8590887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            }
8600887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        }
8610887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        if (isValid == false) {
8620887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            return;
8630887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        }
8640887461919173015886ea69ef6c6afbe20ebf1dcWink Saville
8657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse(url));
86636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        intent.putExtra(SUBSCRIPTION_KEY, subId);
8677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
8687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.startActivity(intent);
8697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
8727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * End a call based on call state
8737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true is a call was ended
8747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
8757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean endCall() {
876add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return endCallForSubscriber(getDefaultSubscription());
87736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
87836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
87936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
88036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * End a call based on the call state of the subId
88136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true is a call was ended
88236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
883b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean endCallForSubscriber(int subId) {
8847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceCallPermission();
885584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott        return (Boolean) sendRequest(CMD_END_CALL, null, new Integer(subId));
8867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
8877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
8887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void answerRingingCall() {
889add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        answerRingingCallForSubscriber(getDefaultSubscription());
89036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
89136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
892b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void answerRingingCallForSubscriber(int subId) {
8937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG) log("answerRingingCall...");
8947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // TODO: there should eventually be a separate "ANSWER_PHONE" permission,
8957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // but that can probably wait till the big TelephonyManager API overhaul.
8967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For now, protect this call with the MODIFY_PHONE_STATE permission.
8977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
898584921cffac3dc8e7fa3bdeb5a87d764cc0cd77dStuart Scott        sendRequest(CMD_ANSWER_RINGING_CALL, null, new Integer(subId));
8997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
9027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make the actual telephony calls to implement answerRingingCall().
9037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * This should only be called from the main thread of the Phone app.
9047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @see #answerRingingCall
9057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
9067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * TODO: it would be nice to return true if we answered the call, or
9077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * false if there wasn't actually a ringing incoming call, or some
9087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * other error occurred.  (In other words, pass back the return value
9097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * from PhoneUtils.answerCall() or PhoneUtils.answerAndEndActive().)
9107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * But that would require calling this method via sendRequest() rather
9117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * than sendRequestAsync(), and right now we don't actually *need* that
9127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * return value, so let's just return void for now.
9137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
914b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private void answerRingingCallInternal(int subId) {
9150887461919173015886ea69ef6c6afbe20ebf1dcWink Saville        final boolean hasRingingCall = !getPhone(subId).getRingingCall().isIdle();
9167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (hasRingingCall) {
9170887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            final boolean hasActiveCall = !getPhone(subId).getForegroundCall().isIdle();
9180887461919173015886ea69ef6c6afbe20ebf1dcWink Saville            final boolean hasHoldingCall = !getPhone(subId).getBackgroundCall().isIdle();
9197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (hasActiveCall && hasHoldingCall) {
9207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // Both lines are in use!
9217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // TODO: provide a flag to let the caller specify what
9227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // policy to use if both lines are in use.  (The current
9237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // behavior is hardwired to "answer incoming, end ongoing",
9247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // which is how the CALL button is specced to behave.)
9257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerAndEndActive(mCM, mCM.getFirstActiveRingingCall());
9267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
9277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
9287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // answerCall() will automatically hold the current active
9297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // call, if there is one.
9307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                PhoneUtils.answerCall(mCM.getFirstActiveRingingCall());
9317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                return;
9327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
9337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
9347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // No call was ringing.
9357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return;
9367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
9377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
9405422a8deb513e4466ec6cc1e640895a6b536fee0Santos Cordon     * This method is no longer used and can be removed once TelephonyManager stops referring to it.
9417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
9425422a8deb513e4466ec6cc1e640895a6b536fee0Santos Cordon    public void silenceRinger() {
9435422a8deb513e4466ec6cc1e640895a6b536fee0Santos Cordon        Log.e(LOG_TAG, "silenseRinger not supported");
9447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isOffhook() {
947add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return isOffhookForSubscriber(getDefaultSubscription());
94836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
94936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
950b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean isOffhookForSubscriber(int subId) {
95136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.OFFHOOK);
9527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRinging() {
955add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return (isRingingForSubscriber(getDefaultSubscription()));
95636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
95736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
958b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean isRingingForSubscriber(int subId) {
95936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.RINGING);
9607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isIdle() {
963add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return isIdleForSubscriber(getDefaultSubscription());
96436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
96536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
966b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean isIdleForSubscriber(int subId) {
96736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (getPhone(subId).getState() == PhoneConstants.State.IDLE);
9687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
970b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public boolean isSimPinEnabled(String callingPackage) {
971b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "isSimPinEnabled")) {
972b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return false;
973b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
974b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
9757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return (PhoneGlobals.getInstance().isSimPinEnabled());
9767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
9777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
9787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean supplyPin(String pin) {
979add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPinForSubscriber(getDefaultSubscription(), pin);
98036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
98136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
982b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean supplyPinForSubscriber(int subId, String pin) {
983add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        int [] resultArray = supplyPinReportResultForSubscriber(subId, pin);
9849de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
9859de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
9869de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
9879de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public boolean supplyPuk(String puk, String pin) {
988add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPukForSubscriber(getDefaultSubscription(), puk, pin);
98936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
99036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
991b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean supplyPukForSubscriber(int subId, String puk, String pin) {
992add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        int [] resultArray = supplyPukReportResultForSubscriber(subId, puk, pin);
9939de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        return (resultArray[0] == PhoneConstants.PIN_RESULT_SUCCESS) ? true : false;
9949de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    }
9959de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville
9969de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
9979de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPinReportResult(String pin) {
998add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPinReportResultForSubscriber(getDefaultSubscription(), pin);
99936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
100036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1001b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
10027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
100336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPin = new UnlockSim(getPhone(subId).getIccCard());
10047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPin.start();
10057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPin.unlockSim(null, pin);
10067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10089de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    /** {@hide} */
10099de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville    public int[] supplyPukReportResult(String puk, String pin) {
1010add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return supplyPukReportResultForSubscriber(getDefaultSubscription(), puk, pin);
101136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
101236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1013b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
10147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
101536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        final UnlockSim checkSimPuk = new UnlockSim(getPhone(subId).getIccCard());
10167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        checkSimPuk.start();
10177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return checkSimPuk.unlockSim(puk, pin);
10187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
10197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
10219de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville     * Helper thread to turn async call to SimCard#supplyPin into
10227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * a synchronous one.
10237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
10247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private static class UnlockSim extends Thread {
10257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private final IccCard mSimCard;
10277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private boolean mDone = false;
10299de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mResult = PhoneConstants.PIN_GENERAL_FAILURE;
10309de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        private int mRetryCount = -1;
10317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For replies from SimCard interface
10337d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private Handler mHandler;
10347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // For async handler to identify request type
10367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        private static final int SUPPLY_PIN_COMPLETE = 100;
10377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public UnlockSim(IccCard simCard) {
10397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            mSimCard = simCard;
10407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        @Override
10437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        public void run() {
10447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.prepare();
10457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            synchronized (UnlockSim.this) {
10467d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mHandler = new Handler() {
10477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    @Override
10487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    public void handleMessage(Message msg) {
10497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        AsyncResult ar = (AsyncResult) msg.obj;
10507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        switch (msg.what) {
10517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            case SUPPLY_PIN_COMPLETE:
10527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                Log.d(LOG_TAG, "SUPPLY_PIN_COMPLETE");
10537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                synchronized (UnlockSim.this) {
10549de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    mRetryCount = msg.arg1;
10559de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    if (ar.exception != null) {
10569de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        if (ar.exception instanceof CommandException &&
10579de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                ((CommandException)(ar.exception)).getCommandError()
10589de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                                == CommandException.Error.PASSWORD_INCORRECT) {
10599de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
10609de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        } else {
10619de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                            mResult = PhoneConstants.PIN_GENERAL_FAILURE;
10629de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        }
10639de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    } else {
10649de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                        mResult = PhoneConstants.PIN_RESULT_SUCCESS;
10659de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville                                    }
10667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    mDone = true;
10677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                    UnlockSim.this.notifyAll();
10687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                }
10697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                                break;
10707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                        }
10717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    }
10727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                };
10737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                UnlockSim.this.notifyAll();
10747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Looper.loop();
10767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
10777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        /*
10797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * Use PIN or PUK to unlock SIM card
10807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
10817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is null, unlock SIM card with PIN
10827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         *
10837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         * If PUK is not null, unlock SIM card with PUK and set PIN code
10847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon         */
10859de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville        synchronized int[] unlockSim(String puk, String pin) {
10867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (mHandler == null) {
10887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
10897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
10907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
10917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
10927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
10937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
10947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Message callback = Message.obtain(mHandler, SUPPLY_PIN_COMPLETE);
10957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
10967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (puk == null) {
10977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPin(pin, callback);
10987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } else {
10997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                mSimCard.supplyPuk(puk, pin, callback);
11007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
11017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            while (!mDone) {
11037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                try {
11047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Log.d(LOG_TAG, "wait for done");
11057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    wait();
11067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                } catch (InterruptedException e) {
11077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    // Restore the interrupted status
11087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    Thread.currentThread().interrupt();
11097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
11107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
11117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Log.d(LOG_TAG, "done");
11129de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            int[] resultArray = new int[2];
11139de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[0] = mResult;
11149de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            resultArray[1] = mRetryCount;
11159de0f754068c82ed1d1019afb414bc1fcd9298cfWink Saville            return resultArray;
11167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void updateServiceLocation() {
1120add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        updateServiceLocationForSubscriber(getDefaultSubscription());
112136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
112236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
112336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1124b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void updateServiceLocationForSubscriber(int subId) {
11257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // No permission check needed here: this call is harmless, and it's
11267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // needed for the ServiceState.requestStateUpdate() call (which is
11277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        // already intentionally exposed to 3rd parties.)
112836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).updateServiceLocation();
11297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isRadioOn() {
1132add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return isRadioOnForSubscriber(getDefaultSubscription());
113336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
113436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1135b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean isRadioOnForSubscriber(int subId) {
113636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getState() != ServiceState.STATE_POWER_OFF;
11377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
11397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void toggleRadioOnOff() {
1140add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        toggleRadioOnOffForSubscriber(getDefaultSubscription());
114136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
114236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
114336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1144b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void toggleRadioOnOffForSubscriber(int subId) {
11457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1146add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        getPhone(subId).setRadioPower(!isRadioOnForSubscriber(subId));
11477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
114836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
11497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadio(boolean turnOn) {
1150add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return setRadioForSubscriber(getDefaultSubscription(), turnOn);
115136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
115236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1153b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean setRadioForSubscriber(int subId, boolean turnOn) {
11547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
115536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        if ((getPhone(subId).getServiceState().getState() !=
115636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                ServiceState.STATE_POWER_OFF) != turnOn) {
1157add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville            toggleRadioOnOffForSubscriber(subId);
11587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
11597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
116136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
11621fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    public boolean needMobileRadioShutdown() {
11631fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        /*
11641fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         * If any of the Radios are available, it will need to be
11651fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         * shutdown. So return true if any Radio is available.
11661fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla         */
11671fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
11681fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            Phone phone = PhoneFactory.getPhone(i);
11691fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            if (phone != null && phone.isRadioAvailable()) return true;
11701fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
11711fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        logv(TelephonyManager.getDefault().getPhoneCount() + " Phones are shutdown.");
11721fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        return false;
11731fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
11741fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
11751fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    public void shutdownMobileRadios() {
11761fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
11771fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            logv("Shutting down Phone " + i);
11781fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            shutdownRadioUsingPhoneId(i);
11791fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
11801fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
11811fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
11821fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    private void shutdownRadioUsingPhoneId(int phoneId) {
11831fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        enforceModifyPermission();
11841fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        Phone phone = PhoneFactory.getPhone(phoneId);
11851fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        if (phone != null && phone.isRadioAvailable()) {
11861fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla            phone.shutdownRadio();
11871fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        }
11881fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
11891fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
11907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean setRadioPower(boolean turnOn) {
1191add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
119236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
119336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1194b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
11957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
119636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setRadioPower(turnOn);
11977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
11987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
11997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
120036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
12017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean enableDataConnectivity() {
12027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1203ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        int subId = mSubscriptionController.getDefaultDataSubId();
120436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(true);
12057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
12067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
120836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
12097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean disableDataConnectivity() {
12107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
1211ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        int subId = mSubscriptionController.getDefaultDataSubId();
121236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).setDataEnabled(false);
12137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return true;
12147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
121636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    // FIXME: subId version needed
12177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean isDataConnectivityPossible() {
1218ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        int subId = mSubscriptionController.getDefaultDataSubId();
121936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).isDataConnectivityPossible();
12207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean handlePinMmi(String dialString) {
1223add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return handlePinMmiForSubscriber(getDefaultSubscription(), dialString);
122436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
122536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1226b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean handlePinMmiForSubscriber(int subId, String dialString) {
12277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        enforceModifyPermission();
122836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return (Boolean) sendRequest(CMD_HANDLE_PIN_MMI, dialString, subId);
12297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12317d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCallState() {
1232add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getCallStateForSubscriber(getDefaultSubscription());
123336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
123436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1235b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getCallStateForSubscriber(int subId) {
123636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertCallState(getPhone(subId).getState());
12377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataState() {
1240ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
124136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataState(phone.getDataConnectionState());
12427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataActivity() {
1245ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
124636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return DefaultPhoneNotifier.convertDataActivityState(phone.getDataActivityState());
12477d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
125064fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    public Bundle getCellLocation(String callingPackage) {
125164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        enforceFineOrCoarseLocationPermission("getCellLocation");
125264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
125364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        // OP_COARSE_LOCATION controls both fine and coarse location.
125464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
125564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                callingPackage) != AppOpsManager.MODE_ALLOWED) {
12569acc70dcc5bab8df02211ad37a71a1a79c8d54e3Amit Mahajan            log("getCellLocation: returning null; mode != allowed");
125764fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            return null;
12587d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12597d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1260e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
12617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getCellLocation: is active user");
12627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            Bundle data = new Bundle();
12632c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            Phone phone = getPhone(mSubscriptionController.getDefaultDataSubId());
12642c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            phone.getCellLocation().fillInNotifierBundle(data);
12657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return data;
12667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
12679acc70dcc5bab8df02211ad37a71a1a79c8d54e3Amit Mahajan            log("getCellLocation: suppress non-active user");
12687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
12697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
12707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
127264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    private void enforceFineOrCoarseLocationPermission(String message) {
127364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        try {
127464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            mApp.enforceCallingOrSelfPermission(
127564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                    android.Manifest.permission.ACCESS_FINE_LOCATION, null);
127664fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        } catch (SecurityException e) {
127764fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            // If we have ACCESS_FINE_LOCATION permission, skip the check for ACCESS_COARSE_LOCATION
127864fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            // A failure should throw the SecurityException from ACCESS_COARSE_LOCATION since this
127964fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            // is the weaker precondition
128064fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            mApp.enforceCallingOrSelfPermission(
128164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                    android.Manifest.permission.ACCESS_COARSE_LOCATION, message);
128264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        }
128364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    }
128464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
128564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
12867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
12877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void enableLocationUpdates() {
1288add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        enableLocationUpdatesForSubscriber(getDefaultSubscription());
128936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
129036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1291b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void enableLocationUpdatesForSubscriber(int subId) {
12927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
12937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
129436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).enableLocationUpdates();
12957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
12967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
12977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
12987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void disableLocationUpdates() {
1299add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        disableLocationUpdatesForSubscriber(getDefaultSubscription());
130036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
130136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1302b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public void disableLocationUpdatesForSubscriber(int subId) {
13037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(
13047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
130536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        getPhone(subId).disableLocationUpdates();
13067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
13097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @SuppressWarnings("unchecked")
13107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
131164fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        enforceFineOrCoarseLocationPermission("getNeighboringCellInfo");
131264fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
131364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        // OP_COARSE_LOCATION controls both fine and coarse location.
131464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
131564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                callingPackage) != AppOpsManager.MODE_ALLOWED) {
131664fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            return null;
13177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13187d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13197d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (mAppOps.noteOp(AppOpsManager.OP_NEIGHBORING_CELLS, Binder.getCallingUid(),
13207d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                callingPackage) != AppOpsManager.MODE_ALLOWED) {
13217d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
13227d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
132364fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
1324e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
13257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: is active user");
13267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ArrayList<NeighboringCellInfo> cells = null;
13287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
13307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                cells = (ArrayList<NeighboringCellInfo>) sendRequest(
133136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                        CMD_HANDLE_NEIGHBORING_CELL, null, null);
13327d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (RuntimeException e) {
133336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville                Log.e(LOG_TAG, "getNeighboringCellInfo " + e);
13347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
13357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return cells;
13367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
13377d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getNeighboringCellInfo: suppress non-active user");
13387d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
13397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
134464fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav    public List<CellInfo> getAllCellInfo(String callingPackage) {
134564fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        enforceFineOrCoarseLocationPermission("getAllCellInfo");
134664fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav
134764fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        // OP_COARSE_LOCATION controls both fine and coarse location.
134864fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav        if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
134964fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav                callingPackage) != AppOpsManager.MODE_ALLOWED) {
135064fad26f22ed5d382533b3c07271cd1c7b81dd0bSvetoslav            return null;
13517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1353e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (checkIfCallerIsSelfOrForegroundUser()) {
13547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: is active user");
13552c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            List<CellInfo> cellInfos = new ArrayList<CellInfo>();
13562c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            for (Phone phone : PhoneFactory.getPhones()) {
13572c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu                cellInfos.addAll(phone.getAllCellInfo());
13582c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            }
13592c01cdffe4cb2bbc480f7080ef14e21f88833007Legler Wu            return cellInfos;
13607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
13617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("getAllCellInfo: suppress non-active user");
13627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
13637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
13647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1366bd76e4e0407f75c4e6a6961cf943d36fc75a0e1aSailesh Nepal    @Override
13677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public void setCellInfoListRate(int rateInMillis) {
13687d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mPhone.setCellInfoListRate(rateInMillis);
13697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
13707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13717d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
13727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    // Internal helper methods.
13737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    //
13747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1375e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    private static boolean checkIfCallerIsSelfOrForegroundUser() {
13767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean ok;
13777d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        boolean self = Binder.getCallingUid() == Process.myUid();
13797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (!self) {
13807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // Get the caller's user id then clear the calling identity
13817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            // which will be restored in the finally clause.
13827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            int callingUser = UserHandle.getCallingUserId();
13837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            long ident = Binder.clearCallingIdentity();
13847d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
13857d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            try {
13867d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                // With calling identity cleared the current user is the foreground user.
13877d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                int foregroundUser = ActivityManager.getCurrentUser();
13887d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = (foregroundUser == callingUser);
13897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) {
13907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                    log("checkIfCallerIsSelfOrForegoundUser: foregroundUser=" + foregroundUser
13917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                            + " callingUser=" + callingUser + " ok=" + ok);
13927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                }
13937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } catch (Exception ex) {
13947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                if (DBG_LOC) loge("checkIfCallerIsSelfOrForegoundUser: Exception ex=" + ex);
13957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                ok = false;
13967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            } finally {
13977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon                Binder.restoreCallingIdentity(ident);
13987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            }
13997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        } else {
14007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: is self");
14017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            ok = true;
14027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
14037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (DBG_LOC) log("checkIfCallerIsSelfOrForegoundUser: ret=" + ok);
14047d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return ok;
14057d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14067d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14077d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
14087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the MODIFY_PHONE_STATE permission.
14097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
14107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
14117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceModifyPermission() {
14137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
14147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1417a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure either system app or the caller has carrier privilege.
1418a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1419a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission/privilege
1420a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1421a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceModifyPermissionOrCarrierPrivilege() {
1422f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        int permission = mApp.checkCallingOrSelfPermission(
1423f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                android.Manifest.permission.MODIFY_PHONE_STATE);
1424f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        if (permission == PackageManager.PERMISSION_GRANTED) {
1425f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            return;
1426f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        }
1427f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal
1428f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal        log("No modify permission, check carrier privilege next.");
14295e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        if (getCarrierPrivilegeStatus() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1430f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1431f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No modify permission or carrier privilege.");
1432a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1433a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1434a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1435a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
1436a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * Make sure the caller has carrier privilege.
1437a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     *
1438a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     * @throws SecurityException if the caller does not have the required permission
1439a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu     */
1440a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    private void enforceCarrierPrivilege() {
14415e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        if (getCarrierPrivilegeStatus() != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
1442f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            loge("No Carrier Privilege.");
1443f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal            throw new SecurityException("No Carrier Privilege.");
1444a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        }
1445a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    }
1446a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu
1447a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu    /**
14487d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Make sure the caller has the CALL_PHONE permission.
14497d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
14507d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @throws SecurityException if the caller does not have the required permission
14517d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
14527d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private void enforceCallPermission() {
14537d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.CALL_PHONE, null);
14547d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14557d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1456566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    /**
145736ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * Make sure the caller has the READ_PRIVILEGED_PHONE_STATE permission.
145836ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     *
145936ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     * @throws SecurityException if the caller does not have the required permission
146036ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal     */
146136ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    private void enforcePrivilegedPhoneStatePermission() {
146236ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal        mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
146336ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal                null);
146436ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal    }
146536ebb0d4d04346a367b7a54b178ab4f78696e95cGabriel Peal
14668eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    private void enforceConnectivityInternalPermission() {
14678eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott        mApp.enforceCallingOrSelfPermission(
14688eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott                android.Manifest.permission.CONNECTIVITY_INTERNAL,
14698eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott                "ConnectivityService");
14708eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    }
14718eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott
14727d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    private String createTelUrl(String number) {
14737d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        if (TextUtils.isEmpty(number)) {
14747d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon            return null;
14757d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        }
14767d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1477e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return "tel:" + number;
14787d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
1480f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void log(String msg) {
14817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
14827d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14837d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14841fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    private static void logv(String msg) {
14851fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla        Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
14861fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla    }
14871fd79bd442bda04a7e5e467c9ae6ab22e2a83f05Naveen Kalla
1488f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    private static void loge(String msg) {
14897d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
14907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
14927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getActivePhoneType() {
1493add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getActivePhoneTypeForSubscriber(getDefaultSubscription());
149436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
149536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1496b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getActivePhoneTypeForSubscriber(int subId) {
149736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getPhoneType();
14987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
14997d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15007d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15017d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon index to display
15027d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15037d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconIndex() {
1504add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getCdmaEriIconIndexForSubscriber(getDefaultSubscription());
150536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
150636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
150736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1508b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getCdmaEriIconIndexForSubscriber(int subId) {
150936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconIndex();
15107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI icon mode,
15147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 0 - ON
15157d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * 1 - FLASHING
15167d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15177d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getCdmaEriIconMode() {
1518add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getCdmaEriIconModeForSubscriber(getDefaultSubscription());
151936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
152036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1521b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getCdmaEriIconModeForSubscriber(int subId) {
152236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriIconMode();
15237d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the CDMA ERI text,
15277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public String getCdmaEriText() {
1529add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getCdmaEriTextForSubscriber(getDefaultSubscription());
153036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
153136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1532b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public String getCdmaEriTextForSubscriber(int subId) {
153336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getCdmaEriText();
15347d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15357d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15367d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
1537ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     * Returns the CDMA MDN.
1538ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     */
1539b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public String getCdmaMdn(int subId) {
1540ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1541ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1542ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return getPhone(subId).getLine1Number();
1543ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        } else {
1544ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return null;
1545ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        }
1546ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    }
1547ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu
1548ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    /**
1549ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     * Returns the CDMA MIN.
1550ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu     */
1551b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public String getCdmaMin(int subId) {
1552ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1553ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
1554ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return getPhone(subId).getCdmaMin();
1555ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        } else {
1556ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu            return null;
1557ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu        }
1558ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    }
1559ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu
1560ca05d5dad142516de2cc78dead550472a9cc5ee0Junda Liu    /**
15617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns true if CDMA provisioning needs to run.
15627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean needsOtaServiceProvisioning() {
15647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon        return mPhone.needsOtaServiceProvisioning();
15657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
156876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal     * Sets the voice mail number of a given subId.
156976d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal     */
157076d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    @Override
157176d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
15725e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        enforceCarrierPrivilege();
157376d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
157476d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal                new Pair<String, String>(alphaTag, number), new Integer(subId));
157576d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal        return success;
157676d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    }
157776d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal
157876d5da9d705eba24aea9e5ef8d9ff2071b7819e2Shishir Agrawal    /**
15797d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the unread count of voicemails
15807d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15817d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceMessageCount() {
1582add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getVoiceMessageCountForSubscriber(getDefaultSubscription());
158336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
158436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
158536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
158636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the unread count of voicemails for a subId
158736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
1588b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getVoiceMessageCountForSubscriber( int subId) {
158936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getVoiceMessageCount();
15907d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
15917d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
15927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
15937d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
15947d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
15957d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @Deprecated to be removed Q3 2013 use {@link #getDataNetworkType}.
15967d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
15977d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
15987d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getNetworkType() {
1599add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getNetworkTypeForSubscriber(getDefaultSubscription());
160036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
160136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
160236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
160336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the network type for a subId
160436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
160536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
1606b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getNetworkTypeForSubscriber(int subId) {
160736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
16087d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16097d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16107d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
16117d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
16127d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
16137d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
16147d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getDataNetworkType() {
1615add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getDataNetworkTypeForSubscriber(getDefaultSubscription());
161636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
161736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
161836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
161936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the data network type for a subId
162036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
162136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
1622b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getDataNetworkTypeForSubscriber(int subId) {
162336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getDataNetworkType();
16247d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16257d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16267d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
16277d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Returns the data network type
16287d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
16297d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    @Override
16307d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getVoiceNetworkType() {
1631add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getVoiceNetworkTypeForSubscriber(getDefaultSubscription());
163236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
163336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
163436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
163536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns the Voice network type for a subId
163636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
163736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    @Override
1638b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getVoiceNetworkTypeForSubscriber(int subId) {
163936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getServiceState().getVoiceNetworkType();
16407d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16417d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16427d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
16437d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return true if a ICC card is present
16447d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
16457d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public boolean hasIccCard() {
164636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        // FIXME Make changes to pass defaultSimId of type int
1647a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        return hasIccCardUsingSlotId(mSubscriptionController.getSlotId(getDefaultSubscription()));
164836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
164936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
165036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
165136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * @return true if a ICC card is present for a slotId
165236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
1653b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public boolean hasIccCardUsingSlotId(int slotId) {
1654a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        int subId[] = mSubscriptionController.getSubIdUsingSlotId(slotId);
1655a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        if (subId != null) {
1656a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan            return getPhone(subId[0]).getIccCard().hasIccCard();
1657a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        } else {
1658a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan            return false;
1659a6fc2a8518c71b7a720f849bbfd4c51fe35a461dAmit Mahajan        }
16607d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
16617d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon
16627d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    /**
16637d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * Return if the current radio is LTE on CDMA. This
16647d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * is a tri-state return value as for a period of time
16657d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * the mode may be unknown.
16667d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     *
16677d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     * @return {@link Phone#LTE_ON_CDMA_UNKNOWN}, {@link Phone#LTE_ON_CDMA_FALSE}
1668e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * or {@link Phone#LTE_ON_CDMA_TRUE}
16697d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon     */
16707d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    public int getLteOnCdmaMode() {
1671add7cc5326c1daf6b51a608e143eccef893bbedbWink Saville        return getLteOnCdmaModeForSubscriber(getDefaultSubscription());
167236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
167336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1674b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    public int getLteOnCdmaModeForSubscriber(int subId) {
167536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return getPhone(subId).getLteOnCdmaMode();
167636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
167736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
167836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setPhone(Phone phone) {
167936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone = phone;
168036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
168136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
168236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
168336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
168436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default subId, 0 in the case of single standby.
168536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
1686b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private int getDefaultSubscription() {
1687ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        return mSubscriptionController.getDefaultSubId();
168836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
168936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1690b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private int getPreferredVoiceSubscription() {
1691ac1bdfd36366426513d51bd2c4b107b00533889eWink Saville        return mSubscriptionController.getDefaultVoiceSubId();
16927d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon    }
1693f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1694f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1695f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1696f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1697f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public int getWhenToMakeWifiCalls() {
1698d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        return Settings.System.getInt(mPhone.getContext().getContentResolver(),
1699d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, getWhenToMakeWifiCallsDefaultPreference());
1700f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
1701f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad
1702f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    /**
1703f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     * @see android.telephony.TelephonyManager.WifiCallingChoices
1704f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad     */
1705f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    public void setWhenToMakeWifiCalls(int preference) {
1706d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        if (DBG) log("setWhenToMakeWifiCallsStr, storing setting = " + preference);
1707d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal        Settings.System.putInt(mPhone.getContext().getContentResolver(),
1708d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal                Settings.System.WHEN_TO_MAKE_WIFI_CALLS, preference);
1709f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad    }
1710f9e92733e130dc37ce2c592b36deab86008f5706Ihab Awad
1711d1e681513fb108d5902a1c76eedca7b83034c056Sailesh Nepal    private static int getWhenToMakeWifiCallsDefaultPreference() {
1712da120f4e3d32ca97c5b4c21d6c505d834a29ab8dSantos Cordon        // TODO: Use a build property to choose this value.
17139829e880f73f76119ba76ba032db42aad042858fEvan Charlton        return TelephonyManager.WifiCallingChoices.ALWAYS_USE;
1714f2177b7ec0fd9efcb8299e8272a494e869dcf16fIhab Awad    }
171569f68120b94cecb2d87fe856bc115714b4e77bcdShishir Agrawal
1716566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1717da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID) {
1718a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1719566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1720566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + AID);
1721da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccOpenLogicalChannelResponse response = (IccOpenLogicalChannelResponse)sendRequest(
1722da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            CMD_OPEN_CHANNEL, AID);
1723da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccOpenLogicalChannel: " + response);
1724da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return response;
1725566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1726566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1727566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1728566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public boolean iccCloseLogicalChannel(int channel) {
1729a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1730566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1731566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + channel);
1732566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1733566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal          return false;
1734566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1735e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean)sendRequest(CMD_CLOSE_CHANNEL, channel);
1736566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccCloseLogicalChannel: " + success);
1737566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return success;
1738566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1739566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1740566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    @Override
1741566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    public String iccTransmitApduLogicalChannel(int channel, int cla,
1742566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            int command, int p1, int p2, int p3, String data) {
1743a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1744566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1745566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) {
1746566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            log("iccTransmitApduLogicalChannel: chnl=" + channel + " cla=" + cla +
1747566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 +
1748566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                    " data=" + data);
1749566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1750566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1751566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (channel < 0) {
1752566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal            return "";
1753566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        }
1754566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1755da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_LOGICAL_CHANNEL,
1756566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                new IccAPDUArgument(channel, cla, command, p1, p2, p3, data));
1757566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        if (DBG) log("iccTransmitApduLogicalChannel: " + response);
1758566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal
1759566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        // Append the returned status code to the end of the response payload.
1760566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        String s = Integer.toHexString(
1761566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
17625ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        if (response.payload != null) {
17635ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal            s = IccUtils.bytesToHexString(response.payload) + s;
17645ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        }
1765566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal        return s;
1766566b761b610e7e5e1ade9ab0906a2a7e816dad63Shishir Agrawal    }
1767e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1768c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    @Override
1769da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public String iccTransmitApduBasicChannel(int cla, int command, int p1, int p2,
1770da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                int p3, String data) {
1771da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1772da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1773da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1774da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("iccTransmitApduBasicChannel: cla=" + cla + " cmd=" + command + " p1="
1775da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                    + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
1776da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1777da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1778da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response = (IccIoResult)sendRequest(CMD_TRANSMIT_APDU_BASIC_CHANNEL,
1779da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                new IccAPDUArgument(0, cla, command, p1, p2, p3, data));
1780da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) log("iccTransmitApduBasicChannel: " + response);
1781da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1782da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        // Append the returned status code to the end of the response payload.
1783da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        String s = Integer.toHexString(
1784da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
17855ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        if (response.payload != null) {
17865ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal            s = IccUtils.bytesToHexString(response.payload) + s;
17875ec14172e42d180d7dd6110ef8eb1dedb0a0a7fbShishir Agrawal        }
1788da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return s;
1789da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
1790da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1791da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
1792da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1793da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            String filePath) {
1794da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        enforceModifyPermissionOrCarrierPrivilege();
1795da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1796da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1797da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            log("Exchange SIM_IO " + fileID + ":" + command + " " +
1798da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal                p1 + " " + p2 + " " + p3 + ":" + filePath);
1799da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1800da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1801da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        IccIoResult response =
1802da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            (IccIoResult)sendRequest(CMD_EXCHANGE_SIM_IO,
18033edf3789a6e8b6b9ac28b7dfb24d6d7b00b3b554Yong Jiang                    new IccAPDUArgument(-1, fileID, command, p1, p2, p3, filePath));
1804da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1805da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (DBG) {
1806da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal          log("Exchange SIM_IO [R]" + response);
1807da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1808da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1809da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        byte[] result = null;
1810da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        int length = 2;
1811da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        if (response.payload != null) {
1812da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            length = 2 + response.payload.length;
1813da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
1814da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            System.arraycopy(response.payload, 0, result, 0, response.payload.length);
1815da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        } else {
1816da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal            result = new byte[length];
1817da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        }
1818da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1819da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 1] = (byte) response.sw2;
1820da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        result[length - 2] = (byte) response.sw1;
1821da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal        return result;
1822da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    }
1823da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal
1824da0bb0d7aff7b4a445370dc0709e94b874031178Shishir Agrawal    @Override
1825c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    public String sendEnvelopeWithStatus(String content) {
1826a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1827c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1828c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content);
1829c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        if (response.payload == null) {
1830c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton          return "";
1831c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        }
1832c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1833c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        // Append the returned status code to the end of the response payload.
1834c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        String s = Integer.toHexString(
1835c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton                (response.sw1 << 8) + response.sw2 + 0x10000).substring(1);
1836c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        s = IccUtils.bytesToHexString(response.payload) + s;
1837c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton        return s;
1838c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton    }
1839c66da36833b835a9a122f6b0a3e4ecef27be266bEvan Charlton
1840e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1841e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Read one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1842e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1843e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1844e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1845e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return the NV item as a String, or null on error.
1846e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1847e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1848e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public String nvReadItem(int itemID) {
1849a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1850e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID);
1851e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
1852e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
1853e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return value;
1854e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1855e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1856e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1857e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Write one of the NV items defined in {@link com.android.internal.telephony.RadioNVItems}
1858e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * and {@code ril_nv_items.h}. Used for device configuration by some CDMA operators.
1859e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1860e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemID the ID of the item to read
1861e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param itemValue the value to write, as a String
1862e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1863e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1864e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1865e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteItem(int itemID, String itemValue) {
1866a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1867e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
1868e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
1869e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby                new Pair<Integer, String>(itemID, itemValue));
1870e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteItem: item " + itemID + ' ' + (success ? "ok" : "fail"));
1871e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1872e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1873e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1874e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1875e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
1876e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1877e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1878e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param preferredRoamingList byte array containing the new PRL
1879e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1880e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1881e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1882e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
1883a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1884e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
1885e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
1886e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
1887e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1888e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
1889e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby
1890e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    /**
1891e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Perform the specified type of NV config reset.
1892e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * Used for device configuration by some CDMA operators.
1893e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     *
1894e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @param resetType the type of reset to perform (1 == factory reset; 2 == NV-only reset)
1895e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     * @return true on success; false on any failure
1896e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby     */
1897e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    @Override
1898e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    public boolean nvResetConfig(int resetType) {
1899a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
1900e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType);
1901e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
1902e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
1903e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby        return success;
1904e994d46a1f951b496441a42d1eabd2a0e026ceaeJake Hamby    }
19057c27be317e8757948178815426d3a329c852b9eeJake Hamby
19067c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
190736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * {@hide}
190836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     * Returns Default sim, 0 in the case of single standby.
190936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville     */
191036469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public int getDefaultSim() {
191136469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        //TODO Need to get it from Telephony Devcontroller
191236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        return 0;
191336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
191436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
1915b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String[] getPcscfAddress(String apnType, String callingPackage) {
1916b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
1917b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return new String[0];
1918b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
1919b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
1920b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
192187fca6f34c10e43e4dcfdd3f4e35bd4050e19582ram        return mPhone.getPcscfAddress(apnType);
192236469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
192336469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
192436469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    public void setImsRegistrationState(boolean registered) {
192536469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        enforceModifyPermission();
192636469e74b7c79ed84148754190c38196eb9a2c49Wink Saville        mPhone.setImsRegistrationState(registered);
192736469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    }
192836469e74b7c79ed84148754190c38196eb9a2c49Wink Saville
192936469e74b7c79ed84148754190c38196eb9a2c49Wink Saville    /**
193054788801de04c603a856596f4ae4377ab77a9821Stuart Scott     * Set the network selection mode to automatic.
193154788801de04c603a856596f4ae4377ab77a9821Stuart Scott     *
193254788801de04c603a856596f4ae4377ab77a9821Stuart Scott     */
193354788801de04c603a856596f4ae4377ab77a9821Stuart Scott    @Override
193454788801de04c603a856596f4ae4377ab77a9821Stuart Scott    public void setNetworkSelectionModeAutomatic(int subId) {
193554788801de04c603a856596f4ae4377ab77a9821Stuart Scott        enforceModifyPermissionOrCarrierPrivilege();
193654788801de04c603a856596f4ae4377ab77a9821Stuart Scott        if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
193754788801de04c603a856596f4ae4377ab77a9821Stuart Scott        sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
193854788801de04c603a856596f4ae4377ab77a9821Stuart Scott    }
193954788801de04c603a856596f4ae4377ab77a9821Stuart Scott
194054788801de04c603a856596f4ae4377ab77a9821Stuart Scott    /**
194184d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Get the calculated preferred network type.
194284d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * Used for debugging incorrect network type.
194384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     *
194484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     * @return the preferred network type, defined in RILConstants.java.
194584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu     */
194684d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    @Override
1947b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public int getCalculatedPreferredNetworkType(String callingPackage) {
1948b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
1949b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return RILConstants.PREFERRED_NETWORK_MODE;
1950b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
1951b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
195243330e02af9431ac18a9b9d6c09610f910b8c0f2Amit Mahajan        return PhoneFactory.calculatePreferredNetworkType(mPhone.getContext(), 0); // wink FIXME: need to get SubId from somewhere.
195384d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    }
195484d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu
195584d15a2e84fa528f111abf05d17fc2280b182b7cJunda Liu    /**
19567c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Get the preferred network type.
19577c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
19587c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
19597c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return the preferred network type, defined in RILConstants.java.
19607c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
19617c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
196254788801de04c603a856596f4ae4377ab77a9821Stuart Scott    public int getPreferredNetworkType(int subId) {
1963a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
19647c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType");
196554788801de04c603a856596f4ae4377ab77a9821Stuart Scott        int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
19667c27be317e8757948178815426d3a329c852b9eeJake Hamby        int networkType = (result != null ? result[0] : -1);
19677c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("getPreferredNetworkType: " + networkType);
19687c27be317e8757948178815426d3a329c852b9eeJake Hamby        return networkType;
19697c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
19707c27be317e8757948178815426d3a329c852b9eeJake Hamby
19717c27be317e8757948178815426d3a329c852b9eeJake Hamby    /**
19727c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Set the preferred network type.
19737c27be317e8757948178815426d3a329c852b9eeJake Hamby     * Used for device configuration by some CDMA operators.
19747c27be317e8757948178815426d3a329c852b9eeJake Hamby     *
19757c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @param networkType the preferred network type, defined in RILConstants.java.
19767c27be317e8757948178815426d3a329c852b9eeJake Hamby     * @return true on success; false on any failure.
19777c27be317e8757948178815426d3a329c852b9eeJake Hamby     */
19787c27be317e8757948178815426d3a329c852b9eeJake Hamby    @Override
197954788801de04c603a856596f4ae4377ab77a9821Stuart Scott    public boolean setPreferredNetworkType(int subId, int networkType) {
1980a2e3601f8c198e7880ff407e1cea9ef2b8ce8505Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
198154788801de04c603a856596f4ae4377ab77a9821Stuart Scott        if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
198254788801de04c603a856596f4ae4377ab77a9821Stuart Scott        Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
19837c27be317e8757948178815426d3a329c852b9eeJake Hamby        if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
198480bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        if (success) {
198580bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu            Settings.Global.putInt(mPhone.getContext().getContentResolver(),
198654788801de04c603a856596f4ae4377ab77a9821Stuart Scott                    Settings.Global.PREFERRED_NETWORK_MODE + subId, networkType);
198780bc0d1614b46c89fa7a2c1d68fdb3ccb018625dJunda Liu        }
19887c27be317e8757948178815426d3a329c852b9eeJake Hamby        return success;
19897c27be317e8757948178815426d3a329c852b9eeJake Hamby    }
1990ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
1991ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
1992475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning
1993475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * SystemProperty, and config_tether_apndata to decide whether DUN APN is required for
1994475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * tethering.
1995475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     *
1996475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * @return 0: Not required. 1: required. 2: Not set.
1997475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     * @hide
1998475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu     */
1999475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    @Override
2000475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    public int getTetherApnRequired() {
2001475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        enforceModifyPermissionOrCarrierPrivilege();
2002475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        int dunRequired = Settings.Global.getInt(mPhone.getContext().getContentResolver(),
2003475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu                Settings.Global.TETHER_DUN_REQUIRED, 2);
2004475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        // If not set, check net.tethering.noprovisioning, TETHER_DUN_APN setting and
2005475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        // config_tether_apndata.
2006475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        if (dunRequired == 2 && mPhone.hasMatchedTetherApnSetting()) {
2007475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu            dunRequired = 1;
2008475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        }
2009475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu        return dunRequired;
2010475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    }
2011475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu
2012475951f7b5c5831cbe015869c69b6916d4ab7053Junda Liu    /**
2013ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Set mobile data enabled
2014ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * Used by the user through settings etc to turn on/off mobile data
2015ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
2016ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @param enable {@code true} turn turn data on, else {@code false}
2017ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
2018ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
2019e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville    public void setDataEnabled(int subId, boolean enable) {
2020ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt        enforceModifyPermission();
2021e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        int phoneId = mSubscriptionController.getPhoneId(subId);
2022e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2023e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        Phone phone = PhoneFactory.getPhone(phoneId);
2024e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        if (phone != null) {
2025e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            log("setDataEnabled: subId=" + subId + " enable=" + enable);
2026e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            phone.setDataEnabled(enable);
2027e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        } else {
2028e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            loge("setDataEnabled: no phone for subId=" + subId);
2029e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        }
2030ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
2031ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt
2032ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    /**
2033646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Get whether mobile data is enabled.
2034646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     *
2035646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * Note that this used to be available from ConnectivityService, gated by
2036646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * ACCESS_NETWORK_STATE permission, so this will accept either that or
2037646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt     * our MODIFY_PHONE_STATE.
2038ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     *
2039ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     * @return {@code true} if data is enabled else {@code false}
2040ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt     */
2041ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    @Override
2042e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville    public boolean getDataEnabled(int subId) {
2043646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        try {
2044646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
2045646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
2046646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        } catch (Exception e) {
2047646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
2048646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt                    null);
2049646120a5b2c016a4528dab5372db94e027233fb3Robert Greenwalt        }
2050e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        int phoneId = mSubscriptionController.getPhoneId(subId);
2051e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        log("getDataEnabled: subId=" + subId + " phoneId=" + phoneId);
2052e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        Phone phone = PhoneFactory.getPhone(phoneId);
2053e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        if (phone != null) {
2054e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            boolean retVal = phone.getDataEnabled();
2055e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            log("getDataEnabled: subId=" + subId + " retVal=" + retVal);
2056e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            return retVal;
2057e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        } else {
2058e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            loge("getDataEnabled: no phone subId=" + subId + " retVal=false");
2059e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville            return false;
2060e7353bb9c6321b0858f9d981835b1bbc52b3e517Wink Saville        }
2061ed86e5837b426bcba625b57e466b8d04ddbd8008Robert Greenwalt    }
206260f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal
206360f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    @Override
20645e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal    public int getCarrierPrivilegeStatus() {
206521409250c4001605606a37c3903dc22805410900Shishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
2066eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
20675e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal            loge("getCarrierPrivilegeStatus: No UICC");
2068eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2069eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
2070eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        return card.getCarrierPrivilegeStatusForCurrentTransaction(
2071f1ac4c93f1b87b7db0836882ed72935a86ed3898Shishir Agrawal                mPhone.getContext().getPackageManager());
207260f9c952a11be2a34460b4cc8e0f9b31e38f5f30Shishir Agrawal    }
20732934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu
20742934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    @Override
207550ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    public int checkCarrierPrivilegesForPackage(String pkgName) {
207621409250c4001605606a37c3903dc22805410900Shishir Agrawal        UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId());
2077eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        if (card == null) {
2078eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            loge("checkCarrierPrivilegesForPackage: No UICC");
2079eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2080eb8771e9b44fcc885c17d3ff4a3358fcd0b21c6eShishir Agrawal        }
208150ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        return card.getCarrierPrivilegeStatus(mPhone.getContext().getPackageManager(), pkgName);
208250ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    }
208350ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson
208450ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    @Override
208550ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson    public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
208650ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        int result = TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
208750ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
208850ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            UiccCard card = UiccController.getInstance().getUiccCard(i);
208950ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            if (card == null) {
209050ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson              loge("checkCarrierPrivilegesForPackageAnyPhones: No UICC");
209150ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson              continue;
209250ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            }
209350ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson
209450ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            result = card.getCarrierPrivilegeStatus(
209550ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson                mPhone.getContext().getPackageManager(), pkgName);
209650ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            if (result == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
209750ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson                break;
209850ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson            }
209950ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        }
210050ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson
210150ecba360335a12252c30c95c309ef3ff5560fbfZach Johnson        return result;
21022934034e04c5ca7839de41d0cc8f8bab89b1e336Junda Liu    }
210389e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan
210489e89d47f249a1e910d6d726dbfcbedfc193cb83Derek Tan    @Override
2105e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu    public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
2106e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu        if (!SubscriptionManager.isValidPhoneId(phoneId)) {
2107e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu            loge("phoneId " + phoneId + " is not valid.");
2108e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu            return null;
2109e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu        }
2110e64de7820475d67ef0882a1b37f3bd188ca68e25Junda Liu        UiccCard card = UiccController.getInstance().getUiccCard(phoneId);
2111eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        if (card == null) {
2112af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero            loge("getCarrierPackageNamesForIntent: No UICC");
2113eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal            return null ;
2114eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal        }
2115af74c86463b193100a48a0a2b83d0096863bf110Diego Pontoriero        return card.getCarrierPackageNamesForIntent(
2116483aff78d6bada4c2f4d28f804935d24c8173fceSvetoslav                mPhone.getContext().getPackageManager(), intent);
2117eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    }
2118eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal
2119b564aaeff3b6c4b20c899b8c254e4622b691d0cfWink Saville    private String getIccId(int subId) {
212097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        UiccCard card = getPhone(subId).getUiccCard();
212197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (card == null) {
212297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            loge("getIccId: No UICC");
212397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return null;
212497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
212597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = card.getIccId();
212697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (TextUtils.isEmpty(iccId)) {
212797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            loge("getIccId: ICC ID is null or empty.");
212897ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            return null;
212997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
213097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return iccId;
213197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan    }
213297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
2133eb6439a7bd453313f7ed7972d30e2478243801ffShishir Agrawal    @Override
213485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
213585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            String number) {
21365e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        enforceCarrierPrivilege();
213797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
213885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String iccId = getIccId(subId);
213985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String subscriberId = getPhone(subId).getSubscriberId();
214085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
214185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        if (DBG_MERGE) {
214285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            Slog.d(LOG_TAG, "Setting line number for ICC=" + iccId + ", subscriberId="
214385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    + subscriberId + " to " + number);
214485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
214585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
2146495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        if (TextUtils.isEmpty(iccId)) {
2147495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            return false;
2148495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        }
214997ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
215085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
215185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
215285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2153495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        if (alphaTag == null) {
2154495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.remove(alphaTagPrefKey);
2155495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        } else {
2156495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.putString(alphaTagPrefKey, alphaTag);
215797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        }
2158495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal
215985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Record both the line number and IMSI for this ICCID, since we need to
216085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // track all merged IMSIs based on line number
216185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
216285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String subscriberPrefKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
2163495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        if (number == null) {
2164495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.remove(numberPrefKey);
216585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            editor.remove(subscriberPrefKey);
2166495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        } else {
2167495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal            editor.putString(numberPrefKey, number);
216885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            editor.putString(subscriberPrefKey, subscriberId);
2169495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        }
217085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
2171495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        editor.commit();
2172495d7e1f6af536095cf90d7299b64e47c8323dfcShishir Agrawal        return true;
21737226c84acb402f96e527650347391fa025294350Derek Tan    }
21747226c84acb402f96e527650347391fa025294350Derek Tan
21757226c84acb402f96e527650347391fa025294350Derek Tan    @Override
2176b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String getLine1NumberForDisplay(int subId, String callingPackage) {
2177b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getLine1NumberForDisplay")) {
2178b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return null;
2179b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
218097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
218197ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
218297ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
218397ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String numberPrefKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
2184df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee            return mTelephonySharedPreferences.getString(numberPrefKey, null);
21857226c84acb402f96e527650347391fa025294350Derek Tan        }
218697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return null;
21877226c84acb402f96e527650347391fa025294350Derek Tan    }
21887226c84acb402f96e527650347391fa025294350Derek Tan
21897226c84acb402f96e527650347391fa025294350Derek Tan    @Override
2190b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
2191b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
2192b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return null;
2193b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
219497ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan
219597ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        String iccId = getIccId(subId);
219697ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        if (iccId != null) {
219797ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan            String alphaTagPrefKey = PREF_CARRIERS_ALPHATAG_PREFIX + iccId;
2198df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee            return mTelephonySharedPreferences.getString(alphaTagPrefKey, null);
21997226c84acb402f96e527650347391fa025294350Derek Tan        }
220097ebb427fc22f1f14eab7c79745dfcbf2eb2ff7aDerek Tan        return null;
22017226c84acb402f96e527650347391fa025294350Derek Tan    }
2202b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal
2203b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    @Override
220485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    public String[] getMergedSubscriberIds() {
220585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final Context context = mPhone.getContext();
220685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(context);
220785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final SubscriptionManager sub = SubscriptionManager.from(context);
220885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
220985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Figure out what subscribers are currently active
221085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final ArraySet<String> activeSubscriberIds = new ArraySet<>();
221185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final int[] subIds = sub.getActiveSubscriptionIdList();
221285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        for (int subId : subIds) {
221385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            activeSubscriberIds.add(tele.getSubscriberId(subId));
221485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
221585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
221685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // First pass, find a number override for an active subscriber
221785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        String mergeNumber = null;
221885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final Map<String, ?> prefs = mTelephonySharedPreferences.getAll();
221985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        for (String key : prefs.keySet()) {
222085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            if (key.startsWith(PREF_CARRIERS_SUBSCRIBER_PREFIX)) {
222185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                final String subscriberId = (String) prefs.get(key);
222285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                if (activeSubscriberIds.contains(subscriberId)) {
222385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String iccId = key.substring(PREF_CARRIERS_SUBSCRIBER_PREFIX.length());
222485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String numberKey = PREF_CARRIERS_NUMBER_PREFIX + iccId;
222585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    mergeNumber = (String) prefs.get(numberKey);
222685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    if (DBG_MERGE) {
222785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                        Slog.d(LOG_TAG, "Found line number " + mergeNumber
222885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                                + " for active subscriber " + subscriberId);
222985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    }
223085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    if (!TextUtils.isEmpty(mergeNumber)) {
223185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                        break;
223285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    }
223385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                }
223485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            }
223585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
223685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
223785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Shortcut when no active merged subscribers
223885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        if (TextUtils.isEmpty(mergeNumber)) {
223985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            return null;
224085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
224185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
224285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        // Second pass, find all subscribers under that line override
224385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final ArraySet<String> result = new ArraySet<>();
224485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        for (String key : prefs.keySet()) {
224585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            if (key.startsWith(PREF_CARRIERS_NUMBER_PREFIX)) {
224685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                final String number = (String) prefs.get(key);
224785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                if (mergeNumber.equals(number)) {
224885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String iccId = key.substring(PREF_CARRIERS_NUMBER_PREFIX.length());
224985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String subscriberKey = PREF_CARRIERS_SUBSCRIBER_PREFIX + iccId;
225085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    final String subscriberId = (String) prefs.get(subscriberKey);
225185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    if (!TextUtils.isEmpty(subscriberId)) {
225285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                        result.add(subscriberId);
225385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                    }
225485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey                }
225585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            }
225685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
225785190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
225885190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        final String[] resultArray = result.toArray(new String[result.size()]);
225985190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        Arrays.sort(resultArray);
226085190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        if (DBG_MERGE) {
226185190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey            Slog.d(LOG_TAG, "Found subscribers " + Arrays.toString(resultArray) + " after merge");
226285190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        }
226385190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey        return resultArray;
226485190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    }
226585190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey
226685190e62b6d44db4454891cd98c7e5ead04e8e1bJeff Sharkey    @Override
2267a3dfd75141d37ae7e170eeb200374f62235b092eShishir Agrawal    public boolean setOperatorBrandOverride(String brand) {
22685e5becdfa352e3ad1699cce13386b20761e2fde1Shishir Agrawal        enforceCarrierPrivilege();
2269a3dfd75141d37ae7e170eeb200374f62235b092eShishir Agrawal        return mPhone.setOperatorBrandOverride(brand);
2270b1ebf8c3755b7e1cb207cbd49f6c8bdfa3566668Shishir Agrawal    }
22714bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
22724bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    @Override
2273621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal    public boolean setRoamingOverride(List<String> gsmRoamingList,
2274621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal            List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2275621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal            List<String> cdmaNonRoamingList) {
2276621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal        enforceCarrierPrivilege();
2277621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal        return mPhone.setRoamingOverride(gsmRoamingList, gsmNonRoamingList, cdmaRoamingList,
2278621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal                cdmaNonRoamingList);
2279621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal    }
2280621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal
2281621a47c9ff058ac6a735ee5347c45ec30b0236baShishir Agrawal    @Override
22824bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    public int invokeOemRilRequestRaw(byte[] oemReq, byte[] oemResp) {
22834bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        enforceModifyPermission();
22844bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
22854bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        int returnValue = 0;
22864bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        try {
22874bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            AsyncResult result = (AsyncResult)sendRequest(CMD_INVOKE_OEM_RIL_REQUEST_RAW, oemReq);
22884bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(result.exception == null) {
22894bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if (result.result != null) {
22904bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    byte[] responseData = (byte[])(result.result);
22914bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    if(responseData.length > oemResp.length) {
22924bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                        Log.w(LOG_TAG, "Buffer to copy response too small: Response length is " +
22934bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                responseData.length +  "bytes. Buffer Size is " +
22944bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                                oemResp.length + "bytes.");
22954bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    }
22964bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    System.arraycopy(responseData, 0, oemResp, 0, responseData.length);
22974bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                    returnValue = responseData.length;
22984bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                }
22994bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            } else {
23004bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                CommandException ex = (CommandException) result.exception;
23014bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                returnValue = ex.getCommandError().ordinal();
23024bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu                if(returnValue > 0) returnValue *= -1;
23034bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            }
23044bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        } catch (RuntimeException e) {
23054bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            Log.w(LOG_TAG, "sendOemRilRequestRaw: Runtime Exception");
23064bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            returnValue = (CommandException.Error.GENERIC_FAILURE.ordinal());
23074bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu            if(returnValue > 0) returnValue *= -1;
23084bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        }
23094bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu
23104bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu        return returnValue;
23114bf01bc69fe97b9675463978cf5a2afff26fcccbSteven Liu    }
23125d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville
23135d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    @Override
23145d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    public void setRadioCapability(RadioAccessFamily[] rafs) {
23155d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        try {
23165d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville            ProxyController.getInstance().setRadioCapability(rafs);
23175d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        } catch (RuntimeException e) {
23185d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville            Log.w(LOG_TAG, "setRadioCapability: Runtime Exception");
23195d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        }
23205d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    }
23215d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville
23225d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    @Override
23235d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    public int getRadioAccessFamily(int phoneId) {
23245d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville        return ProxyController.getInstance().getRadioAccessFamily(phoneId);
23255d475dda0d2c2a220b8e33e77f9a40f5983c75b9Wink Saville    }
2326df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee
2327df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    @Override
2328df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    public void enableVideoCalling(boolean enable) {
2329df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        enforceModifyPermission();
2330df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
2331df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        editor.putBoolean(PREF_ENABLE_VIDEO_CALLING, enable);
2332df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee        editor.commit();
2333df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    }
2334df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee
2335df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    @Override
2336b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public boolean isVideoCallingEnabled(String callingPackage) {
2337b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
2338b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return false;
2339b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2340b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
234177527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // Check the user preference and the  system-level IMS setting. Even if the user has
234277527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // enabled video calling, if IMS is disabled we aren't able to support video calling.
234377527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // In the long run, we may instead need to check if there exists a connection service
234477527ac0cdad089f51530066f5248cb7925dd365Andrew Lee        // which can support video calling.
2345312e8177b25ab359627685d449e0a5fdb539809fAndrew Lee        return ImsManager.isVtEnabledByPlatform(mPhone.getContext())
2346312e8177b25ab359627685d449e0a5fdb539809fAndrew Lee                && ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
2347312e8177b25ab359627685d449e0a5fdb539809fAndrew Lee                && mTelephonySharedPreferences.getBoolean(PREF_ENABLE_VIDEO_CALLING, true);
2348df14ead5c9ddb3120a6841552db54d4713058d3bAndrew Lee    }
2349afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com
2350a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    @Override
2351a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    public boolean canChangeDtmfToneLength() {
23529504c6b5c5c7072f72d8a9e6df59dbda8a6ccbe4Jonathan Basseri        return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_DTMF_TYPE_ENABLED_BOOL);
2353a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    }
2354a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee
2355a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    @Override
2356a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    public boolean isWorldPhone() {
23579504c6b5c5c7072f72d8a9e6df59dbda8a6ccbe4Jonathan Basseri        return mApp.getCarrierConfig().getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL);
2358a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee    }
2359a1239f2604b7fed20970aadf7496d6e12ba7ceaeAndrew Lee
23609431b838f89399db2278c0436bd2817322a45f74Andrew Lee    @Override
23619431b838f89399db2278c0436bd2817322a45f74Andrew Lee    public boolean isTtyModeSupported() {
23629431b838f89399db2278c0436bd2817322a45f74Andrew Lee        TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
23639431b838f89399db2278c0436bd2817322a45f74Andrew Lee        TelephonyManager telephonyManager =
23649431b838f89399db2278c0436bd2817322a45f74Andrew Lee                (TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
23659431b838f89399db2278c0436bd2817322a45f74Andrew Lee        return !telephonyManager.isMultiSimEnabled() && telecomManager.isTtySupported();
23669431b838f89399db2278c0436bd2817322a45f74Andrew Lee    }
23679431b838f89399db2278c0436bd2817322a45f74Andrew Lee
23689431b838f89399db2278c0436bd2817322a45f74Andrew Lee    @Override
23699431b838f89399db2278c0436bd2817322a45f74Andrew Lee    public boolean isHearingAidCompatibilitySupported() {
23709431b838f89399db2278c0436bd2817322a45f74Andrew Lee        return mPhone.getContext().getResources().getBoolean(R.bool.hac_enabled);
23719431b838f89399db2278c0436bd2817322a45f74Andrew Lee    }
23729431b838f89399db2278c0436bd2817322a45f74Andrew Lee
23737310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe    /**
23747310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     * Returns the unique device ID of phone, for example, the IMEI for
23757310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     * GSM and the MEID for CDMA phones. Return null if device ID is not available.
23767310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     *
23777310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     * <p>Requires Permission:
23787310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
23797310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe     */
23807310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe    @Override
2381b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    public String getDeviceId(String callingPackage) {
2382b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (!canReadPhoneState(callingPackage, "getDeviceId")) {
2383b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return null;
2384b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2385b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
23867310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        final Phone phone = PhoneFactory.getPhone(0);
23877310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        if (phone != null) {
23887310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe            return phone.getDeviceId();
23897310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        } else {
23907310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe            return null;
23917310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe        }
23927310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe    }
23937310cc789b2efe4674e75bb8255373ab0c5a6881Sanket Padawe
2394afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com    /*
2395afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com     * {@hide}
2396afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com     * Returns the IMS Registration Status
2397afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com     */
23987a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    @Override
2399afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com    public boolean isImsRegistered() {
2400afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com        return mPhone.isImsRegistered();
2401afe8264bd1241982c39c86f40d0fd08f0888c824Libin.Tang@motorola.com    }
24027a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon
24037a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    @Override
24047a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
24057a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon        return PhoneUtils.getSubIdForPhoneAccount(phoneAccount);
24067a1885ba88b4ca833d6dae8b352097636f242917Santos Cordon    }
2407dcfc793ddff32e3fd5ab49db2647d7b08fc4d29cNathan Harold
2408c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    /*
2409c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * {@hide}
2410c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * Returns the IMS Registration Status
2411c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     */
2412c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    public boolean isWifiCallingEnabled() {
2413c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold        return mPhone.isWifiCallingEnabled();
2414c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    }
2415c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold
2416c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    /*
2417c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * {@hide}
2418c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     * Returns the IMS Registration Status
2419c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold     */
2420c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    public boolean isVolteEnabled() {
2421c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold        return mPhone.isVolteEnabled();
2422c55097a922f316dd97084bce196335b64c6a55b0Nathan Harold    }
2423b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
2424b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    private boolean canReadPhoneState(String callingPackage, String message) {
2425b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        mApp.enforceCallingOrSelfPermission(
2426b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov                android.Manifest.permission.READ_PHONE_STATE, message);
2427b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
2428b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
2429b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov                callingPackage) != AppOpsManager.MODE_ALLOWED) {
2430b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov            return false;
2431b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        }
2432b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov
2433b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov        return true;
2434b320e187c6eddc4a9d5f31d397f52500d38b4c05Svet Ganov    }
24358eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott
24368eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    @Override
24378eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    public void factoryReset(int subId) {
24388eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott        enforceConnectivityInternalPermission();
2439981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
2440981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott            return;
2441981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott        }
2442981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott
2443cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov        final long identity = Binder.clearCallingIdentity();
2444cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov        try {
2445981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott            if (SubscriptionManager.isUsableSubIdValue(subId) && !mUserManager.hasUserRestriction(
2446981d85874294656a51683ae6ecc6ba312d3635ceStuart Scott                    UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
2447cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Enable data
2448cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                setDataEnabled(subId, true);
2449cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Set network selection mode to automatic
2450cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                setNetworkSelectionModeAutomatic(subId);
2451cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Set preferred mobile network type to the best available
2452cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
2453cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                // Turn off roaming
2454cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov                SubscriptionManager.from(mApp).setDataRoaming(0, subId);
2455cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov            }
2456cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov        } finally {
2457cc087f8219bf8dd606a46a18a2b0f57079c7ff8aSvet Ganov            Binder.restoreCallingIdentity(identity);
24588eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott        }
24598eef64f25181774c3112892ca222af3c1cf259c7Stuart Scott    }
24601c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
24611c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    @Override
24621c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    public String getLocaleFromDefaultSim() {
24631c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // We query all subscriptions instead of just the active ones, because
24641c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // this might be called early on in the provisioning flow when the
24651c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // subscriptions potentially aren't active yet.
24661c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final List<SubscriptionInfo> slist = getAllSubscriptionInfoList();
24671c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (slist == null || slist.isEmpty()) {
24681c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return null;
24691c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
24701c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
24711c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // This function may be called very early, say, from the setup wizard, at
24721c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // which point we won't have a default subscription set. If that's the case
24731c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // we just choose the first, which will be valid in "most cases".
24741c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final int defaultSubId = getDefaultSubscription();
24751c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        SubscriptionInfo info = null;
24761c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (defaultSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
24771c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            info = slist.get(0);
24781c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        } else {
24791c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            for (SubscriptionInfo item : slist) {
24801c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                if (item.getSubscriptionId() == defaultSubId) {
24811c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    info = item;
24821c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    break;
24831c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                }
24841c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            }
24851c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
24861c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            if (info == null) {
24871c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                return null;
24881c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            }
24891c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
24901c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
24911c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // Try and fetch the locale from the carrier properties or from the SIM language
24921c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // preferences (EF-PL and EF-LI)...
24931c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final Phone defaultPhone = getPhone(info.getSubscriptionId());
24941c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (defaultPhone != null) {
24951c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            final Locale localeFromDefaultSim = defaultPhone.getLocaleFromSimAndCarrierPrefs();
24961c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            if (localeFromDefaultSim != null) {
24971c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                return localeFromDefaultSim.toLanguageTag();
24981c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            }
24991c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
25001c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
25011c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        // .. if that doesn't work, try and guess the language from the sim MCC.
25021c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final int mcc = info.getMcc();
25031c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final Locale locale = MccTable.getLocaleFromMcc(mPhone.getContext(), mcc);
25041c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        if (locale != null) {
25051c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return locale.toLanguageTag();
25061c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
25071c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
25081c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        return null;
25091c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    }
25101c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
25111c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    private List<SubscriptionInfo> getAllSubscriptionInfoList() {
25121c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final long identity = Binder.clearCallingIdentity();
25131c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        try {
25141c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return mSubscriptionController.getAllSubInfoList(
25151c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    mPhone.getContext().getOpPackageName());
25161c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        } finally {
25171c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            Binder.restoreCallingIdentity(identity);
25181c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
25191c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    }
25201c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath
25211c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
25221c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        final long identity = Binder.clearCallingIdentity();
25231c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        try {
25241c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            return mSubscriptionController.getActiveSubscriptionInfoList(
25251c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath                    mPhone.getContext().getOpPackageName());
25261c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        } finally {
25271c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath            Binder.restoreCallingIdentity(identity);
25281c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath        }
25291c496c28c4122c00f3c54ce8717fb767d1421bf6Narayan Kamath    }
25307fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham
25317fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    /**
25327fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham     * {@hide}
25337fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham     * Returns the modem stats
25347fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham     */
25357fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    @Override
25367fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    public ModemActivityInfo getModemActivityInfo() {
25377fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham        return (ModemActivityInfo) sendRequest(CMD_GET_MODEM_ACTIVITY_INFO, null);
25387fcff6902e3a8b5f54c5020edbbb8818dfcdcbffPrerepa Viswanadham    }
25397d4ddf6dc0d7c8158bac3a5dec7936e837e95bddSantos Cordon}
2540