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