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,
76c7fd69699058e9b7f0601aca9275b597e8f62736Adrian 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,
878443dd0e7680e489509e8a9bf0bb5fcefd7a8c3ejackqdyulei                config, wakeLock, this::onSensor, this::onProximityFar,
888443dd0e7680e489509e8a9bf0bb5fcefd7a8c3ejackqdyulei                new AlwaysOnDisplayPolicy(context));
89ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mUiModeManager = mContext.getSystemService(UiModeManager.class);
90ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
91ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
92ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void onNotification() {
93ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        if (DozeMachine.DEBUG) Log.d(TAG, "requestNotificationPulse");
94ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mNotificationPulseTime = SystemClock.elapsedRealtime();
95ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
96ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
97181c320ee4b464244296ceddfbce7c0503110d03Adrian Roos        DozeLog.traceNotificationPulse(mContext);
98ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
99ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
100ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void onWhisper() {
101ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
102ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
103ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
104d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos    private void proximityCheckThenCall(IntConsumer callback,
105d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            boolean alreadyPerformedProxCheck,
106d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            int pulseReason) {
10770da03adbdb6fc06b1ff5ad5decf36d55d749e84Adrian Roos        Boolean cachedProxFar = mDozeSensors.isProximityCurrentlyFar();
108d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        if (alreadyPerformedProxCheck) {
109d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            callback.accept(ProximityCheck.RESULT_NOT_CHECKED);
11070da03adbdb6fc06b1ff5ad5decf36d55d749e84Adrian Roos        } else if (cachedProxFar != null) {
11170da03adbdb6fc06b1ff5ad5decf36d55d749e84Adrian Roos            callback.accept(cachedProxFar ? ProximityCheck.RESULT_FAR : ProximityCheck.RESULT_NEAR);
112d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        } else {
113d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            final long start = SystemClock.uptimeMillis();
114d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            new ProximityCheck() {
115d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                @Override
116d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                public void onProximityResult(int result) {
117d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    final long end = SystemClock.uptimeMillis();
118d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    DozeLog.traceProximityResult(mContext, result == RESULT_NEAR,
119d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                            end - start, pulseReason);
120d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    callback.accept(result);
121d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                }
122d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            }.check();
123d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        }
124d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos    }
125d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos
12625c7a58f33c7c24e59f522b86e3cf064fdfd3b8cAdrian Roos    private void onSensor(int pulseReason, boolean sensorPerformedProxCheck,
12725c7a58f33c7c24e59f522b86e3cf064fdfd3b8cAdrian Roos            float screenX, float screenY) {
128ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        boolean isDoubleTap = pulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
129ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        boolean isPickup = pulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP;
130d0963a07d148426d7b872862697ae1ca538a834bAdrian Roos        boolean isLongPress = pulseReason == DozeLog.PULSE_REASON_SENSOR_LONG_PRESS;
131ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
132d0963a07d148426d7b872862697ae1ca538a834bAdrian Roos        if (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) && !isLongPress) {
133d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            proximityCheckThenCall((result) -> {
134d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                if (result == ProximityCheck.RESULT_NEAR) {
135d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    // In pocket, drop event.
136d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    return;
137d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                }
138d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                if (isDoubleTap) {
139d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    mDozeHost.onDoubleTap(screenX, screenY);
140d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    mMachine.wakeUp();
141d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                } else {
142d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                    mDozeHost.extendPulse();
143d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                }
144d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            }, sensorPerformedProxCheck, pulseReason);
145d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            return;
146ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        } else {
147ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos            requestPulse(pulseReason, sensorPerformedProxCheck);
148ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        }
149ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos
150ed85e58656685f0ac28be7678db61edc88cd95e7Adrian Roos        if (isPickup) {
151ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            final long timeSinceNotification =
152ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    SystemClock.elapsedRealtime() - mNotificationPulseTime;
153ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            final boolean withinVibrationThreshold =
154ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
155ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
156ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
157ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
158ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
15967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos    private void onProximityFar(boolean far) {
16067cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        final boolean near = !far;
1616023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        final DozeMachine.State state = mMachine.getState();
162c7fd69699058e9b7f0601aca9275b597e8f62736Adrian Roos        final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
163c7fd69699058e9b7f0601aca9275b597e8f62736Adrian Roos        final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
164c7fd69699058e9b7f0601aca9275b597e8f62736Adrian Roos        final boolean aod = (state == DozeMachine.State.DOZE_AOD);
1656023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos
166a6c03f8d27cf6239e318e815dd12e2eed5d300a4Adrian Roos        if (state == DozeMachine.State.DOZE_PULSING) {
167a6c03f8d27cf6239e318e815dd12e2eed5d300a4Adrian Roos            boolean ignoreTouch = near;
168a6c03f8d27cf6239e318e815dd12e2eed5d300a4Adrian Roos            if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
169a6c03f8d27cf6239e318e815dd12e2eed5d300a4Adrian Roos            mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch);
17067cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        }
171c7fd69699058e9b7f0601aca9275b597e8f62736Adrian Roos        if (far && (paused || pausing)) {
17267cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
17367cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mMachine.requestState(DozeMachine.State.DOZE_AOD);
1746023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos        } else if (near && aod) {
17567cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
1766023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos            mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
17767cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        }
17867cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos    }
17967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos
180ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    @Override
181ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
182ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        switch (newState) {
183ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case INITIALIZED:
184ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mBroadcastReceiver.register(mContext);
185ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeHost.addCallback(mHostCallback);
186ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                checkTriggersAtInit();
187ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                break;
188ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case DOZE:
189ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case DOZE_AOD:
19067cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
191ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (oldState != DozeMachine.State.INITIALIZED) {
192ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    mDozeSensors.reregisterAllSensors();
193ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                }
194e3ac6f853f5ef9a034ef4d8a8c66ac47f3b66188Adrian Roos                mDozeSensors.setListening(true);
195ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                break;
1965f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos            case DOZE_AOD_PAUSED:
1976023ccbea1568d8b22db82cac9bf7a03367d0a61Adrian Roos            case DOZE_AOD_PAUSING:
1985f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos                mDozeSensors.setProxListening(true);
1995f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos                mDozeSensors.setListening(false);
2005f7bee46e1561e293e646565be6851d86a6b7f1eAdrian Roos                break;
20167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            case DOZE_PULSING:
20298d3198b5ced6b371067d0ff6166aaffff1dd512Adrian Roos                mDozeSensors.setTouchscreenSensorsListening(false);
20367cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                mDozeSensors.setProxListening(true);
20467cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                break;
205ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            case FINISH:
206ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mBroadcastReceiver.unregister(mContext);
207ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeHost.removeCallback(mHostCallback);
208ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeSensors.setListening(false);
20967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                mDozeSensors.setProxListening(false);
210ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                break;
211ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            default:
212ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
213ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
214ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
215ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void checkTriggersAtInit() {
216f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos        if (mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR
217f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                || mDozeHost.isPowerSaveActive()
218710a0b13628be61899472959526fa5e6fbb06b1fAdrian Roos                || mDozeHost.isBlockingDoze()
219f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                || !mDozeHost.isProvisioned()) {
220f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos            mMachine.requestState(DozeMachine.State.FINISH);
221ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
222ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
223ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
224ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void requestPulse(final int reason, boolean performedProxCheck) {
225ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        Assert.isMainThread();
22667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        mDozeHost.extendPulse();
227f9d13f6d7a6fda22620cd4eab74ec98cafdbd147Adrian Roos        if (mPulsePending || !mAllowPulseTriggers || !canPulse()) {
228d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            if (mAllowPulseTriggers) {
229d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos                DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(),
230d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos                        mDozeHost.isPulsingBlocked());
231d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            }
232ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            return;
233ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
234ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
235ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mPulsePending = true;
236d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        proximityCheckThenCall((result) -> {
237d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            if (result == ProximityCheck.RESULT_NEAR) {
238d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                // in pocket, abort pulse
239d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                mPulsePending = false;
240d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos            } else {
241d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos                // not in pocket, continue pulsing
242ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                continuePulseRequest(reason);
243ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
244d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        }, !mDozeParameters.getProxCheckBeforePulse() || performedProxCheck, reason);
245ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
246ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
247ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private boolean canPulse() {
248ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        return mMachine.getState() == DozeMachine.State.DOZE
249ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                || mMachine.getState() == DozeMachine.State.DOZE_AOD;
250ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
251ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
252ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private void continuePulseRequest(int reason) {
253ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mPulsePending = false;
254ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        if (mDozeHost.isPulsingBlocked() || !canPulse()) {
255d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos            DozeLog.tracePulseDropped(mContext, mPulsePending, mMachine.getState(),
256d35d4ca69f06cc53c02036f418275c255dc6ed68Adrian Roos                    mDozeHost.isPulsingBlocked());
257ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            return;
258ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
259d7b9d10d569438968f75d2453c4293caf89774f2Adrian Roos        mMachine.requestPulse(reason);
260ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
261ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
262ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    @Override
263ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    public void dump(PrintWriter pw) {
264ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.print(" notificationPulseTime=");
265ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.println(Formatter.formatShortElapsedTime(mContext, mNotificationPulseTime));
266ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
267ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.print(" pulsePending="); pw.println(mPulsePending);
268ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        pw.println("DozeSensors:");
269ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        mDozeSensors.dump(pw);
270ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
271ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
272ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private abstract class ProximityCheck implements SensorEventListener, Runnable {
273ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private static final int TIMEOUT_DELAY_MS = 500;
274ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
275ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected static final int RESULT_UNKNOWN = 0;
276ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected static final int RESULT_NEAR = 1;
277ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected static final int RESULT_FAR = 2;
278d32b366a1752d1735cfe4b87058596d05fcf9588Adrian Roos        protected static final int RESULT_NOT_CHECKED = 3;
279ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
280ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private boolean mRegistered;
281ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private boolean mFinished;
282ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private float mMaxRange;
283ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
284ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        protected abstract void onProximityResult(int result);
285ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
286ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void check() {
287ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            Preconditions.checkState(!mFinished && !mRegistered);
288ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            final Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
289ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (sensor == null) {
290ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No sensor found");
291ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                finishWithResult(RESULT_UNKNOWN);
292ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                return;
293ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
294ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mDozeSensors.setDisableSensorsInterferingWithProximity(true);
295ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
296ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mMaxRange = sensor.getMaximumRange();
297ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_NORMAL, 0,
298ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    mHandler);
299ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mHandler.postDelayed(this, TIMEOUT_DELAY_MS);
300ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mWakeLock.acquire();
301ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mRegistered = true;
302ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
303ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
304ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
305ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onSensorChanged(SensorEvent event) {
306ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (event.values.length == 0) {
307ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: Event has no values!");
308ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                finishWithResult(RESULT_UNKNOWN);
309ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            } else {
310ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) {
311ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                    Log.d(TAG, "ProxCheck: Event: value=" + event.values[0] + " max=" + mMaxRange);
312ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                }
313ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                final boolean isNear = event.values[0] < mMaxRange;
314ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                finishWithResult(isNear ? RESULT_NEAR : RESULT_FAR);
315ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
316ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
317ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
318ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
319ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void run() {
320ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (DozeMachine.DEBUG) Log.d(TAG, "ProxCheck: No event received before timeout");
321ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            finishWithResult(RESULT_UNKNOWN);
322ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
323ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
324ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        private void finishWithResult(int result) {
325ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (mFinished) return;
326ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            boolean wasRegistered = mRegistered;
327ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (mRegistered) {
328ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mHandler.removeCallbacks(this);
329ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mSensorManager.unregisterListener(this);
330ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeSensors.setDisableSensorsInterferingWithProximity(false);
331ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mRegistered = false;
332ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
333ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            onProximityResult(result);
334ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (wasRegistered) {
335ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mWakeLock.release();
336ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
337ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            mFinished = true;
338ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
339ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
340ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
341ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onAccuracyChanged(Sensor sensor, int accuracy) {
342ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            // noop
343ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
344ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
345ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
346ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private class TriggerReceiver extends BroadcastReceiver {
34767cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos        private boolean mRegistered;
34867cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos
349ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
350ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onReceive(Context context, Intent intent) {
351ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (PULSE_ACTION.equals(intent.getAction())) {
352ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                if (DozeMachine.DEBUG) Log.d(TAG, "Received pulse intent");
353ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                requestPulse(DozeLog.PULSE_REASON_INTENT, false /* performedProxCheck */);
354ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
355ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
356f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                mMachine.requestState(DozeMachine.State.FINISH);
357ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
358ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
359ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos                mDozeSensors.onUserSwitched();
360ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
361ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
362ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
363ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void register(Context context) {
36467cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (mRegistered) {
36567cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                return;
36667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            }
367ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            IntentFilter filter = new IntentFilter(PULSE_ACTION);
368ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
369ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            filter.addAction(Intent.ACTION_USER_SWITCHED);
370ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            context.registerReceiver(this, filter);
37167cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mRegistered = true;
372ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
373ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
374ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void unregister(Context context) {
37567cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            if (!mRegistered) {
37667cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos                return;
37767cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            }
378ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            context.unregisterReceiver(this);
37967cca7442bfeffc0bace506a796cfdd39e5d511cAdrian Roos            mRegistered = false;
380ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
381ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    }
382ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
383ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    private DozeHost.Callback mHostCallback = new DozeHost.Callback() {
384ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
3854b820e4e5e0404adbf9f9678b79fa7e988e3e597Adrian Roos        public void onNotificationHeadsUp() {
386ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            onNotification();
387ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
388ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos
389ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        @Override
390ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        public void onPowerSaveChanged(boolean active) {
391ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            if (active) {
392f2d545e30717c09c39df36aa601cf39e44dcdc50Adrian Roos                mMachine.requestState(DozeMachine.State.FINISH);
393ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos            }
394ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos        }
395ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos    };
396ff2c4563cdee60576847e161678549bc501e8d84Adrian Roos}
397