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 static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; 23 24 import android.content.Context; 25 import android.content.Intent; 26 27 import androidx.annotation.VisibleForTesting; 28 29 import com.android.launcher3.dagger.ApplicationContext; 30 import com.android.launcher3.dagger.LauncherAppSingleton; 31 import com.android.launcher3.dagger.LauncherBaseAppComponent; 32 33 import java.util.concurrent.CopyOnWriteArrayList; 34 35 import javax.inject.Inject; 36 37 /** 38 * Utility class for tracking if the screen is currently on or off 39 */ 40 @LauncherAppSingleton 41 public class ScreenOnTracker implements SafeCloseable { 42 43 public static final DaggerSingletonObject<ScreenOnTracker> INSTANCE = 44 new DaggerSingletonObject<>(LauncherBaseAppComponent::getScreenOnTracker); 45 46 private final SimpleBroadcastReceiver mReceiver; 47 private final CopyOnWriteArrayList<ScreenOnListener> mListeners = new CopyOnWriteArrayList<>(); 48 49 private boolean mIsScreenOn; 50 51 @Inject ScreenOnTracker(@pplicationContext Context context, DaggerSingletonTracker tracker)52 ScreenOnTracker(@ApplicationContext Context context, DaggerSingletonTracker tracker) { 53 // Assume that the screen is on to begin with 54 mReceiver = new SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR, this::onReceive); 55 init(tracker); 56 } 57 58 @VisibleForTesting ScreenOnTracker(@pplicationContext Context context, SimpleBroadcastReceiver receiver, DaggerSingletonTracker tracker)59 ScreenOnTracker(@ApplicationContext Context context, SimpleBroadcastReceiver receiver, 60 DaggerSingletonTracker tracker) { 61 mReceiver = receiver; 62 init(tracker); 63 } 64 init(DaggerSingletonTracker tracker)65 private void init(DaggerSingletonTracker tracker) { 66 mIsScreenOn = true; 67 mReceiver.register(ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT); 68 tracker.addCloseable(this); 69 } 70 71 @Override close()72 public void close() { 73 mReceiver.unregisterReceiverSafely(); 74 } 75 76 @VisibleForTesting onReceive(Intent intent)77 void onReceive(Intent intent) { 78 String action = intent.getAction(); 79 if (ACTION_SCREEN_ON.equals(action)) { 80 mIsScreenOn = true; 81 dispatchScreenOnChanged(); 82 } else if (ACTION_SCREEN_OFF.equals(action)) { 83 mIsScreenOn = false; 84 dispatchScreenOnChanged(); 85 } else if (ACTION_USER_PRESENT.equals(action)) { 86 mListeners.forEach(ScreenOnListener::onUserPresent); 87 } 88 } 89 dispatchScreenOnChanged()90 private void dispatchScreenOnChanged() { 91 mListeners.forEach(l -> l.onScreenOnChanged(mIsScreenOn)); 92 } 93 94 /** Returns if the screen is on or not */ isScreenOn()95 public boolean isScreenOn() { 96 return mIsScreenOn; 97 } 98 99 /** Adds a listener for screen on changes */ addListener(ScreenOnListener listener)100 public void addListener(ScreenOnListener listener) { 101 mListeners.add(listener); 102 } 103 104 /** Removes a previously added listener */ removeListener(ScreenOnListener listener)105 public void removeListener(ScreenOnListener listener) { 106 mListeners.remove(listener); 107 } 108 109 /** 110 * Interface to listen for screen on changes 111 */ 112 public interface ScreenOnListener { 113 114 /** 115 * Called when the screen turns on/off 116 */ onScreenOnChanged(boolean isOn)117 void onScreenOnChanged(boolean isOn); 118 119 /** 120 * Called when the keyguard goes away 121 */ onUserPresent()122 default void onUserPresent() { } 123 } 124 } 125