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