DozeTriggers.java revision d0963a07d148426d7b872862697ae1ca538a834b
1ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos/*
2ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Copyright (C) 2016 The Android Open Source Project
3ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos *
4ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License");
5ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * you may not use this file except in compliance with the License.
6ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * You may obtain a copy of the License at
7ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos *
8ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos *      http://www.apache.org/licenses/LICENSE-2.0
9ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos *
10ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Unless required by applicable law or agreed to in writing, software
11ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS,
12ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * See the License for the specific language governing permissions and
14ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * limitations under the License.
15ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos */
16ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
17ff2c4563cdee60576847e161678549bc501e8d84Adrian Roospackage com.android.systemui.doze;
18ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
196023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roosimport android.app.AlarmManager;
20ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.app.UiModeManager;
21ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.content.BroadcastReceiver;
22ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.content.Context;
23ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.content.Intent;
24ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.content.IntentFilter;
25ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.content.res.Configuration;
26ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.hardware.Sensor;
27ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.hardware.SensorEvent;
28ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.hardware.SensorEventListener;
29ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.hardware.SensorManager;
30ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.os.Handler;
31ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.os.SystemClock;
32ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.os.UserHandle;
33ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.text.format.Formatter;
34ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport android.util.Log;
35ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
36ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport com.android.internal.hardware.AmbientDisplayConfiguration;
37ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport com.android.internal.util.Preconditions;
38ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport com.android.systemui.statusbar.phone.DozeParameters;
39ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport com.android.systemui.util.Assert;
40c1b50324a2286b24b691b8a7190743cbc341727eAdrian Roosimport com.android.systemui.util.wakelock.WakeLock;
41ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
42ff2c4563cdee60576847e161678549bc501e8d84Adrian Roosimport java.io.PrintWriter;
43d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roosimport java.util.function.IntConsumer;
44ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
45ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos/**
46ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos * Handles triggers for ambient state changes.
47ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos */
48ff2c4563cdee60576847e161678549bc501e8d84Adrian Roospublic class DozeTriggers implements DozeMachine.Part {
49ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
50ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private static final String TAG = "DozeTriggers";
5167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos    private static final boolean DEBUG = DozeService.DEBUG;
52ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
53ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    /** adb shell am broadcast -a com.android.systemui.doze.pulse com.android.systemui */
54ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private static final String PULSE_ACTION = "com.android.systemui.doze.pulse";
55ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
56ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final Context mContext;
57ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final DozeMachine mMachine;
58ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final DozeSensors mDozeSensors;
59ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final DozeHost mDozeHost;
60ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final AmbientDisplayConfiguration mConfig;
61ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final DozeParameters mDozeParameters;
62ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final SensorManager mSensorManager;
63ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final Handler mHandler;
64c1b50324a2286b24b691b8a7190743cbc341727eAdrian Roos    private final WakeLock mWakeLock;
65f9d13f6d7a6fda22620cd4eab74ec98cafdbd147Adrian Roos    private final boolean mAllowPulseTriggers;
66ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final UiModeManager mUiModeManager;
67ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
68ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
69ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private long mNotificationPulseTime;
70ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private boolean mPulsePending;
71ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
72ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
73ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
746023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos            AlarmManager alarmManager, AmbientDisplayConfiguration config,
75ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
76c1b50324a2286b24b691b8a7190743cbc341727eAdrian Roos            WakeLock wakeLock, boolean allowPulseTriggers) {
77ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mContext = context;
78ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mMachine = machine;
79ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mDozeHost = dozeHost;
80ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mConfig = config;
81ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mDozeParameters = dozeParameters;
82ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mSensorManager = sensorManager;
83ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mHandler = handler;
84ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mWakeLock = wakeLock;
85f9d13f6d7a6fda22620cd4eab74ec98cafdbd147Adrian Roos        mAllowPulseTriggers = allowPulseTriggers;
866023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        mDozeSensors = new DozeSensors(context, alarmManager, mSensorManager, dozeParameters,
876023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos                config, wakeLock, this::onSensor, this::onProximityFar);
88ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mUiModeManager = mContext.getSystemService(UiModeManager.class);
89ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
90ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
91ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void onNotification() {
92ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        if (DozeMachine.DEBUG) Log.d(TAG, "requestNotificationPulse");
93ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mNotificationPulseTime = SystemClock.elapsedRealtime();
94ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
95ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
96181c320ee4b464244296ceddfbce7c0503110d03Adrian Roos        DozeLog.traceNotificationPulse(mContext);
97ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
98ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
99ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void onWhisper() {
100ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
101ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
102ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
103d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos    private void proximityCheckThenCall(IntConsumer callback,
104d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            boolean alreadyPerformedProxCheck,
105d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            int pulseReason) {
106d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        if (alreadyPerformedProxCheck) {
107d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            callback.accept(ProximityCheck.RESULT_NOT_CHECKED);
108d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        } else {
109d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            final long start = SystemClock.uptimeMillis();
110d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            new ProximityCheck() {
111d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                @Override
112d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                public void onProximityResult(int result) {
113d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    final long end = SystemClock.uptimeMillis();
114d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
115d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                            end - start, pulseReason);
116d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    callback.accept(result);
117d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                }
118d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            }.check();
119d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        }
120d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos    }
121d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos
12225c7a58f33c7c24e59f522b86e3cf064fdfd3b8cAdrian Roos    private void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
12325c7a58f33c7c24e59f522b86e3cf064fdfd3b8cAdrian Roos            float screenX, float screenY) {
124ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
125ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
126d0963a07d148426d7b872862697ae1ca538a834bAdrian Roos        boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
127ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
128d0963a07d148426d7b872862697ae1ca538a834bAdrian Roos        if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) && !isLongPress) {
129d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            proximityCheckThenCall((result) -> {
130d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                if (result == ProximityCheck.RESULT_NEAR) {
131d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    // In pocket, drop event.
132d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    return;
133d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                }
134d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                if (isDoubleTap) {
135d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    mDozeHost.onDoubleTap(screenX, screenY);
136d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    mMachine.wakeUp();
137d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                } else {
138d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    mDozeHost.extendPulse();
139d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                }
140d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            }, sensorPerformedProxCheck, pulseReason);
141d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            return;
142ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        } else {
143ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos            requestPulse(pulseReason, sensorPerformedProxCheck);
144ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        }
145ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos
146ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        if (isPickup) {
147ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            final long timeSinceNotification =
148ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    SystemClock.elapsedRealtime() - mNotificationPulseTime;
149ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            final boolean withinVibrationThreshold =
150ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
151ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
152ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
153ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
154ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
15567cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos    private void onProximityFar(boolean far) {
15667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        final boolean near = !far;
1576023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        final DozeMachine.State state = mMachine.getState();
1586023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
1596023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
1606023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        final boolean aod = (state == DozeMachine.State.DOZE_AOD);
1616023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos
16267cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        if (near && state == DozeMachine.State.DOZE_PULSING) {
16367cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (DEBUG) Log.i(TAG, "Prox NEAR, ending pulse");
164d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            DozeLog.tracePulseCanceledByProx(mContext);
16567cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mMachine.requestState(DozeMachine.State.DOZE_PULSE_DONE);
16667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        }
1676023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        if (far && (paused || pausing)) {
16867cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
16967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mMachine.requestState(DozeMachine.State.DOZE_AOD);
1706023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        } else if (near && aod) {
17167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
1726023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos            mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
17367cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        }
17467cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos    }
17567cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos
176ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    @Override
177ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
178ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        switch (newState) {
179ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case INITIALIZED:
180ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mBroadcastReceiver.register(mContext);
181ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeHost.addCallback(mHostCallback);
182ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                checkTriggersAtInit();
183ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                break;
184ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case DOZE:
185ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case DOZE_AOD:
18667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
187ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (oldState != DozeMachine.State.INITIALIZED) {
188ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    mDozeSensors.reregisterAllSensors();
189ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                }
190e3ac6f853f5ef9a034ef4d8a8c66ac47f3b66188Adrian Roos                mDozeSensors.setListening(true);
191ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                break;
1925f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos            case DOZE_AOD_PAUSED:
1936023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos            case DOZE_AOD_PAUSING:
1945f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos                mDozeSensors.setProxListening(true);
1955f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos                mDozeSensors.setListening(false);
1965f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos                break;
19767cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            case DOZE_PULSING:
19867cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                mDozeSensors.setProxListening(true);
19967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                break;
200ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case FINISH:
201ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mBroadcastReceiver.unregister(mContext);
202ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeHost.removeCallback(mHostCallback);
203ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeSensors.setListening(false);
20467cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                mDozeSensors.setProxListening(false);
205ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                break;
206ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            default:
207ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
208ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
209ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
210ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void checkTriggersAtInit() {
211f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos        if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
212f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                || mDozeHost.isPowerSaveActive()
213710a0b13628be61899472959526fa5e6fbb06b1fAdrian Roos                || mDozeHost.isBlockingDoze()
214f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                || !mDozeHost.isProvisioned()) {
215f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos            mMachine.requestState(DozeMachine.State.FINISH);
216ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
217ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
218ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
219ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void requestPulse(final int reason, boolean performedProxCheck) {
220ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        Assert.isMainThread();
22167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        mDozeHost.extendPulse();
222f9d13f6d7a6fda22620cd4eab74ec98cafdbd147Adrian Roos        if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
223d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            if (mAllowPulseTriggers) {
224d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos                DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(),
225d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos                        mDozeHost.isPulsingBlocked());
226d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            }
227ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            return;
228ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
229ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
230ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mPulsePending = true;
231d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        proximityCheckThenCall((result) -> {
232d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            if (result == ProximityCheck.RESULT_NEAR) {
233d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                // in pocket, abort pulse
234d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                mPulsePending = false;
235d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            } else {
236d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                // not in pocket, continue pulsing
237ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                continuePulseRequest(reason);
238ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
239d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        }, !mDozeParameters.getProxCheckBeforePulse() || performedProxCheck, reason);
240ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
241ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
242ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private boolean canPulse() {
243ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        return mMachine.getState() == DozeMachine.State.DOZE
244ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                || mMachine.getState() == DozeMachine.State.DOZE_AOD;
245ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
246ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
247ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void continuePulseRequest(int reason) {
248ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mPulsePending = false;
249ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        if (mDozeHost.isPulsingBlocked() || !canPulse()) {
250d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(),
251d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos                    mDozeHost.isPulsingBlocked());
252ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            return;
253ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
254d7b9d10d569438968f75d2453c4293caf89774f2Adrian Roos        mMachine.requestPulse(reason);
255ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
256ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
257ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    @Override
258ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    public void dump(PrintWriter pw) {
259ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.print(" notificationPulseTime=");
260ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.println(Formatter.formatShortElapsedTime(mContext, mNotificationPulseTime));
261ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
262ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.print(" pulsePending="); pw.println(mPulsePending);
263ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.println("DozeSensors:");
264ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mDozeSensors.dump(pw);
265ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
266ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
267ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private abstract class ProximityCheck implements SensorEventListener, Runnable {
268ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private static final int TIMEOUT_DELAY_MS = 500;
269ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
270ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected static final int RESULT_UNKNOWN = 0;
271ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected static final int RESULT_NEAR = 1;
272ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected static final int RESULT_FAR = 2;
273d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        protected static final int RESULT_NOT_CHECKED = 3;
274ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
275ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private boolean mRegistered;
276ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private boolean mFinished;
277ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private float mMaxRange;
278ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
279ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected abstract void onProximityResult(int result);
280ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
281ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void check() {
282ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            Preconditions.checkState(!mFinished && !mRegistered);
283ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
284ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (sensor == null) {
285ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No sensor found");
286ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                finishWithResult(RESULT_UNKNOWN);
287ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                return;
288ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
289ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mDozeSensors.setDisableSensorsInterferingWithProximity(true);
290ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
291ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mMaxRange = sensor.getMaximumRange();
292ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
293ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    mHandler);
294ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
295ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mWakeLock.acquire();
296ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mRegistered = true;
297ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
298ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
299ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
300ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onSensorChanged(SensorEvent event) {
301ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (event.values.length == 0) {
302ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: Event has no values!");
303ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                finishWithResult(RESULT_UNKNOWN);
304ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            } else {
305ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) {
306ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    Log.d(TAG, "ProxCheck: Event: value=" + event.values[0] + " max=" + mMaxRange);
307ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                }
308ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                final boolean isNear = event.values[0] < mMaxRange;
309ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
310ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
311ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
312ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
313ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
314ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void run() {
315ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No event received before timeout");
316ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            finishWithResult(RESULT_UNKNOWN);
317ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
318ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
319ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private void finishWithResult(int result) {
320ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (mFinished) return;
321ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            boolean wasRegistered = mRegistered;
322ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (mRegistered) {
323ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mHandler.removeCallbacks(this);
324ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mSensorManager.unregisterListener(this);
325ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeSensors.setDisableSensorsInterferingWithProximity(false);
326ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mRegistered = false;
327ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
328ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            onProximityResult(result);
329ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (wasRegistered) {
330ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mWakeLock.release();
331ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
332ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mFinished = true;
333ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
334ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
335ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
336ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onAccuracyChanged(Sensor sensor, int accuracy) {
337ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            // noop
338ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
339ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
340ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
341ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private class TriggerReceiver extends BroadcastReceiver {
34267cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        private boolean mRegistered;
34367cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos
344ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
345ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onReceive(Context context, Intent intent) {
346ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (PULSE_ACTION.equals(intent.getAction())) {
347ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent");
348ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                requestPulse(DozeLog.PULSE_REASON_INTENT, false /* performedProxCheck */);
349ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
350ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
351f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                mMachine.requestState(DozeMachine.State.FINISH);
352ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
353ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
354ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeSensors.onUserSwitched();
355ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
356ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
357ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
358ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void register(Context context) {
35967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (mRegistered) {
36067cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                return;
36167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            }
362ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            IntentFilter filter = new IntentFilter(PULSE_ACTION);
363ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
364ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            filter.addAction(Intent.ACTION_USER_SWITCHED);
365ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            context.registerReceiver(this, filter);
36667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mRegistered = true;
367ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
368ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
369ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void unregister(Context context) {
37067cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (!mRegistered) {
37167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                return;
37267cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            }
373ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            context.unregisterReceiver(this);
37467cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mRegistered = false;
375ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
376ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
377ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
378ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
379ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
3804b820e4e5e0404adbf9f9678b79fa7e988e3e597Adrian Roos        public void onNotificationHeadsUp() {
381ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            onNotification();
382ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
383ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
384ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
385ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onPowerSaveChanged(boolean active) {
386ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (active) {
387f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                mMachine.requestState(DozeMachine.State.FINISH);
388ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
389ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
390ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    };
391ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos}
392