1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.doze;
18 
19 import android.hardware.display.AmbientDisplayConfiguration;
20 import android.util.Log;
21 
22 import com.android.systemui.dock.DockManager;
23 import com.android.systemui.doze.DozeMachine.State;
24 import com.android.systemui.doze.dagger.DozeScope;
25 import com.android.systemui.settings.UserTracker;
26 
27 import java.io.PrintWriter;
28 
29 import javax.inject.Inject;
30 
31 /**
32  * Handles dock events for ambient state changes.
33  */
34 @DozeScope
35 public class DozeDockHandler implements DozeMachine.Part {
36 
37     private static final String TAG = "DozeDockHandler";
38     private static final boolean DEBUG = DozeService.DEBUG;
39 
40     private final AmbientDisplayConfiguration mConfig;
41     private DozeMachine mMachine;
42     private final DockManager mDockManager;
43     private final UserTracker mUserTracker;
44     private final DockEventListener mDockEventListener;
45 
46     private int mDockState = DockManager.STATE_NONE;
47 
48     @Inject
DozeDockHandler(AmbientDisplayConfiguration config, DockManager dockManager, UserTracker userTracker)49     DozeDockHandler(AmbientDisplayConfiguration config, DockManager dockManager,
50             UserTracker userTracker) {
51         mConfig = config;
52         mDockManager = dockManager;
53         mUserTracker = userTracker;
54         mDockEventListener = new DockEventListener();
55     }
56 
57     @Override
setDozeMachine(DozeMachine dozeMachine)58     public void setDozeMachine(DozeMachine dozeMachine) {
59         mMachine = dozeMachine;
60     }
61 
62     @Override
transitionTo(DozeMachine.State oldState, DozeMachine.State newState)63     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
64         switch (newState) {
65             case INITIALIZED:
66                 mDockEventListener.register();
67                 break;
68             case FINISH:
69                 mDockEventListener.unregister();
70                 break;
71             default:
72                 // no-op
73         }
74     }
75 
76     @Override
dump(PrintWriter pw)77     public void dump(PrintWriter pw) {
78         pw.println("DozeDockHandler:");
79         pw.println(" dockState=" + mDockState);
80     }
81 
82     private class DockEventListener implements DockManager.DockEventListener {
83         private boolean mRegistered;
84 
85         @Override
onEvent(int dockState)86         public void onEvent(int dockState) {
87             if (DEBUG) Log.d(TAG, "dock event = " + dockState);
88 
89             // Only act upon state changes, otherwise we might overwrite other transitions,
90             // like proximity sensor initialization.
91             if (mDockState == dockState) {
92                 return;
93             }
94 
95             mDockState = dockState;
96             if (mMachine.isExecutingTransition() || isPulsing()) {
97                 // If the device is in the middle of executing a transition or is pulsing,
98                 // exit early instead of requesting a new state. DozeMachine
99                 // will check the docked state and resolveIntermediateState in the next
100                 // transition after pulse done.
101                 return;
102             }
103 
104             DozeMachine.State nextState;
105             switch (mDockState) {
106                 case DockManager.STATE_DOCKED:
107                     nextState = State.DOZE_AOD_DOCKED;
108                     break;
109                 case DockManager.STATE_NONE:
110                     nextState = mConfig.alwaysOnEnabled(mUserTracker.getUserId()) ? State.DOZE_AOD
111                             : State.DOZE;
112                     break;
113                 case DockManager.STATE_DOCKED_HIDE:
114                     nextState = State.DOZE;
115                     break;
116                 default:
117                     return;
118             }
119             mMachine.requestState(nextState);
120         }
121 
isPulsing()122         private boolean isPulsing() {
123             DozeMachine.State state = mMachine.getState();
124             return state == State.DOZE_REQUEST_PULSE || state == State.DOZE_PULSING
125                     || state == State.DOZE_PULSING_BRIGHT;
126         }
127 
register()128         void register() {
129             if (mRegistered) {
130                 return;
131             }
132             if (mDockManager != null) {
133                 mDockManager.addListener(this);
134             }
135             mRegistered = true;
136         }
137 
unregister()138         void unregister() {
139             if (!mRegistered) {
140                 return;
141             }
142             if (mDockManager != null) {
143                 mDockManager.removeListener(this);
144             }
145             mRegistered = false;
146         }
147     }
148 }
149