• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.keyguard;
18 
19 import android.annotation.IntDef;
20 import android.app.IWallpaperManager;
21 import android.content.Context;
22 import android.content.res.Configuration;
23 import android.graphics.Point;
24 import android.os.Bundle;
25 import android.os.PowerManager;
26 import android.os.RemoteException;
27 import android.os.Trace;
28 import android.util.DisplayMetrics;
29 
30 import androidx.annotation.Nullable;
31 
32 import com.android.systemui.Dumpable;
33 import com.android.systemui.R;
34 import com.android.systemui.dagger.SysUISingleton;
35 
36 import java.io.FileDescriptor;
37 import java.io.PrintWriter;
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 
41 import javax.inject.Inject;
42 
43 /**
44  * Tracks the wakefulness lifecycle, including why we're waking or sleeping.
45  */
46 @SysUISingleton
47 public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observer> implements
48         Dumpable {
49 
50     @IntDef(prefix = { "WAKEFULNESS_" }, value = {
51             WAKEFULNESS_ASLEEP,
52             WAKEFULNESS_WAKING,
53             WAKEFULNESS_AWAKE,
54             WAKEFULNESS_GOING_TO_SLEEP,
55     })
56     @Retention(RetentionPolicy.SOURCE)
57     public @interface Wakefulness {}
58 
59     public static final int WAKEFULNESS_ASLEEP = 0;
60     public static final int WAKEFULNESS_WAKING = 1;
61     public static final int WAKEFULNESS_AWAKE = 2;
62     public static final int WAKEFULNESS_GOING_TO_SLEEP = 3;
63 
64     private final Context mContext;
65     private final DisplayMetrics mDisplayMetrics;
66 
67     @Nullable
68     private final IWallpaperManager mWallpaperManagerService;
69 
70     private int mWakefulness = WAKEFULNESS_AWAKE;
71 
72     private @PowerManager.WakeReason int mLastWakeReason = PowerManager.WAKE_REASON_UNKNOWN;
73 
74     @Nullable
75     private Point mLastWakeOriginLocation = null;
76 
77     private @PowerManager.GoToSleepReason int mLastSleepReason =
78             PowerManager.GO_TO_SLEEP_REASON_MIN;
79 
80     @Nullable
81     private Point mLastSleepOriginLocation = null;
82 
83     @Inject
WakefulnessLifecycle( Context context, @Nullable IWallpaperManager wallpaperManagerService)84     public WakefulnessLifecycle(
85             Context context,
86             @Nullable IWallpaperManager wallpaperManagerService) {
87         mContext = context;
88         mDisplayMetrics = context.getResources().getDisplayMetrics();
89         mWallpaperManagerService = wallpaperManagerService;
90     }
91 
getWakefulness()92     public @Wakefulness int getWakefulness() {
93         return mWakefulness;
94     }
95 
96     /**
97      * Returns the most recent reason the device woke up. This is one of PowerManager.WAKE_REASON_*.
98      */
getLastWakeReason()99     public @PowerManager.WakeReason int getLastWakeReason() {
100         return mLastWakeReason;
101     }
102 
103     /**
104      * Returns the most recent reason the device went to sleep up. This is one of
105      * PowerManager.GO_TO_SLEEP_REASON_*.
106      */
getLastSleepReason()107     public @PowerManager.GoToSleepReason int getLastSleepReason() {
108         return mLastSleepReason;
109     }
110 
dispatchStartedWakingUp(@owerManager.WakeReason int pmWakeReason)111     public void dispatchStartedWakingUp(@PowerManager.WakeReason int pmWakeReason) {
112         if (getWakefulness() == WAKEFULNESS_WAKING) {
113             return;
114         }
115         setWakefulness(WAKEFULNESS_WAKING);
116         mLastWakeReason = pmWakeReason;
117         updateLastWakeOriginLocation();
118 
119         if (mWallpaperManagerService != null) {
120             try {
121                 mWallpaperManagerService.notifyWakingUp(
122                         mLastWakeOriginLocation.x, mLastWakeOriginLocation.y, new Bundle());
123             } catch (RemoteException e) {
124                 e.printStackTrace();
125             }
126         }
127 
128         dispatch(Observer::onStartedWakingUp);
129     }
130 
dispatchFinishedWakingUp()131     public void dispatchFinishedWakingUp() {
132         if (getWakefulness() == WAKEFULNESS_AWAKE) {
133             return;
134         }
135         setWakefulness(WAKEFULNESS_AWAKE);
136         dispatch(Observer::onFinishedWakingUp);
137     }
138 
dispatchStartedGoingToSleep(@owerManager.GoToSleepReason int pmSleepReason)139     public void dispatchStartedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason) {
140         if (getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP) {
141             return;
142         }
143         setWakefulness(WAKEFULNESS_GOING_TO_SLEEP);
144         mLastSleepReason = pmSleepReason;
145         updateLastSleepOriginLocation();
146 
147         if (mWallpaperManagerService != null) {
148             try {
149                 mWallpaperManagerService.notifyGoingToSleep(
150                         mLastSleepOriginLocation.x, mLastSleepOriginLocation.y, new Bundle());
151             } catch (RemoteException e) {
152                 e.printStackTrace();
153             }
154         }
155 
156         dispatch(Observer::onStartedGoingToSleep);
157     }
158 
dispatchFinishedGoingToSleep()159     public void dispatchFinishedGoingToSleep() {
160         if (getWakefulness() == WAKEFULNESS_ASLEEP) {
161             return;
162         }
163         setWakefulness(WAKEFULNESS_ASLEEP);
164         dispatch(Observer::onFinishedGoingToSleep);
165     }
166 
167     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)168     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
169         pw.println("WakefulnessLifecycle:");
170         pw.println("  mWakefulness=" + mWakefulness);
171     }
172 
setWakefulness(@akefulness int wakefulness)173     private void setWakefulness(@Wakefulness int wakefulness) {
174         mWakefulness = wakefulness;
175         Trace.traceCounter(Trace.TRACE_TAG_APP, "wakefulness", wakefulness);
176     }
177 
updateLastWakeOriginLocation()178     private void updateLastWakeOriginLocation() {
179         mLastWakeOriginLocation = null;
180 
181         switch (mLastWakeReason) {
182             case PowerManager.WAKE_REASON_POWER_BUTTON:
183                 mLastWakeOriginLocation = getPowerButtonOrigin();
184                 break;
185             default:
186                 mLastWakeOriginLocation = getDefaultWakeSleepOrigin();
187                 break;
188         }
189     }
190 
updateLastSleepOriginLocation()191     private void updateLastSleepOriginLocation() {
192         mLastSleepOriginLocation = null;
193 
194         switch (mLastSleepReason) {
195             case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
196                 mLastSleepOriginLocation = getPowerButtonOrigin();
197                 break;
198             default:
199                 mLastSleepOriginLocation = getDefaultWakeSleepOrigin();
200                 break;
201         }
202     }
203 
204     /**
205      * Returns the point on the screen closest to the physical power button.
206      */
getPowerButtonOrigin()207     private Point getPowerButtonOrigin() {
208         final boolean isPortrait = mContext.getResources().getConfiguration().orientation
209                 == Configuration.ORIENTATION_PORTRAIT;
210 
211         if (isPortrait) {
212             return new Point(
213                     mDisplayMetrics.widthPixels,
214                     mContext.getResources().getDimensionPixelSize(
215                             R.dimen.physical_power_button_center_screen_location_y));
216         } else {
217             return new Point(
218                     mContext.getResources().getDimensionPixelSize(
219                             R.dimen.physical_power_button_center_screen_location_y),
220                     mDisplayMetrics.heightPixels);
221         }
222     }
223 
224     /**
225      * Returns the point on the screen used as the default origin for wake/sleep events. This is the
226      * middle-bottom of the screen.
227      */
getDefaultWakeSleepOrigin()228     private Point getDefaultWakeSleepOrigin() {
229         return new Point(mDisplayMetrics.widthPixels / 2, mDisplayMetrics.heightPixels);
230     }
231 
232     public interface Observer {
onStartedWakingUp()233         default void onStartedWakingUp() {}
onFinishedWakingUp()234         default void onFinishedWakingUp() {}
onStartedGoingToSleep()235         default void onStartedGoingToSleep() {}
onFinishedGoingToSleep()236         default void onFinishedGoingToSleep() {}
237     }
238 }
239