PhoneSwitcher.java revision 6bfc71d2b5340f6274b3e63926a7068e364fc9ff
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
396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.CommandsInterface;
406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.IOnSubscriptionsChangedListener;
416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.ITelephonyRegistry;
426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.telephony.dataconnection.DcRequest;
436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport com.android.internal.util.IndentingPrintWriter;
446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.io.FileDescriptor;
466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.io.PrintWriter;
476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.lang.IllegalArgumentException;
486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.ArrayList;
496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.Calendar;
506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.Collection;
516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.Collections;
526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltimport java.util.List;
536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt/**
556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * Utility singleton to monitor subscription changes and incoming NetworkRequests
566bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * and determine which phone/phones are active.
576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt *
586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * Manages the ALLOW_DATA calls to modems and notifies phones about changes to
596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt * the active phones.  Note we don't wait for data attach (which may not happen anyway).
606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt */
616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwaltpublic class PhoneSwitcher extends Handler {
626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static String LOG_TAG = "PhoneSwitcher";
636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static boolean VDBG = false;
646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final int mMaxActivePhones;
666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final List<DcRequest> mPrioritizedDcRequests = new ArrayList<DcRequest>();
676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final RegistrantList[] mActivePhoneRegistrants;
686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final SubscriptionController mSubscriptionController;
696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final int[] mPhoneSubscriptions;
706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final CommandsInterface[] mCommandsInterfaces;
716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final Context mContext;
726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final PhoneState[] mPhoneStates;
736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final int mNumPhones;
746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final Phone[] mPhones;
756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final LocalLog mLocalLog;
766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private int mDefaultDataSubscription;
786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_DEFAULT_SUBSCRIPTION_CHANGED = 101;
806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_SUBSCRIPTION_CHANGED         = 102;
816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_REQUEST_NETWORK              = 103;
826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_RELEASE_NETWORK              = 104;
836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int EVENT_EMERGENCY_TOGGLE             = 105;
846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final static int MAX_LOCAL_LOG_LINES = 30;
866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public PhoneSwitcher(int maxActivePhones, int numPhones, Context context,
886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            SubscriptionController subscriptionController, Looper looper, ITelephonyRegistry tr,
896bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            CommandsInterface[] cis, Phone[] phones) {
906bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        super(looper);
916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mContext = context;
926bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mNumPhones = numPhones;
936bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mPhones = phones;
946bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mPhoneSubscriptions = new int[numPhones];
956bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mMaxActivePhones = maxActivePhones;
966bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mLocalLog = new LocalLog(MAX_LOCAL_LOG_LINES);
976bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
986bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mSubscriptionController = subscriptionController;
996bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1006bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants = new RegistrantList[numPhones];
1016bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mPhoneStates = new PhoneState[numPhones];
1026bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0; i < numPhones; i++) {
1036bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mActivePhoneRegistrants[i] = new RegistrantList();
1046bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mPhoneStates[i] = new PhoneState();
1056bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (mPhones[i] != null) {
1066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                mPhones[i].registerForEmergencyCallToggle(this, EVENT_EMERGENCY_TOGGLE, null);
1076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mCommandsInterfaces = cis;
1116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        try {
1136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            tr.addOnSubscriptionsChangedListener("PhoneSwitcher", mSubscriptionsChangedListener);
1146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        } catch (RemoteException e) {
1156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mContext.registerReceiver(mDefaultDataChangedReceiver,
1186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));
1196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        NetworkCapabilities netCap = new NetworkCapabilities();
1216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
1236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
1246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
1256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
1266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
1276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
1286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
1296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
1306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
1316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
1326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
1336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
1346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        netCap.setNetworkSpecifier(NetworkCapabilities.MATCH_ALL_REQUESTS_NETWORK_SPECIFIER);
1356bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
1376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                netCap, this);
1386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        networkFactory.setScoreFilter(50);
1396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        networkFactory.register();
1406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        log("PhoneSwitcher started");
1426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
1436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final BroadcastReceiver mDefaultDataChangedReceiver = new BroadcastReceiver() {
1456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
1466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public void onReceive(Context context, Intent intent) {
1476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = PhoneSwitcher.this.obtainMessage(EVENT_DEFAULT_SUBSCRIPTION_CHANGED);
1486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
1496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    };
1516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private final IOnSubscriptionsChangedListener mSubscriptionsChangedListener =
1536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            new IOnSubscriptionsChangedListener.Stub() {
1546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
1556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public void onSubscriptionsChanged() {
1566bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = PhoneSwitcher.this.obtainMessage(EVENT_SUBSCRIPTION_CHANGED);
1576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
1586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    };
1606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    @Override
1626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void handleMessage(Message msg) {
1636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        switch (msg.what) {
1646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_SUBSCRIPTION_CHANGED: {
1656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onEvaluate(REQUESTS_UNCHANGED, "subChanged");
1666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_DEFAULT_SUBSCRIPTION_CHANGED: {
1696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onEvaluate(REQUESTS_UNCHANGED, "defaultChanged");
1706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_REQUEST_NETWORK: {
1736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onRequestNetwork((NetworkRequest)msg.obj);
1746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_RELEASE_NETWORK: {
1776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onReleaseNetwork((NetworkRequest)msg.obj);
1786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            case EVENT_EMERGENCY_TOGGLE: {
1816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                onEvaluate(REQUESTS_CHANGED, "emergencyToggle");
1826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
1836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
1846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
1866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private boolean isEmergency() {
1886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (Phone p : mPhones) {
1896bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (p == null) continue;
1906bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (p.isInEcm() || p.isInEmergencyCall()) return true;
1916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
1926bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        return false;
1936bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
1946bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
1956bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static class PhoneSwitcherNetworkRequestListener extends NetworkFactory {
1966bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        private final PhoneSwitcher mPhoneSwitcher;
1976bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public PhoneSwitcherNetworkRequestListener (Looper l, Context c,
1986bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                NetworkCapabilities nc, PhoneSwitcher ps) {
1996bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            super(l, c, "PhoneSwitcherNetworkRequstListener", nc);
2006bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mPhoneSwitcher = ps;
2016bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2026bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2036bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
2046bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
2056bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK);
2066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.obj = networkRequest;
2076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
2086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        @Override
2116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        protected void releaseNetworkFor(NetworkRequest networkRequest) {
2126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK);
2136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.obj = networkRequest;
2146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            msg.sendToTarget();
2156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void onRequestNetwork(NetworkRequest networkRequest) {
2196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final DcRequest dcRequest = new DcRequest(networkRequest, mContext);
2206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (mPrioritizedDcRequests.contains(dcRequest) == false) {
2216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mPrioritizedDcRequests.add(dcRequest);
2226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            Collections.sort(mPrioritizedDcRequests);
2236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            onEvaluate(REQUESTS_CHANGED, "netRequest");
2246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void onReleaseNetwork(NetworkRequest networkRequest) {
2286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final DcRequest dcRequest = new DcRequest(networkRequest, mContext);
2296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (mPrioritizedDcRequests.remove(dcRequest)) {
2316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            onEvaluate(REQUESTS_CHANGED, "netReleased");
2326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
2346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2356bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static final boolean REQUESTS_CHANGED   = true;
2366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static final boolean REQUESTS_UNCHANGED = false;
2376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    /**
2386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * Re-evaluate things.
2396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * Do nothing if nothing's changed.
2406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     *
2416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * Otherwise, go through the requests in priority order adding their phone
2426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * until we've added up to the max allowed.  Then go through shutting down
2436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * phones that aren't in the active phone list.  Finally, activate all
2446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     * phones in the active phone list.
2456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt     */
2466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void onEvaluate(boolean requestsChanged, String why) {
2476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (isEmergency()) {
2486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            log("onEvalute aborted due to Emergency");
2496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            return;
2506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        boolean diffDetected = requestsChanged;
2536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final int dataSub = mSubscriptionController.getDefaultDataSubId();
2546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (dataSub != mDefaultDataSubscription) {
2556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            mDefaultDataSubscription = dataSub;
2566bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            diffDetected = true;
2576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0; i < mNumPhones; i++) {
2606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            int sub = mSubscriptionController.getSubIdUsingPhoneId(i);
2616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (sub != mPhoneSubscriptions[i]) {
2626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                mPhoneSubscriptions[i] = sub;
2636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                diffDetected = true;
2646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
2656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
2666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (diffDetected) {
2686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            log("evaluating due to " + why);
2696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            List<Integer> newActivePhones = new ArrayList<Integer>();
2716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            for (DcRequest dcRequest : mPrioritizedDcRequests) {
2736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                int phoneIdForRequest = phoneIdForRequest(dcRequest.networkRequest);
2746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (phoneIdForRequest == INVALID_PHONE_INDEX) continue;
2756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (newActivePhones.contains(phoneIdForRequest)) continue;
2766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                newActivePhones.add(phoneIdForRequest);
2776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (newActivePhones.size() >= mMaxActivePhones) break;
2786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
2796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (VDBG) {
2816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                log("default subId = " + mDefaultDataSubscription);
2826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                for (int i = 0; i < mNumPhones; i++) {
2836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                    log(" phone[" + i + "] using sub[" + mPhoneSubscriptions[i] + "]");
2846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                }
2856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                log(" newActivePhones:");
2866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                for (Integer i : newActivePhones) log("  " + i);
2876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
2886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2896bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
2906bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                if (newActivePhones.contains(phoneId) == false) {
2916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                    deactivate(phoneId);
2926bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                }
2936bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
2946bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
2956bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            // only activate phones up to the limit
2966bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            for (int phoneId : newActivePhones) {
2976bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                activate(phoneId);
2986bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
2996bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3006bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3016bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3026bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private static class PhoneState {
3036bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public volatile boolean active = false;
3046bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        public long lastRequested = 0;
3056bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3066bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3076bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void deactivate(int phoneId) {
3086bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        PhoneState state = mPhoneStates[phoneId];
3096bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (state.active == false) return;
3106bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.active = false;
3116bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        log("deactivate " + phoneId);
3126bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.lastRequested = System.currentTimeMillis();
3136bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mCommandsInterfaces[phoneId].setDataAllowed(false, null);
3146bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].notifyRegistrants();
3156bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3166bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3176bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void activate(int phoneId) {
3186bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        PhoneState state = mPhoneStates[phoneId];
3196bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (state.active == true) return;
3206bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.active = true;
3216bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        log("activate " + phoneId);
3226bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        state.lastRequested = System.currentTimeMillis();
3236bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mCommandsInterfaces[phoneId].setDataAllowed(true, null);
3246bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].notifyRegistrants();
3256bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3266bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3276bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private int phoneIdForRequest(NetworkRequest netRequest) {
3286bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        String specifier = netRequest.networkCapabilities.getNetworkSpecifier();
3296bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        int subId;
3306bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3316bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (TextUtils.isEmpty(specifier)) {
3326bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            subId = mDefaultDataSubscription;
3336bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        } else {
3346bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            subId = Integer.parseInt(specifier);
3356bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3366bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        int phoneId = INVALID_PHONE_INDEX;
3376bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (subId == INVALID_SUBSCRIPTION_ID) return phoneId;
3386bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3396bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0 ; i < mNumPhones; i++) {
3406bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            if (mPhoneSubscriptions[i] == subId) {
3416bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                phoneId = i;
3426bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                break;
3436bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            }
3446bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3456bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        return phoneId;
3466bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3476bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3486bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public boolean isPhoneActive(int phoneId) {
3496bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        validatePhoneId(phoneId);
3506bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        return mPhoneStates[phoneId].active;
3516bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3526bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3536bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void registerForActivePhoneSwitch(int phoneId, Handler h, int what, Object o) {
3546bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        validatePhoneId(phoneId);
3556bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        Registrant r = new Registrant(h, what, o);
3566bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].add(r);
3576bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        r.notifyRegistrant();
3586bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3596bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3606bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void unregisterForActivePhoneSwitch(int phoneId, Handler h) {
3616bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        validatePhoneId(phoneId);
3626bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mActivePhoneRegistrants[phoneId].remove(h);
3636bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3646bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3656bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void validatePhoneId(int phoneId) {
3666bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        if (phoneId < 0 || phoneId >= mNumPhones) {
3676bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            throw new IllegalArgumentException("Invalid PhoneId");
3686bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3696bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3706bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3716bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    private void log(String l) {
3726bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        Rlog.d(LOG_TAG, l);
3736bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mLocalLog.log(l);
3746bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3756bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt
3766bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
3776bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
3786bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        pw.println("PhoneSwitcher:");
3796bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        Calendar c = Calendar.getInstance();
3806bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        for (int i = 0; i < mNumPhones; i++) {
3816bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            PhoneState ps = mPhoneStates[i];
3826bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            c.setTimeInMillis(ps.lastRequested);
3836bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt            pw.println("PhoneId(" + i + ") active=" + ps.active + ", lastRequest=" +
3846bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                    (ps.lastRequested == 0 ? "never" :
3856bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt                     String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)));
3866bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        }
3876bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        pw.increaseIndent();
3886bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        mLocalLog.dump(fd, pw, args);
3896bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt        pw.decreaseIndent();
3906bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt    }
3916bfc71d2b5340f6274b3e63926a7068e364fc9ffRobert Greenwalt}
392