16bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt/*
26bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* Copyright (C) 2015 The Android Open Source Project
36bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt*
46bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* Licensed under the Apache License, Version 2.0 (the "License");
56bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* you may not use this file except in compliance with the License.
66bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* You may obtain a copy of the License at
76bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt*
86bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt*      http://www.apache.org/licenses/LICENSE-2.0
96bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt*
106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* Unless required by applicable law or agreed to in writing, software
116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* distributed under the License is distributed on an "AS IS" BASIS,
126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* See the License for the specific language governing permissions and
146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt* limitations under the License.
156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt*/
166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltpackage com.android.internal.telephony;
186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport static android.telephony.SubscriptionManager.INVALID_PHONE_INDEX;
206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.content.BroadcastReceiver;
236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.content.Context;
246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.content.Intent;
256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.content.IntentFilter;
266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.net.NetworkCapabilities;
276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.net.NetworkFactory;
286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.net.NetworkRequest;
296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.os.Handler;
306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.os.Looper;
316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.os.Message;
326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.os.Registrant;
336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.os.RegistrantList;
346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.os.RemoteException;
356bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.telephony.Rlog;
366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.text.TextUtils;
376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport android.util.LocalLog;
386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
39e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwaltimport com.android.internal.annotations.VisibleForTesting;
406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.CommandsInterface;
416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.IOnSubscriptionsChangedListener;
426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.ITelephonyRegistry;
436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.dataconnection.DcRequest;
446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.util.IndentingPrintWriter;
456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.io.FileDescriptor;
476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.io.PrintWriter;
486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.lang.IllegalArgumentException;
496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.ArrayList;
506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.Calendar;
516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.Collection;
526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.Collections;
536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.List;
546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt/**
566bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * Utility singleton to monitor subscription changes and incoming NetworkRequests
576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * and determine which phone/phones are active.
586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt *
596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * Manages the ALLOW_DATA calls to modems and notifies phones about changes to
606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * the active phones.  Note we don't wait for data attach (which may not happen anyway).
616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt */
626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltpublic class PhoneSwitcher extends Handler {
636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static String LOG_TAG = "PhoneSwitcher";
646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static boolean VDBG = false;
656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final int mMaxActivePhones;
676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final List<DcRequest> mPrioritizedDcRequests = new ArrayList<DcRequest>();
686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final RegistrantList[] mActivePhoneRegistrants;
696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final SubscriptionController mSubscriptionController;
706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final int[] mPhoneSubscriptions;
716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final CommandsInterface[] mCommandsInterfaces;
726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final Context mContext;
736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final PhoneState[] mPhoneStates;
746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final int mNumPhones;
756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final Phone[] mPhones;
766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final LocalLog mLocalLog;
776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private int mDefaultDataSubscription;
796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_DEFAULT_SUBSCRIPTION_CHANGED = 101;
816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_SUBSCRIPTION_CHANGED         = 102;
826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_REQUEST_NETWORK              = 103;
836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_RELEASE_NETWORK              = 104;
846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_EMERGENCY_TOGGLE             = 105;
85e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    private final static int EVENT_RESEND_DATA_ALLOWED          = 106;
866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int MAX_LOCAL_LOG_LINES = 30;
886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
89e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    @VisibleForTesting
90e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    public PhoneSwitcher(Looper looper) {
91e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        super(looper);
92e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mMaxActivePhones = 0;
93e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mSubscriptionController = null;
94e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mPhoneSubscriptions = null;
95e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mCommandsInterfaces = null;
96e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mContext = null;
97e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mPhoneStates = null;
98e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mPhones = null;
99e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mLocalLog = null;
100e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mActivePhoneRegistrants = null;
101e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mNumPhones = 0;
102e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    }
103e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt
1046bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public PhoneSwitcher(int maxActivePhones, int numPhones, Context context,
1056bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
1066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            CommandsInterface[] cis, Phone[] phones) {
1076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        super(looper);
1086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mContext = context;
1096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mNumPhones = numPhones;
1106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mPhones = phones;
1116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mPhoneSubscriptions = new int[numPhones];
1126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mMaxActivePhones = maxActivePhones;
1136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES);
1146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mSubscriptionController = subscriptionController;
1166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants = new RegistrantList[numPhones];
1186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mPhoneStates = new PhoneState[numPhones];
1196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0; i < numPhones; i++) {
1206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mActivePhoneRegistrants[i] = new RegistrantList();
1216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mPhoneStates[i] = new PhoneState();
1226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (mPhones[i] != null) {
1236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                mPhones[i].registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
1246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mCommandsInterfaces = cis;
1286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        try {
1306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            tr.addOnSubscriptionsChangedListener("PhoneSwitcher", mSubscriptionsChangedListener);
1316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        } catch (RemoteException e) {
1326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mContext.registerReceiver(mDefaultDataChangedReceiver,
1356bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
1366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        NetworkCapabilities netCap = new NetworkCapabilities();
1386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
1416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
1426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
1436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
1446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
1456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
1466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
1476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
1486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
1496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
1506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
1516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
1546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                netCap, this);
1553baedf2ead743a2c67dcac03733cec52bcef5636Robert Greenwalt        // we want to see all requests
1563baedf2ead743a2c67dcac03733cec52bcef5636Robert Greenwalt        networkFactory.setScoreFilter(101);
1576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        networkFactory.register();
1586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        log("PhoneSwitcher started");
1606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
1616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final BroadcastReceiver mDefaultDataChangedReceiver = new BroadcastReceiver() {
1636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
1646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public void onReceive(Context context, Intent intent) {
1656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = PhoneSwitcher.this.obtainMessage(EVENT_DEFAULT_SUBSCRIPTION_CHANGED);
1666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
1676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    };
1696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
1716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            new IOnSubscriptionsChangedListener.Stub() {
1726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
1736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public void onSubscriptionsChanged() {
1746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = PhoneSwitcher.this.obtainMessage(EVENT_SUBSCRIPTION_CHANGED);
1756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
1766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    };
1786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    @Override
1806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void handleMessage(Message msg) {
1816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        switch (msg.what) {
1826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_SUBSCRIPTION_CHANGED: {
1836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onEvaluate(REQUESTS_UNCHANGED, "subChanged");
1846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_DEFAULT_SUBSCRIPTION_CHANGED: {
1876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onEvaluate(REQUESTS_UNCHANGED, "defaultChanged");
1886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1896bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1906bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_REQUEST_NETWORK: {
1916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onRequestNetwork((NetworkRequest)msg.obj);
1926bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1936bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1946bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_RELEASE_NETWORK: {
1956bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onReleaseNetwork((NetworkRequest)msg.obj);
1966bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1976bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1986bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_EMERGENCY_TOGGLE: {
1996bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onEvaluate(REQUESTS_CHANGED, "emergencyToggle");
2006bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
2016bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
202e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            case EVENT_RESEND_DATA_ALLOWED: {
203e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt                onResendDataAllowed(msg);
204e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt                break;
205e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt            }
2066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private boolean isEmergency() {
2106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (Phone p : mPhones) {
2116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (p == null) continue;
2126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (p.isInEcm() || p.isInEmergencyCall()) return true;
2136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        return false;
2156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory {
2186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        private final PhoneSwitcher mPhoneSwitcher;
2196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public PhoneSwitcherNetworkRequestListener (Looper l, Context c,
2206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                NetworkCapabilities nc, PhoneSwitcher ps) {
2216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            super(l, c, "PhoneSwitcherNetworkRequstListener", nc);
2226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mPhoneSwitcher = ps;
2236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
2266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
2273baedf2ead743a2c67dcac03733cec52bcef5636Robert Greenwalt            if (VDBG) log("needNetworkFor " + networkRequest + ", " + score);
2286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK);
2296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.obj = networkRequest;
2306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
2316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
2346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        protected void releaseNetworkFor(NetworkRequest networkRequest) {
2353baedf2ead743a2c67dcac03733cec52bcef5636Robert Greenwalt            if (VDBG) log("releaseNetworkFor " + networkRequest);
2366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK);
2376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.obj = networkRequest;
2386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
2396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void onRequestNetwork(NetworkRequest networkRequest) {
2436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final DcRequest dcRequest = new DcRequest(networkRequest, mContext);
2446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (mPrioritizedDcRequests.contains(dcRequest) == false) {
2456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mPrioritizedDcRequests.add(dcRequest);
2466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Collections.sort(mPrioritizedDcRequests);
2476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            onEvaluate(REQUESTS_CHANGED, "netRequest");
2486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void onReleaseNetwork(NetworkRequest networkRequest) {
2526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final DcRequest dcRequest = new DcRequest(networkRequest, mContext);
2536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (mPrioritizedDcRequests.remove(dcRequest)) {
2556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            onEvaluate(REQUESTS_CHANGED, "netReleased");
2566bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static final boolean REQUESTS_CHANGED   = true;
2606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static final boolean REQUESTS_UNCHANGED = false;
2616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    /**
2626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * Re-evaluate things.
2636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * Do nothing if nothing's changed.
2646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     *
2656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * Otherwise, go through the requests in priority order adding their phone
2666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * until we've added up to the max allowed.  Then go through shutting down
2676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * phones that aren't in the active phone list.  Finally, activate all
2686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * phones in the active phone list.
2696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     */
27087c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt    private void onEvaluate(boolean requestsChanged, String reason) {
27187c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt        StringBuilder sb = new StringBuilder(reason);
2726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (isEmergency()) {
2736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            log("onEvalute aborted due to Emergency");
2746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            return;
2756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        boolean diffDetected = requestsChanged;
2786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final int dataSub = mSubscriptionController.getDefaultDataSubId();
2796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (dataSub != mDefaultDataSubscription) {
28087c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt            sb.append(" default ").append(mDefaultDataSubscription).append("->").append(dataSub);
2816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mDefaultDataSubscription = dataSub;
2826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            diffDetected = true;
28387c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt
2846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0; i < mNumPhones; i++) {
2876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            int sub = mSubscriptionController.getSubIdUsingPhoneId(i);
2886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (sub != mPhoneSubscriptions[i]) {
28987c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt                sb.append(" phone[").append(i).append("] ").append(mPhoneSubscriptions[i]);
29087c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt                sb.append("->").append(sub);
2916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                mPhoneSubscriptions[i] = sub;
2926bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                diffDetected = true;
2936bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
2946bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2956bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2966bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (diffDetected) {
29787c2958ce9e74b35ca6ef36f0b5caaaac8d5b008Robert Greenwalt            log("evaluating due to " + sb.toString());
2986bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2996bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            List<Integer> newActivePhones = new ArrayList<Integer>();
3006bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3016bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            for (DcRequest dcRequest : mPrioritizedDcRequests) {
3026bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                int phoneIdForRequest = phoneIdForRequest(dcRequest.networkRequest);
3036bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (phoneIdForRequest == INVALID_PHONE_INDEX) continue;
3046bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (newActivePhones.contains(phoneIdForRequest)) continue;
3056bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                newActivePhones.add(phoneIdForRequest);
3066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (newActivePhones.size() >= mMaxActivePhones) break;
3076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
3086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (VDBG) {
3106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                log("default subId = " + mDefaultDataSubscription);
3116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                for (int i = 0; i < mNumPhones; i++) {
3126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                    log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]");
3136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                }
3146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                log(" newActivePhones:");
3156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                for (Integer i : newActivePhones) log("  " + i);
3166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
3176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
3196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (newActivePhones.contains(phoneId) == false) {
3206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                    deactivate(phoneId);
3216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                }
3226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
3236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            // only activate phones up to the limit
3256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            for (int phoneId : newActivePhones) {
3266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                activate(phoneId);
3276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
3286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static class PhoneState {
3326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public volatile boolean active = false;
3336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public long lastRequested = 0;
3346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3356bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void deactivate(int phoneId) {
3376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        PhoneState state = mPhoneStates[phoneId];
3386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (state.active == false) return;
3396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.active = false;
3406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        log("deactivate " + phoneId);
3416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.lastRequested = System.currentTimeMillis();
3426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mCommandsInterfaces[phoneId].setDataAllowed(false, null);
3436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].notifyRegistrants();
3446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void activate(int phoneId) {
3476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        PhoneState state = mPhoneStates[phoneId];
3486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (state.active == true) return;
3496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.active = true;
3506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        log("activate " + phoneId);
3516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.lastRequested = System.currentTimeMillis();
3526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mCommandsInterfaces[phoneId].setDataAllowed(true, null);
3536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].notifyRegistrants();
3546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
356e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    // used when the modem may have been rebooted and we want to resend
357e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    // setDataAllowed
358e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    public void resendDataAllowed(int phoneId) {
359e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        validatePhoneId(phoneId);
360e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        Message msg = obtainMessage(EVENT_RESEND_DATA_ALLOWED);
361e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        msg.arg1 = phoneId;
362e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        msg.sendToTarget();
363e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    }
364e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt
365e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    private void onResendDataAllowed(Message msg) {
366e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        final int phoneId = msg.arg1;
367e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt        mCommandsInterfaces[phoneId].setDataAllowed(mPhoneStates[phoneId].active, null);
368e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt    }
369e9bf1f44cc6a888fff8419c8f35612d503ba3216Robert Greenwalt
3706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private int phoneIdForRequest(NetworkRequest netRequest) {
3716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        String specifier = netRequest.networkCapabilities.getNetworkSpecifier();
3726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        int subId;
3736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (TextUtils.isEmpty(specifier)) {
3756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            subId = mDefaultDataSubscription;
3766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        } else {
3776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            subId = Integer.parseInt(specifier);
3786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        int phoneId = INVALID_PHONE_INDEX;
3806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (subId == INVALID_SUBSCRIPTION_ID) return phoneId;
3816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0 ; i < mNumPhones; i++) {
3836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (mPhoneSubscriptions[i] == subId) {
3846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                phoneId = i;
3856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
3866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
3876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        return phoneId;
3896bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3906bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public boolean isPhoneActive(int phoneId) {
3926bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        validatePhoneId(phoneId);
3936bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        return mPhoneStates[phoneId].active;
3946bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3956bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3966bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void registerForActivePhoneSwitch(int phoneId, Handler h, int what, Object o) {
3976bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        validatePhoneId(phoneId);
3986bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        Registrant r = new Registrant(h, what, o);
3996bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].add(r);
4006bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        r.notifyRegistrant();
4016bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
4026bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
4036bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void unregisterForActivePhoneSwitch(int phoneId, Handler h) {
4046bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        validatePhoneId(phoneId);
4056bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].remove(h);
4066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
4076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
4086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void validatePhoneId(int phoneId) {
4096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (phoneId < 0 || phoneId >= mNumPhones) {
4106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            throw new IllegalArgumentException("Invalid PhoneId");
4116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
4126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
4136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
4146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void log(String l) {
4156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        Rlog.d(LOG_TAG, l);
4166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mLocalLog.log(l);
4176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
4186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
4196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
4206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
4216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        pw.println("PhoneSwitcher:");
4226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        Calendar c = Calendar.getInstance();
4236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0; i < mNumPhones; i++) {
4246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            PhoneState ps = mPhoneStates[i];
4256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            c.setTimeInMillis(ps.lastRequested);
4266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            pw.println("PhoneId(" + i + ") active=" + ps.active + ", lastRequest=" +
4276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                    (ps.lastRequested == 0 ? "never" :
4286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                     String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)));
4296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
4306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        pw.increaseIndent();
4316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mLocalLog.dump(fd, pw, args);
4326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        pw.decreaseIndent();
4336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
4346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt}
435