diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java index fb2d0dcc3c..d8fd51a850 100644 --- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java +++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java @@ -18,6 +18,8 @@ package com.android.launcher3.model; import static android.content.ContentResolver.SCHEME_CONTENT; +import static com.android.launcher3.util.SimpleBroadcastReceiver.getPackageFilter; + import android.annotation.TargetApi; import android.app.RemoteAction; import android.content.ContentProviderClient; @@ -55,7 +57,6 @@ import com.android.launcher3.popup.RemoteActionShortcut; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.util.BgObjectWithLooper; import com.android.launcher3.util.MainThreadInitializedObject; -import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.SimpleBroadcastReceiver; @@ -117,7 +118,7 @@ public final class WellbeingModel extends BgObjectWithLooper { if (!TextUtils.isEmpty(mWellbeingProviderPkg)) { mContext.registerReceiver( new SimpleBroadcastReceiver(t -> restartObserver()), - PackageManagerHelper.getPackageFilter(mWellbeingProviderPkg, + getPackageFilter(mWellbeingProviderPkg, Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_PACKAGE_REMOVED, Intent.ACTION_PACKAGE_DATA_CLEARED, Intent.ACTION_PACKAGE_RESTARTED), diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java index 0808faba1c..edf4648e86 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java @@ -10,12 +10,10 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_S import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; import android.app.KeyguardManager; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.util.ScreenOnTracker; +import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener; import com.android.systemui.shared.system.QuickStepContract; import java.io.PrintWriter; @@ -30,6 +28,7 @@ public class TaskbarKeyguardController implements TaskbarControllers.LoggableTas SYSUI_STATE_OVERVIEW_DISABLED | SYSUI_STATE_HOME_DISABLED | SYSUI_STATE_BACK_DISABLED | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED; + private final ScreenOnListener mScreenOnListener; private final TaskbarActivityContext mContext; private int mKeyguardSysuiFlags; private boolean mBouncerShowing; @@ -37,22 +36,20 @@ public class TaskbarKeyguardController implements TaskbarControllers.LoggableTas private final KeyguardManager mKeyguardManager; private boolean mIsScreenOff; - private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - mIsScreenOff = true; - AbstractFloatingView.closeOpenViews(mContext, false, TYPE_ALL); - } - }; - public TaskbarKeyguardController(TaskbarActivityContext context) { mContext = context; + mScreenOnListener = isOn -> { + if (!isOn) { + mIsScreenOff = true; + AbstractFloatingView.closeOpenViews(mContext, false, TYPE_ALL); + } + }; mKeyguardManager = mContext.getSystemService(KeyguardManager.class); } public void init(NavbarButtonsViewController navbarButtonUIController) { mNavbarButtonsViewController = navbarButtonUIController; - mContext.registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); + ScreenOnTracker.INSTANCE.get(mContext).addListener(mScreenOnListener); } public void updateStateForSysuiFlags(int systemUiStateFlags) { @@ -104,7 +101,7 @@ public class TaskbarKeyguardController implements TaskbarControllers.LoggableTas } public void onDestroy() { - mContext.unregisterReceiver(mScreenOffReceiver); + ScreenOnTracker.INSTANCE.get(mContext).removeListener(mScreenOnListener); } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 078865fd02..0673dc6e9f 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -609,10 +609,12 @@ public class QuickstepLauncher extends Launcher { } @Override - protected void onScreenOff() { - super.onScreenOff(); - RecentsView recentsView = getOverviewPanel(); - recentsView.finishRecentsAnimation(true /* toRecents */, null); + protected void onScreenOnChanged(boolean isOn) { + super.onScreenOnChanged(isOn); + if (!isOn) { + RecentsView recentsView = getOverviewPanel(); + recentsView.finishRecentsAnimation(true /* toRecents */, null); + } } @Override diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java index 83f2a0a114..589459f5c6 100644 --- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java +++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java @@ -21,15 +21,12 @@ import static android.content.Intent.ACTION_PACKAGE_CHANGED; import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY; -import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter; import static com.android.systemui.shared.system.PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED; import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -57,9 +54,9 @@ import java.util.function.Consumer; public final class OverviewComponentObserver { private static final String TAG = "OverviewComponentObserver"; - private final BroadcastReceiver mUserPreferenceChangeReceiver = + private final SimpleBroadcastReceiver mUserPreferenceChangeReceiver = new SimpleBroadcastReceiver(this::updateOverviewTargets); - private final BroadcastReceiver mOtherHomeAppUpdateReceiver = + private final SimpleBroadcastReceiver mOtherHomeAppUpdateReceiver = new SimpleBroadcastReceiver(this::updateOverviewTargets); private final Context mContext; @@ -102,8 +99,7 @@ public final class OverviewComponentObserver { mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges); } catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ } - mContext.registerReceiver(mUserPreferenceChangeReceiver, - new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED)); + mUserPreferenceChangeReceiver.register(mContext, ACTION_PREFERRED_ACTIVITY_CHANGED); updateOverviewTargets(); } @@ -181,9 +177,8 @@ public final class OverviewComponentObserver { unregisterOtherHomeAppUpdateReceiver(); mUpdateRegisteredPackage = defaultHome.getPackageName(); - mContext.registerReceiver(mOtherHomeAppUpdateReceiver, getPackageFilter( - mUpdateRegisteredPackage, ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, - ACTION_PACKAGE_REMOVED)); + mOtherHomeAppUpdateReceiver.registerPkgActions(mContext, mUpdateRegisteredPackage, + ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REMOVED); } } mOverviewChangeListener.accept(mIsHomeAndOverviewSame); diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java index 28d4a9f7a8..49afc1f170 100644 --- a/src/com/android/launcher3/AbstractFloatingView.java +++ b/src/com/android/launcher3/AbstractFloatingView.java @@ -63,11 +63,13 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch TYPE_TASK_MENU, TYPE_OPTIONS_POPUP, TYPE_ICON_SURFACE, + TYPE_OPTIONS_POPUP_DIALOG, TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP, TYPE_WIDGETS_EDUCATION_DIALOG, TYPE_TASKBAR_EDUCATION_DIALOG, TYPE_TASKBAR_ALL_APPS, - TYPE_OPTIONS_POPUP_DIALOG + TYPE_ADD_TO_HOME_CONFIRMATION, + TYPE_TASKBAR_OVERLAY_PROXY }) @Retention(RetentionPolicy.SOURCE) public @interface FloatingViewType {} @@ -87,14 +89,14 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch public static final int TYPE_TASK_MENU = 1 << 11; public static final int TYPE_OPTIONS_POPUP = 1 << 12; public static final int TYPE_ICON_SURFACE = 1 << 13; - public static final int TYPE_OPTIONS_POPUP_DIALOG = 1 << 18; + public static final int TYPE_OPTIONS_POPUP_DIALOG = 1 << 14; - public static final int TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP = 1 << 14; - public static final int TYPE_WIDGETS_EDUCATION_DIALOG = 1 << 15; - public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 16; - public static final int TYPE_TASKBAR_ALL_APPS = 1 << 17; - public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 18; - public static final int TYPE_TASKBAR_OVERLAY_PROXY = 1 << 19; + public static final int TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP = 1 << 15; + public static final int TYPE_WIDGETS_EDUCATION_DIALOG = 1 << 16; + public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 17; + public static final int TYPE_TASKBAR_ALL_APPS = 1 << 18; + public static final int TYPE_ADD_TO_HOME_CONFIRMATION = 1 << 19; + public static final int TYPE_TASKBAR_OVERLAY_PROXY = 1 << 20; public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index af6935f616..de5419eb7b 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -76,11 +76,9 @@ import android.app.PendingIntent; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetManager; import android.content.ActivityNotFoundException; -import android.content.BroadcastReceiver; import android.content.ComponentCallbacks2; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.IntentSender; import android.content.SharedPreferences; import android.content.pm.PackageManager; @@ -198,6 +196,8 @@ import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.PendingRequestArgs; import com.android.launcher3.util.RunnableList; import com.android.launcher3.util.SafeCloseable; +import com.android.launcher3.util.ScreenOnTracker; +import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; import com.android.launcher3.util.Thunk; @@ -536,9 +536,8 @@ public class Launcher extends StatefulActivity } getRootView().dispatchInsets(); - // Listen for broadcasts - registerReceiver(mScreenOffReceiver, new IntentFilter(Intent.ACTION_SCREEN_OFF)); - + // Listen for screen turning off + ScreenOnTracker.INSTANCE.get(this).addListener(mScreenOnListener); getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); @@ -1476,12 +1475,7 @@ public class Launcher extends StatefulActivity hostView.setOnFocusChangeListener(mFocusHandler); } - private final BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - onScreenOff(); - } - }; + private final ScreenOnListener mScreenOnListener = this::onScreenOnChanged; private void updateNotificationDots(Predicate updatedDots) { mWorkspace.updateNotificationDots(updatedDots); @@ -1715,7 +1709,7 @@ public class Launcher extends StatefulActivity super.onDestroy(); ACTIVITY_TRACKER.onActivityDestroyed(this); - unregisterReceiver(mScreenOffReceiver); + ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener); mWorkspace.removeFolderListeners(); PluginManagerWrapper.INSTANCE.get(this).removePluginListener(this); @@ -2083,10 +2077,10 @@ public class Launcher extends StatefulActivity mStateManager.getState().onBackCancelled(this); } - protected void onScreenOff() { + protected void onScreenOnChanged(boolean isOn) { // Reset AllApps to its initial state only if we are not in the middle of // processing a multi-step drop - if (mPendingRequestArgs == null) { + if (!isOn && mPendingRequestArgs == null) { if (!isInState(NORMAL)) { onUiChangedWhileSleeping(); } diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 3461601f1d..2b98d983a6 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -102,7 +102,7 @@ public class LauncherAppState implements SafeCloseable { Intent.ACTION_MANAGED_PROFILE_UNLOCKED, ACTION_DEVICE_POLICY_RESOURCE_UPDATED); if (FeatureFlags.IS_STUDIO_BUILD) { - modelChangeReceiver.register(mContext, Context.RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD); + modelChangeReceiver.register(mContext, ACTION_FORCE_ROLOAD); } mOnTerminateCallback.add(() -> mContext.unregisterReceiver(modelChangeReceiver)); diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java index 185b8d3f44..11e7dc8630 100644 --- a/src/com/android/launcher3/graphics/SysUiScrim.java +++ b/src/com/android/launcher3/graphics/SysUiScrim.java @@ -16,17 +16,10 @@ package com.android.launcher3.graphics; -import static android.content.Intent.ACTION_SCREEN_OFF; -import static android.content.Intent.ACTION_USER_PRESENT; - import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION; import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; import android.animation.ObjectAnimator; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; @@ -43,10 +36,12 @@ import android.view.WindowInsets; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.R; -import com.android.launcher3.testing.shared.ResourceUtils; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.testing.shared.ResourceUtils; import com.android.launcher3.util.DynamicResource; +import com.android.launcher3.util.ScreenOnTracker; +import com.android.launcher3.util.ScreenOnTracker.ScreenOnListener; import com.android.launcher3.util.Themes; import com.android.systemui.plugins.ResourceProvider; @@ -85,18 +80,20 @@ public class SysUiScrim implements View.OnAttachStateChangeListener { /** * Receiver used to get a signal that the user unlocked their device. */ - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + private final ScreenOnListener mScreenOnListener = new ScreenOnListener() { @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (ACTION_SCREEN_OFF.equals(action)) { + public void onScreenOnChanged(boolean isOn) { + if (!isOn) { mAnimateScrimOnNextDraw = true; - } else if (ACTION_USER_PRESENT.equals(action)) { - // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where - // the user unlocked and the Launcher is not in the foreground. - mAnimateScrimOnNextDraw = false; } } + + @Override + public void onUserPresent() { + // ACTION_USER_PRESENT is sent after onStart/onResume. This covers the case where + // the user unlocked and the Launcher is not in the foreground. + mAnimateScrimOnNextDraw = false; + } }; private static final int MAX_HOTSEAT_SCRIM_ALPHA = 100; @@ -208,16 +205,14 @@ public class SysUiScrim implements View.OnAttachStateChangeListener { @Override public void onViewAttachedToWindow(View view) { if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) { - IntentFilter filter = new IntentFilter(ACTION_SCREEN_OFF); - filter.addAction(ACTION_USER_PRESENT); // When the device wakes up + keyguard is gone - mRoot.getContext().registerReceiver(mReceiver, filter); + ScreenOnTracker.INSTANCE.get(mActivity).addListener(mScreenOnListener); } } @Override public void onViewDetachedFromWindow(View view) { if (!KEYGUARD_ANIMATION.get() && mTopScrim != null) { - mRoot.getContext().unregisterReceiver(mReceiver); + ScreenOnTracker.INSTANCE.get(mActivity).removeListener(mScreenOnListener); } } diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java index c81214e67b..40fc16e9c2 100644 --- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java +++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java @@ -15,6 +15,9 @@ */ package com.android.launcher3.settings; +import static android.content.Intent.ACTION_PACKAGE_ADDED; +import static android.content.Intent.ACTION_PACKAGE_CHANGED; +import static android.content.Intent.ACTION_PACKAGE_REMOVED; import static android.content.pm.PackageManager.GET_RESOLVED_FILTER; import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS; import static android.view.View.GONE; @@ -25,11 +28,9 @@ import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.PLU import static com.android.launcher3.uioverrides.plugins.PluginManagerWrapper.pluginEnabledKey; import android.annotation.TargetApi; -import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -66,6 +67,7 @@ import com.android.launcher3.config.FlagTogglerPrefUi; import com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.util.OnboardingPrefs; +import com.android.launcher3.util.SimpleBroadcastReceiver; import java.util.ArrayList; import java.util.List; @@ -83,12 +85,8 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat { private static final String ACTION_PLUGIN_SETTINGS = "com.android.systemui.action.PLUGIN_SETTINGS"; private static final String PLUGIN_PERMISSION = "com.android.systemui.permission.PLUGIN"; - private final BroadcastReceiver mPluginReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - loadPluginPrefs(); - } - }; + private final SimpleBroadcastReceiver mPluginReceiver = + new SimpleBroadcastReceiver(i -> loadPluginPrefs()); private PreferenceScreen mPreferenceScreen; @@ -97,13 +95,9 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); - filter.addAction(Intent.ACTION_PACKAGE_CHANGED); - filter.addAction(Intent.ACTION_PACKAGE_REMOVED); - filter.addDataScheme("package"); - getContext().registerReceiver(mPluginReceiver, filter); - getContext().registerReceiver(mPluginReceiver, - new IntentFilter(Intent.ACTION_USER_UNLOCKED)); + mPluginReceiver.registerPkgActions(getContext(), null, + ACTION_PACKAGE_ADDED, ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REMOVED); + mPluginReceiver.register(getContext(), Intent.ACTION_USER_UNLOCKED); mPreferenceScreen = getPreferenceManager().createPreferenceScreen(getContext()); setPreferenceScreen(mPreferenceScreen); @@ -185,7 +179,7 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat { @Override public void onDestroy() { super.onDestroy(); - getContext().unregisterReceiver(mPluginReceiver); + mPluginReceiver.unregisterReceiverSafely(getContext()); } private PreferenceCategory newCategory(String title) { diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java index c52890fd18..9ed6700959 100644 --- a/src/com/android/launcher3/util/DisplayController.java +++ b/src/com/android/launcher3/util/DisplayController.java @@ -23,7 +23,6 @@ import static com.android.launcher3.Utilities.dpiFromPx; import static com.android.launcher3.config.FeatureFlags.ENABLE_TRANSIENT_TASKBAR; import static com.android.launcher3.config.FeatureFlags.FORCE_PERSISTENT_TASKBAR; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; -import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter; import static com.android.launcher3.util.window.WindowManagerProxy.MIN_TABLET_WIDTH; import android.annotation.SuppressLint; @@ -111,8 +110,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable { } // Initialize navigation mode change listener - mContext.registerReceiver(mReceiver, - getPackageFilter(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED)); + mReceiver.registerPkgActions(mContext, TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED); WindowManagerProxy wmProxy = WindowManagerProxy.INSTANCE.get(context); Context displayInfoContext = getDisplayInfoContext(display); diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 140440eee2..a6a2751dc7 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -21,7 +21,6 @@ import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; @@ -33,7 +32,6 @@ import android.graphics.Rect; import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.os.PatternMatcher; import android.os.UserHandle; import android.text.TextUtils; import android.util.Log; @@ -249,19 +247,6 @@ public class PackageManagerHelper { } } - /** - * Creates an intent filter to listen for actions with a specific package in the data field. - */ - public static IntentFilter getPackageFilter(String pkg, String... actions) { - IntentFilter packageFilter = new IntentFilter(); - for (String action : actions) { - packageFilter.addAction(action); - } - packageFilter.addDataScheme("package"); - packageFilter.addDataSchemeSpecificPart(pkg, PatternMatcher.PATTERN_LITERAL); - return packageFilter; - } - public static boolean isSystemApp(@NonNull final Context context, @NonNull final Intent intent) { PackageManager pm = context.getPackageManager(); diff --git a/src/com/android/launcher3/util/ScreenOnTracker.java b/src/com/android/launcher3/util/ScreenOnTracker.java new file mode 100644 index 0000000000..67530a6a47 --- /dev/null +++ b/src/com/android/launcher3/util/ScreenOnTracker.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.util; + +import static android.content.Intent.ACTION_SCREEN_OFF; +import static android.content.Intent.ACTION_SCREEN_ON; +import static android.content.Intent.ACTION_USER_PRESENT; + +import android.content.Context; +import android.content.Intent; + +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * Utility class for tracking if the screen is currently on or off + */ +public class ScreenOnTracker { + + public static final MainThreadInitializedObject INSTANCE = + new MainThreadInitializedObject<>(ScreenOnTracker::new); + + private final SimpleBroadcastReceiver mReceiver = new SimpleBroadcastReceiver(this::onReceive); + private final CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); + + private boolean mIsScreenOn; + + private ScreenOnTracker(Context context) { + // Assume that the screen is on to begin with + mIsScreenOn = true; + mReceiver.register(context, ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT); + } + + private void onReceive(Intent intent) { + String action = intent.getAction(); + if (ACTION_SCREEN_ON.equals(action)) { + mIsScreenOn = true; + dispatchScreenOnChanged(); + } else if (ACTION_SCREEN_OFF.equals(action)) { + mIsScreenOn = false; + dispatchScreenOnChanged(); + } else if (ACTION_USER_PRESENT.equals(action)) { + mListeners.forEach(ScreenOnListener::onUserPresent); + } + } + + private void dispatchScreenOnChanged() { + mListeners.forEach(l -> l.onScreenOnChanged(mIsScreenOn)); + } + + /** Returns if the screen is on or not */ + public boolean isScreenOn() { + return mIsScreenOn; + } + + /** Adds a listener for screen on changes */ + public void addListener(ScreenOnListener listener) { + mListeners.add(listener); + } + + /** Removes a previously added listener */ + public void removeListener(ScreenOnListener listener) { + mListeners.remove(listener); + } + + /** + * Interface to listen for screen on changes + */ + public interface ScreenOnListener { + + /** + * Called when the screen turns on/off + */ + void onScreenOnChanged(boolean isOn); + + /** + * Called when the keyguard goes away + */ + default void onUserPresent() { } + } +} diff --git a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java index 0a23506692..064bcd072f 100644 --- a/src/com/android/launcher3/util/SimpleBroadcastReceiver.java +++ b/src/com/android/launcher3/util/SimpleBroadcastReceiver.java @@ -19,6 +19,10 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.PatternMatcher; +import android.text.TextUtils; + +import androidx.annotation.Nullable; import java.util.function.Consumer; @@ -39,18 +43,34 @@ public class SimpleBroadcastReceiver extends BroadcastReceiver { * Helper method to register multiple actions */ public void register(Context context, String... actions) { - register(context, 0, actions); + context.registerReceiver(this, getFilter(actions)); } /** - * Helper method to register multiple actions with one or more {@code flags}. + * Helper method to register multiple actions associated with a paction */ - public void register(Context context, int flags, String... actions) { + public void registerPkgActions(Context context, @Nullable String pkg, String... actions) { + context.registerReceiver(this, getPackageFilter(pkg, actions)); + } + + /** + * Creates an intent filter to listen for actions with a specific package in the data field. + */ + public static IntentFilter getPackageFilter(String pkg, String... actions) { + IntentFilter filter = getFilter(actions); + filter.addDataScheme("package"); + if (!TextUtils.isEmpty(pkg)) { + filter.addDataSchemeSpecificPart(pkg, PatternMatcher.PATTERN_LITERAL); + } + return filter; + } + + private static IntentFilter getFilter(String... actions) { IntentFilter filter = new IntentFilter(); for (String action : actions) { filter.addAction(action); } - context.registerReceiver(this, filter, flags); + return filter; } /** diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java index 43e98201f4..4ac6bc475c 100644 --- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java +++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java @@ -1,12 +1,11 @@ package com.android.launcher3.util; +import static android.content.Intent.ACTION_WALLPAPER_CHANGED; + import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.app.WallpaperManager; -import android.content.BroadcastReceiver; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.os.Handler; import android.os.IBinder; import android.os.Message; @@ -23,7 +22,7 @@ import com.android.launcher3.anim.Interpolators; /** * Utility class to handle wallpaper scrolling along with workspace. */ -public class WallpaperOffsetInterpolator extends BroadcastReceiver { +public class WallpaperOffsetInterpolator { private static final int[] sTempInt = new int[2]; private static final String TAG = "WPOffsetInterpolator"; @@ -32,6 +31,8 @@ public class WallpaperOffsetInterpolator extends BroadcastReceiver { // Don't use all the wallpaper for parallax until you have at least this many pages private static final int MIN_PARALLAX_PAGE_SPAN = 4; + private final SimpleBroadcastReceiver mWallpaperChangeReceiver = + new SimpleBroadcastReceiver(i -> onWallpaperChanged()); private final Workspace mWorkspace; private final boolean mIsRtl; private final Handler mHandler; @@ -197,22 +198,20 @@ public class WallpaperOffsetInterpolator extends BroadcastReceiver { public void setWindowToken(IBinder token) { mWindowToken = token; if (mWindowToken == null && mRegistered) { - mWorkspace.getContext().unregisterReceiver(this); + mWallpaperChangeReceiver.unregisterReceiverSafely(mWorkspace.getContext()); mRegistered = false; } else if (mWindowToken != null && !mRegistered) { - mWorkspace.getContext() - .registerReceiver(this, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED)); - onReceive(mWorkspace.getContext(), null); + mWallpaperChangeReceiver.register(mWorkspace.getContext(), ACTION_WALLPAPER_CHANGED); + onWallpaperChanged(); mRegistered = true; } } - @Override - public void onReceive(Context context, Intent intent) { + private void onWallpaperChanged() { UI_HELPER_EXECUTOR.execute(() -> { // Updating the boolean on a background thread is fine as the assignments are atomic - mWallpaperIsLiveWallpaper = - WallpaperManager.getInstance(context).getWallpaperInfo() != null; + mWallpaperIsLiveWallpaper = WallpaperManager.getInstance(mWorkspace.getContext()) + .getWallpaperInfo() != null; updateOffset(); }); } diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java index cf21dd723f..eae1868213 100644 --- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java +++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java @@ -63,7 +63,7 @@ import com.android.launcher3.tapl.TestHelpers; import com.android.launcher3.testcomponent.TestCommandReceiver; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.LooperExecutor; -import com.android.launcher3.util.PackageManagerHelper; +import com.android.launcher3.util.SimpleBroadcastReceiver; import com.android.launcher3.util.Wait; import com.android.launcher3.util.WidgetUtils; import com.android.launcher3.util.rule.FailureWatcher; @@ -196,15 +196,10 @@ public abstract class AbstractLauncherUiTest { protected void clearPackageData(String pkg) throws IOException, InterruptedException { final CountDownLatch count = new CountDownLatch(2); - final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - count.countDown(); - } - }; - mTargetContext.registerReceiver(broadcastReceiver, - PackageManagerHelper.getPackageFilter(pkg, - Intent.ACTION_PACKAGE_RESTARTED, Intent.ACTION_PACKAGE_DATA_CLEARED)); + final SimpleBroadcastReceiver broadcastReceiver = + new SimpleBroadcastReceiver(i -> count.countDown()); + broadcastReceiver.registerPkgActions(mTargetContext, pkg, + Intent.ACTION_PACKAGE_RESTARTED, Intent.ACTION_PACKAGE_DATA_CLEARED); mDevice.executeShellCommand("pm clear " + pkg); assertTrue(pkg + " didn't restart", count.await(10, TimeUnit.SECONDS));