150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu/*
250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * Copyright (C) 2017 The Android Open Source Project
350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu *
450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * Licensed under the Apache License, Version 2.0 (the "License");
550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * you may not use this file except in compliance with the License.
650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * You may obtain a copy of the License at
750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu *
850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu *      http://www.apache.org/licenses/LICENSE-2.0
950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu *
1050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * Unless required by applicable law or agreed to in writing, software
1150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * distributed under the License is distributed on an "AS IS" BASIS,
1250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * See the License for the specific language governing permissions and
1450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * limitations under the License.
1550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu */
1650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
1750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yupackage com.android.internal.telephony;
1850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
1950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport static android.hardware.radio.V1_0.DeviceStateType.CHARGING_STATE;
2050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport static android.hardware.radio.V1_0.DeviceStateType.LOW_DATA_EXPECTED;
2150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport static android.hardware.radio.V1_0.DeviceStateType.POWER_SAVE_MODE;
2250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
2350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.content.BroadcastReceiver;
2450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.content.Context;
2550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.content.Intent;
2650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.content.IntentFilter;
2750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.hardware.display.DisplayManager;
2850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.hardware.radio.V1_0.IndicationFilter;
2950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.net.ConnectivityManager;
3050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.os.BatteryManager;
3150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.os.Handler;
3250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.os.Message;
3350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.os.PowerManager;
3450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.telephony.Rlog;
3550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.util.LocalLog;
3650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport android.view.Display;
3750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
3850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport com.android.internal.util.IndentingPrintWriter;
3950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
4050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport java.io.FileDescriptor;
4150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport java.io.PrintWriter;
4250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yuimport java.util.ArrayList;
4350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
4450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu/**
4550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * The device state monitor monitors the device state such as charging state, power saving sate,
4650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * and then passes down the information to the radio modem for the modem to perform its own
4750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * proprietary power saving strategy. Device state monitor also turns off the unsolicited
4850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * response from the modem when the device does not need to receive it, for example, device's
4950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * screen is off and does not have activities like tethering, remote display, etc...This effectively
5050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * prevents the CPU from waking up by those unnecessary unsolicited responses such as signal
5150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu * strength update.
5250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu */
5350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yupublic class DeviceStateMonitor extends Handler {
5450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    protected static final boolean DBG = false;      /* STOPSHIP if true */
5550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    protected static final String TAG = DeviceStateMonitor.class.getSimpleName();
5650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
5750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private static final int EVENT_RIL_CONNECTED                = 0;
5850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private static final int EVENT_SCREEN_STATE_CHANGED         = 1;
5950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private static final int EVENT_POWER_SAVE_MODE_CHANGED      = 2;
6050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private static final int EVENT_CHARGING_STATE_CHANGED       = 3;
6150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private static final int EVENT_TETHERING_STATE_CHANGED      = 4;
6250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
6350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private final Phone mPhone;
6450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
6550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private final LocalLog mLocalLog = new LocalLog(100);
6650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
6750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
6850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Flag for wifi/usb/bluetooth tethering turned on or not
6950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
7050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean mIsTetheringOn;
7150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
7250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
73f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu     * Screen state provided by Display Manager. True indicates one of the screen is on, otherwise
74f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu     * all off.
7550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
76f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu    private boolean mIsScreenOn;
7750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
7850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
7950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Indicating the device is plugged in and is supplying sufficient power that the battery level
8050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * is going up (or the battery is fully charged). See BatteryManager.isCharging() for the
8150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * details
8250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
8350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean mIsCharging;
8450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
8550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
8650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Flag for device power save mode. See PowerManager.isPowerSaveMode() for the details.
8750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Note that it is not possible both mIsCharging and mIsPowerSaveOn are true at the same time.
8850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * The system will automatically end power save mode when the device starts charging.
8950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
9050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean mIsPowerSaveOn;
9150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
9250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
9350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Low data expected mode. True indicates low data traffic is expected, for example, when the
9450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * device is idle (e.g. screen is off and not doing tethering in the background). Note this
9550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * doesn't mean no data is expected.
9650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
9750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean mIsLowDataExpected;
9850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
9950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
10050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * The unsolicited response filter. See IndicationFilter defined in types.hal for the definition
10150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * of each bit.
10250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
10350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private int mUnsolicitedResponseFilter = IndicationFilter.ALL;
10450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
10550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private final DisplayManager.DisplayListener mDisplayListener =
10650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            new DisplayManager.DisplayListener() {
10750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                @Override
10850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                public void onDisplayAdded(int displayId) { }
10950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
11050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                @Override
11150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                public void onDisplayRemoved(int displayId) { }
11250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
11350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                @Override
11450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                public void onDisplayChanged(int displayId) {
115f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                    boolean screenOn = isScreenOn();
116f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                    Message msg = obtainMessage(EVENT_SCREEN_STATE_CHANGED);
117f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                    msg.arg1 = screenOn ? 1 : 0;
118f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                    sendMessage(msg);
11950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                }
12050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            };
12150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
12250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
12350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Device state broadcast receiver
12450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
12550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
12650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        @Override
12750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        public void onReceive(Context context, Intent intent) {
12850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            log("received: " + intent, true);
12950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
13050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            Message msg;
13150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            switch (intent.getAction()) {
13250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED:
13350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg = obtainMessage(EVENT_POWER_SAVE_MODE_CHANGED);
13450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg.arg1 = isPowerSaveModeOn() ? 1 : 0;
13550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    log("Power Save mode " + ((msg.arg1 == 1) ? "on" : "off"), true);
13650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    break;
13750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                case BatteryManager.ACTION_CHARGING:
13850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg = obtainMessage(EVENT_CHARGING_STATE_CHANGED);
13950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg.arg1 = 1;   // charging
14050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    break;
14150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                case BatteryManager.ACTION_DISCHARGING:
14250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg = obtainMessage(EVENT_CHARGING_STATE_CHANGED);
14350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg.arg1 = 0;   // not charging
14450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    break;
14550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                case ConnectivityManager.ACTION_TETHER_STATE_CHANGED:
14650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    ArrayList<String> activeTetherIfaces = intent.getStringArrayListExtra(
14750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                            ConnectivityManager.EXTRA_ACTIVE_TETHER);
14850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
14950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    boolean isTetheringOn = activeTetherIfaces != null
15050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                            && activeTetherIfaces.size() > 0;
15150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    log("Tethering " + (isTetheringOn ? "on" : "off"), true);
15250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg = obtainMessage(EVENT_TETHERING_STATE_CHANGED);
15350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    msg.arg1 = isTetheringOn ? 1 : 0;
15450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    break;
15550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                default:
15650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    log("Unexpected broadcast intent: " + intent, false);
15750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                    return;
15850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            }
15950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            sendMessage(msg);
16050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
16150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    };
16250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
16350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
16450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Device state monitor constructor. Note that each phone object should have its own device
16550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * state monitor, meaning there will be two device monitors on the multi-sim device.
16650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
16750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param phone Phone object
16850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
16950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    public DeviceStateMonitor(Phone phone) {
17050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mPhone = phone;
17150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        DisplayManager dm = (DisplayManager) phone.getContext().getSystemService(
17250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                Context.DISPLAY_SERVICE);
17350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        dm.registerDisplayListener(mDisplayListener, null);
17450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
17550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mIsPowerSaveOn = isPowerSaveModeOn();
17650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mIsCharging = isDeviceCharging();
177f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        mIsScreenOn = isScreenOn();
17850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        // Assuming tethering is always off after boot up.
17950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mIsTetheringOn = false;
18050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mIsLowDataExpected = false;
18150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
182f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        log("DeviceStateMonitor mIsPowerSaveOn=" + mIsPowerSaveOn + ",mIsScreenOn="
183f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                + mIsScreenOn + ",mIsCharging=" + mIsCharging, false);
18450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
18550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        final IntentFilter filter = new IntentFilter();
18650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
18750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        filter.addAction(BatteryManager.ACTION_CHARGING);
18850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        filter.addAction(BatteryManager.ACTION_DISCHARGING);
18950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        filter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
19050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mPhone.getContext().registerReceiver(mBroadcastReceiver, filter, null, mPhone);
19150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
19250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mPhone.mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
19350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
19450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
19550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
19650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return True if low data is expected
19750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
19850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean isLowDataExpected() {
199f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        return mIsPowerSaveOn || (!mIsCharging && !mIsTetheringOn && !mIsScreenOn);
20050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
20150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
20250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
20350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return True if signal strength update should be turned off.
20450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
20550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean shouldTurnOffSignalStrength() {
206f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        return mIsPowerSaveOn || (!mIsCharging && !mIsScreenOn);
20750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
20850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
20950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
21050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return True if full network update should be turned off. Only significant changes will
21150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * trigger the network update unsolicited response.
21250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
21350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean shouldTurnOffFullNetworkUpdate() {
214f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        return mIsPowerSaveOn || (!mIsCharging && !mIsScreenOn && !mIsTetheringOn);
21550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
21650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
21750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
21850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return True if data dormancy status update should be turned off.
21950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
22050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean shouldTurnOffDormancyUpdate() {
221f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        return mIsPowerSaveOn || (!mIsCharging && !mIsTetheringOn && !mIsScreenOn);
22250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
22350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
22450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
22550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Message handler
22650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
22750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param msg The message
22850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
22950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    @Override
23050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    public void handleMessage(Message msg) {
23150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        log("handleMessage msg=" + msg, false);
23250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        switch (msg.what) {
23350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case EVENT_RIL_CONNECTED:
23450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                onRilConnected();
23550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                break;
23650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            default:
23750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                updateDeviceState(msg.what, msg.arg1 != 0);
23850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
23950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
24050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
24150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
24250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Update the device and send the information to the modem.
24350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
24450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param eventType Device state event type
24550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param state True if enabled/on, otherwise disabled/off.
24650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
24750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private void updateDeviceState(int eventType, boolean state) {
24850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        switch (eventType) {
24950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case EVENT_SCREEN_STATE_CHANGED:
250f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                if (mIsScreenOn == state) return;
251f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                mIsScreenOn = state;
25250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                break;
25350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case EVENT_CHARGING_STATE_CHANGED:
25450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                if (mIsCharging == state) return;
25550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                mIsCharging = state;
25650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                sendDeviceState(CHARGING_STATE, mIsCharging);
25750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                break;
25850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case EVENT_TETHERING_STATE_CHANGED:
25950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                if (mIsTetheringOn == state) return;
26050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                mIsTetheringOn = state;
26150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                break;
26250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case EVENT_POWER_SAVE_MODE_CHANGED:
26350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                if (mIsPowerSaveOn == state) return;
26450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                mIsPowerSaveOn = state;
26550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn);
26650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                break;
26750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            default:
26850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                return;
26950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
27050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
27150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (mIsLowDataExpected != isLowDataExpected()) {
27250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            mIsLowDataExpected = !mIsLowDataExpected;
27350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            sendDeviceState(LOW_DATA_EXPECTED, mIsLowDataExpected);
27450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
27550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
27650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        int newFilter = 0;
27750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (!shouldTurnOffSignalStrength()) {
27850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            newFilter |= IndicationFilter.SIGNAL_STRENGTH;
27950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
28050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
28150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (!shouldTurnOffFullNetworkUpdate()) {
28250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            newFilter |= IndicationFilter.FULL_NETWORK_STATE;
28350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
28450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
28550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (!shouldTurnOffDormancyUpdate()) {
28650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            newFilter |= IndicationFilter.DATA_CALL_DORMANCY_CHANGED;
28750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
28850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
28950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        setUnsolResponseFilter(newFilter, false);
29050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
29150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
29250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
29350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Called when RIL is connected during boot up or reconnected after modem restart.
29450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
29550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * When modem crashes, if the user turns the screen off before RIL reconnects, device
29650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * state and filter cannot be sent to modem. Resend the state here so that modem
29750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * has the correct state (to stop signal strength reporting, etc).
29850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
29950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private void onRilConnected() {
30050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        log("RIL connected.", true);
30150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        sendDeviceState(CHARGING_STATE, mIsCharging);
30250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        sendDeviceState(LOW_DATA_EXPECTED, mIsLowDataExpected);
30350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        sendDeviceState(POWER_SAVE_MODE, mIsPowerSaveOn);
30450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        setUnsolResponseFilter(mUnsolicitedResponseFilter, true);
30550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
30650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
30750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
30850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Convert the device state type into string
30950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
31050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param type Device state type
31150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return The converted string
31250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
31350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private String deviceTypeToString(int type) {
31450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        switch (type) {
31550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case CHARGING_STATE: return "CHARGING_STATE";
31650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case LOW_DATA_EXPECTED: return "LOW_DATA_EXPECTED";
31750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            case POWER_SAVE_MODE: return "POWER_SAVE_MODE";
31850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            default: return "UNKNOWN";
31950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
32050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
32150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
32250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
32350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Send the device state to the modem.
32450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
32550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param type Device state type. See DeviceStateType defined in types.hal.
32650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param state True if enabled/on, otherwise disabled/off
32750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
32850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private void sendDeviceState(int type, boolean state) {
32950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        log("send type: " + deviceTypeToString(type) + ", state=" + state, true);
33050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mPhone.mCi.sendDeviceState(type, state, null);
33150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
33250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
33350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
33450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Turn on/off the unsolicited response from the modem.
33550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
33650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param newFilter See UnsolicitedResponseFilter in types.hal for the definition of each bit.
33750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param force Always set the filter when true.
33850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
33950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private void setUnsolResponseFilter(int newFilter, boolean force) {
34050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (force || newFilter != mUnsolicitedResponseFilter) {
34150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            log("old filter: " + mUnsolicitedResponseFilter + ", new filter: " + newFilter, true);
34250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            mPhone.mCi.setUnsolResponseFilter(newFilter, null);
34350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            mUnsolicitedResponseFilter = newFilter;
34450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
34550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
34650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
34750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
34850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return True if the device is currently in power save mode.
34950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * See {@link android.os.BatteryManager#isPowerSaveMode BatteryManager.isPowerSaveMode()}.
35050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
35150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean isPowerSaveModeOn() {
35250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        final PowerManager pm = (PowerManager) mPhone.getContext().getSystemService(
35350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                Context.POWER_SERVICE);
35450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        return pm.isPowerSaveMode();
35550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
35650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
35750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
35850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @return Return true if the battery is currently considered to be charging. This means that
35950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * the device is plugged in and is supplying sufficient power that the battery level is
36050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * going up (or the battery is fully charged).
36150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * See {@link android.os.BatteryManager#isCharging BatteryManager.isCharging()}.
36250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
36350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean isDeviceCharging() {
36450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        final BatteryManager bm = (BatteryManager) mPhone.getContext().getSystemService(
36550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu                Context.BATTERY_SERVICE);
36650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        return bm.isCharging();
36750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
36850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
36950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
370f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu     * @return True if one the device's screen (e.g. main screen, wifi display, HDMI display, or
371f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu     *         Android auto, etc...) is on.
37250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
37350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private boolean isScreenOn() {
37450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        // Note that we don't listen to Intent.SCREEN_ON and Intent.SCREEN_OFF because they are no
37550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        // longer adequate for monitoring the screen state since they are not sent in cases where
37650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        // the screen is turned off transiently such as due to the proximity sensor.
377f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        final DisplayManager dm = (DisplayManager) mPhone.getContext().getSystemService(
378f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                Context.DISPLAY_SERVICE);
379f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        Display[] displays = dm.getDisplays();
380f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu
381f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        if (displays != null) {
382f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu            for (Display display : displays) {
383f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                // Anything other than STATE_ON is treated as screen off, such as STATE_DOZE,
384f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                // STATE_DOZE_SUSPEND, etc...
385f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                if (display.getState() == Display.STATE_ON) {
386f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                    log("Screen " + Display.typeToString(display.getType()) + " on", true);
387f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                    return true;
388f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu                }
389f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu            }
390f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu            log("Screens all off", true);
391f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu            return false;
392f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        }
39350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
394f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        log("No displays found", true);
395f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        return false;
39650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
39750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
39850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
39950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param msg Debug message
40050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param logIntoLocalLog True if log into the local log
40150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
40250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    private void log(String msg, boolean logIntoLocalLog) {
40350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (DBG) Rlog.d(TAG, msg);
40450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        if (logIntoLocalLog) {
40550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu            mLocalLog.log(msg);
40650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        }
40750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
40850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu
40950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    /**
41050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * Print the DeviceStateMonitor into the given stream.
41150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     *
41250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param fd The raw file descriptor that the dump is being sent to.
41350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param pw A PrintWriter to which the dump is to be set.
41450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     * @param args Additional arguments to the dump request.
41550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu     */
41650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
41750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
41850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.increaseIndent();
41950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.println("mIsTetheringOn=" + mIsTetheringOn);
420f15cc290d7fb870ed5a1c7a0824bf6177f234f62Jack Yu        ipw.println("mIsScreenOn=" + mIsScreenOn);
42150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.println("mIsCharging=" + mIsCharging);
42250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.println("mIsPowerSaveOn=" + mIsPowerSaveOn);
42350b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.println("mIsLowDataExpected=" + mIsLowDataExpected);
42450b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.println("mUnsolicitedResponseFilter=" + mUnsolicitedResponseFilter);
42550b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.println("Local logs:");
42650b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.increaseIndent();
42750b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        mLocalLog.dump(fd, ipw, args);
42850b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.decreaseIndent();
42950b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.decreaseIndent();
43050b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu        ipw.flush();
43150b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu    }
43250b941e59787a21dd2d4f3d25d700538efb9abc5Jack Yu}
433