1 /* 2 * Copyright (C) 2023 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 package com.android.launcher3.util; 17 18 import static android.content.Intent.ACTION_SCREEN_OFF; 19 import static android.content.Intent.ACTION_SCREEN_ON; 20 import static android.content.Intent.ACTION_USER_PRESENT; 21 22 import android.content.Context; 23 import android.content.Intent; 24 25 import java.util.concurrent.CopyOnWriteArrayList; 26 27 /** 28 * Utility class for tracking if the screen is currently on or off 29 */ 30 public class ScreenOnTracker implements SafeCloseable { 31 32 public static final MainThreadInitializedObject<ScreenOnTracker> INSTANCE = 33 new MainThreadInitializedObject<>(ScreenOnTracker::new); 34 35 private final SimpleBroadcastReceiver mReceiver = new SimpleBroadcastReceiver(this::onReceive); 36 private final CopyOnWriteArrayList<ScreenOnListener> mListeners = new CopyOnWriteArrayList<>(); 37 38 private final Context mContext; 39 private boolean mIsScreenOn; 40 ScreenOnTracker(Context context)41 private ScreenOnTracker(Context context) { 42 // Assume that the screen is on to begin with 43 mContext = context; 44 mIsScreenOn = true; 45 mReceiver.register(context, ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT); 46 } 47 48 @Override close()49 public void close() { 50 mReceiver.unregisterReceiverSafely(mContext); 51 } 52 onReceive(Intent intent)53 private void onReceive(Intent intent) { 54 String action = intent.getAction(); 55 if (ACTION_SCREEN_ON.equals(action)) { 56 mIsScreenOn = true; 57 dispatchScreenOnChanged(); 58 } else if (ACTION_SCREEN_OFF.equals(action)) { 59 mIsScreenOn = false; 60 dispatchScreenOnChanged(); 61 } else if (ACTION_USER_PRESENT.equals(action)) { 62 mListeners.forEach(ScreenOnListener::onUserPresent); 63 } 64 } 65 dispatchScreenOnChanged()66 private void dispatchScreenOnChanged() { 67 mListeners.forEach(l -> l.onScreenOnChanged(mIsScreenOn)); 68 } 69 70 /** Returns if the screen is on or not */ isScreenOn()71 public boolean isScreenOn() { 72 return mIsScreenOn; 73 } 74 75 /** Adds a listener for screen on changes */ addListener(ScreenOnListener listener)76 public void addListener(ScreenOnListener listener) { 77 mListeners.add(listener); 78 } 79 80 /** Removes a previously added listener */ removeListener(ScreenOnListener listener)81 public void removeListener(ScreenOnListener listener) { 82 mListeners.remove(listener); 83 } 84 85 /** 86 * Interface to listen for screen on changes 87 */ 88 public interface ScreenOnListener { 89 90 /** 91 * Called when the screen turns on/off 92 */ onScreenOnChanged(boolean isOn)93 void onScreenOnChanged(boolean isOn); 94 95 /** 96 * Called when the keyguard goes away 97 */ onUserPresent()98 default void onUserPresent() { } 99 } 100 } 101