launcher3: Improve SimpleBroadcastReceiver.
Unless explicitly annotated, parameters in java are by default nullable. There are a few cases where a null context may be passed to the unregisterReceiverSafely function of SimpleBroadcastReceiver. To mitigate misuses or incorrect contexts being passed for register vs unregister, keep the context as a strong reference in the constructor. Also added NonNull annotations for any public callsites to enforce behavior. Bug: 395019017, 395966395 Flag: NONE - bug fixed Test: manual - presubmit Change-Id: Ie371fa45cadceaf51cf184b446df9123ef27c337
This commit is contained in:
@@ -109,9 +109,9 @@ public final class WellbeingModel implements SafeCloseable {
|
||||
? Executors.UI_HELPER_EXECUTOR.getLooper()
|
||||
: Executors.getPackageExecutor(mWellbeingProviderPkg).getLooper());
|
||||
mWellbeingAppChangeReceiver =
|
||||
new SimpleBroadcastReceiver(mWorkerHandler, t -> restartObserver());
|
||||
new SimpleBroadcastReceiver(context, mWorkerHandler, t -> restartObserver());
|
||||
mAppAddRemoveReceiver =
|
||||
new SimpleBroadcastReceiver(mWorkerHandler, this::onAppPackageChanged);
|
||||
new SimpleBroadcastReceiver(context, mWorkerHandler, this::onAppPackageChanged);
|
||||
|
||||
|
||||
mContentObserver = new ContentObserver(mWorkerHandler) {
|
||||
@@ -148,8 +148,8 @@ public final class WellbeingModel implements SafeCloseable {
|
||||
public void close() {
|
||||
if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
|
||||
mWorkerHandler.post(() -> {
|
||||
mWellbeingAppChangeReceiver.unregisterReceiverSafely(mContext);
|
||||
mAppAddRemoveReceiver.unregisterReceiverSafely(mContext);
|
||||
mWellbeingAppChangeReceiver.unregisterReceiverSafely();
|
||||
mAppAddRemoveReceiver.unregisterReceiverSafely();
|
||||
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -124,8 +124,7 @@ public class TaskbarManager {
|
||||
private final TaskbarNavButtonController mDefaultNavButtonController;
|
||||
private final ComponentCallbacks mDefaultComponentCallbacks;
|
||||
|
||||
private final SimpleBroadcastReceiver mShutdownReceiver =
|
||||
new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, i -> destroyAllTaskbars());
|
||||
private final SimpleBroadcastReceiver mShutdownReceiver;
|
||||
|
||||
// The source for this provider is set when Launcher is available
|
||||
// We use 'non-destroyable' version here so the original provider won't be destroyed
|
||||
@@ -183,8 +182,7 @@ public class TaskbarManager {
|
||||
|
||||
private boolean mUserUnlocked = false;
|
||||
|
||||
private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver =
|
||||
new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, this::showTaskbarFromBroadcast);
|
||||
private final SimpleBroadcastReceiver mTaskbarBroadcastReceiver;
|
||||
|
||||
private final AllAppsActionManager mAllAppsActionManager;
|
||||
private final RecentsDisplayModel mRecentsDisplayModel;
|
||||
@@ -266,7 +264,13 @@ public class TaskbarManager {
|
||||
.register(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener);
|
||||
Log.d(TASKBAR_NOT_DESTROYED_TAG, "registering component callbacks from constructor.");
|
||||
mPrimaryWindowContext.registerComponentCallbacks(mDefaultComponentCallbacks);
|
||||
mShutdownReceiver.register(mPrimaryWindowContext, Intent.ACTION_SHUTDOWN);
|
||||
mShutdownReceiver =
|
||||
new SimpleBroadcastReceiver(
|
||||
mPrimaryWindowContext, UI_HELPER_EXECUTOR, i -> destroyAllTaskbars());
|
||||
mTaskbarBroadcastReceiver =
|
||||
new SimpleBroadcastReceiver(mPrimaryWindowContext,
|
||||
UI_HELPER_EXECUTOR, this::showTaskbarFromBroadcast);
|
||||
mShutdownReceiver.register(Intent.ACTION_SHUTDOWN);
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
mSharedState.taskbarSystemActionPendingIntent = PendingIntent.getBroadcast(
|
||||
mPrimaryWindowContext,
|
||||
@@ -274,8 +278,7 @@ public class TaskbarManager {
|
||||
new Intent(ACTION_SHOW_TASKBAR).setPackage(
|
||||
mPrimaryWindowContext.getPackageName()),
|
||||
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
|
||||
mTaskbarBroadcastReceiver.register(
|
||||
mPrimaryWindowContext, RECEIVER_NOT_EXPORTED, ACTION_SHOW_TASKBAR);
|
||||
mTaskbarBroadcastReceiver.register(RECEIVER_NOT_EXPORTED, ACTION_SHOW_TASKBAR);
|
||||
});
|
||||
|
||||
debugWhyTaskbarNotDestroyed("TaskbarManager created");
|
||||
@@ -795,7 +798,7 @@ public class TaskbarManager {
|
||||
mRecentsViewContainer = null;
|
||||
debugWhyTaskbarNotDestroyed("TaskbarManager#destroy()");
|
||||
removeActivityCallbacksAndListeners();
|
||||
mTaskbarBroadcastReceiver.unregisterReceiverSafely(mPrimaryWindowContext);
|
||||
mTaskbarBroadcastReceiver.unregisterReceiverSafely();
|
||||
|
||||
if (mUserUnlocked) {
|
||||
DisplayController.INSTANCE.get(mPrimaryWindowContext).removeChangeListener(
|
||||
@@ -807,7 +810,7 @@ public class TaskbarManager {
|
||||
.unregister(NAV_BAR_KIDS_MODE, mOnSettingsChangeListener);
|
||||
Log.d(TASKBAR_NOT_DESTROYED_TAG, "unregistering component callbacks from destroy().");
|
||||
mPrimaryWindowContext.unregisterComponentCallbacks(mDefaultComponentCallbacks);
|
||||
mShutdownReceiver.unregisterReceiverSafely(mPrimaryWindowContext);
|
||||
mShutdownReceiver.unregisterReceiverSafely();
|
||||
destroyAllTaskbars();
|
||||
}
|
||||
|
||||
|
||||
@@ -72,12 +72,9 @@ public final class OverviewComponentObserver {
|
||||
new DaggerSingletonObject<>(LauncherAppComponent::getOverviewComponentObserver);
|
||||
|
||||
// We register broadcast receivers on main thread to avoid missing updates.
|
||||
private final SimpleBroadcastReceiver mUserPreferenceChangeReceiver =
|
||||
new SimpleBroadcastReceiver(MAIN_EXECUTOR, this::updateOverviewTargets);
|
||||
private final SimpleBroadcastReceiver mOtherHomeAppUpdateReceiver =
|
||||
new SimpleBroadcastReceiver(MAIN_EXECUTOR, this::updateOverviewTargets);
|
||||
private final SimpleBroadcastReceiver mUserPreferenceChangeReceiver;
|
||||
private final SimpleBroadcastReceiver mOtherHomeAppUpdateReceiver;
|
||||
|
||||
private final Context mContext;
|
||||
private final RecentsDisplayModel mRecentsDisplayModel;
|
||||
|
||||
private final Intent mCurrentHomeIntent;
|
||||
@@ -101,10 +98,13 @@ public final class OverviewComponentObserver {
|
||||
@ApplicationContext Context context,
|
||||
RecentsDisplayModel recentsDisplayModel,
|
||||
DaggerSingletonTracker lifecycleTracker) {
|
||||
mContext = context;
|
||||
mUserPreferenceChangeReceiver =
|
||||
new SimpleBroadcastReceiver(context, MAIN_EXECUTOR, this::updateOverviewTargets);
|
||||
mOtherHomeAppUpdateReceiver =
|
||||
new SimpleBroadcastReceiver(context, MAIN_EXECUTOR, this::updateOverviewTargets);
|
||||
mRecentsDisplayModel = recentsDisplayModel;
|
||||
mCurrentHomeIntent = createHomeIntent();
|
||||
mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(mContext.getPackageName());
|
||||
mMyHomeIntent = new Intent(mCurrentHomeIntent).setPackage(context.getPackageName());
|
||||
ResolveInfo info = context.getPackageManager().resolveActivity(mMyHomeIntent, 0);
|
||||
ComponentName myHomeComponent =
|
||||
new ComponentName(context.getPackageName(), info.activityInfo.name);
|
||||
@@ -112,7 +112,7 @@ public final class OverviewComponentObserver {
|
||||
mConfigChangesMap.append(myHomeComponent.hashCode(), info.activityInfo.configChanges);
|
||||
mSetupWizardPkg = context.getString(R.string.setup_wizard_pkg);
|
||||
|
||||
ComponentName fallbackComponent = new ComponentName(mContext, RecentsActivity.class);
|
||||
ComponentName fallbackComponent = new ComponentName(context, RecentsActivity.class);
|
||||
mFallbackIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
.setComponent(fallbackComponent)
|
||||
@@ -124,7 +124,7 @@ public final class OverviewComponentObserver {
|
||||
mConfigChangesMap.append(fallbackComponent.hashCode(), fallbackInfo.configChanges);
|
||||
} catch (PackageManager.NameNotFoundException ignored) { /* Impossible */ }
|
||||
|
||||
mUserPreferenceChangeReceiver.register(mContext, ACTION_PREFERRED_ACTIVITY_CHANGED);
|
||||
mUserPreferenceChangeReceiver.register(ACTION_PREFERRED_ACTIVITY_CHANGED);
|
||||
updateOverviewTargets();
|
||||
|
||||
lifecycleTracker.addCloseable(this::onDestroy);
|
||||
@@ -224,7 +224,7 @@ public final class OverviewComponentObserver {
|
||||
|
||||
mUpdateRegisteredPackage = defaultHome.getPackageName();
|
||||
mOtherHomeAppUpdateReceiver.registerPkgActions(
|
||||
mContext, mUpdateRegisteredPackage, ACTION_PACKAGE_ADDED,
|
||||
mUpdateRegisteredPackage, ACTION_PACKAGE_ADDED,
|
||||
ACTION_PACKAGE_CHANGED, ACTION_PACKAGE_REMOVED);
|
||||
}
|
||||
}
|
||||
@@ -235,13 +235,13 @@ public final class OverviewComponentObserver {
|
||||
* Clean up any registered receivers.
|
||||
*/
|
||||
private void onDestroy() {
|
||||
mUserPreferenceChangeReceiver.unregisterReceiverSafely(mContext);
|
||||
mUserPreferenceChangeReceiver.unregisterReceiverSafely();
|
||||
unregisterOtherHomeAppUpdateReceiver();
|
||||
}
|
||||
|
||||
private void unregisterOtherHomeAppUpdateReceiver() {
|
||||
if (mUpdateRegisteredPackage != null) {
|
||||
mOtherHomeAppUpdateReceiver.unregisterReceiverSafely(mContext);
|
||||
mOtherHomeAppUpdateReceiver.unregisterReceiverSafely();
|
||||
mUpdateRegisteredPackage = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +59,7 @@ public class AsyncClockEventDelegate extends ClockEventDelegate
|
||||
|
||||
private final Context mContext;
|
||||
private final SettingsCache mSettingsCache;
|
||||
private final SimpleBroadcastReceiver mReceiver =
|
||||
new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, this::onClockEventReceived);
|
||||
private final SimpleBroadcastReceiver mReceiver;
|
||||
|
||||
private final ArrayMap<BroadcastReceiver, Handler> mTimeEventReceivers = new ArrayMap<>();
|
||||
private final List<ContentObserver> mFormatObservers = new ArrayList<>();
|
||||
@@ -76,7 +75,9 @@ public class AsyncClockEventDelegate extends ClockEventDelegate
|
||||
super(context);
|
||||
mContext = context;
|
||||
mSettingsCache = settingsCache;
|
||||
mReceiver.register(mContext, ACTION_TIME_CHANGED, ACTION_TIMEZONE_CHANGED);
|
||||
mReceiver = new SimpleBroadcastReceiver(
|
||||
context, UI_HELPER_EXECUTOR, this::onClockEventReceived);
|
||||
mReceiver.register(ACTION_TIME_CHANGED, ACTION_TIMEZONE_CHANGED);
|
||||
tracker.addCloseable(this);
|
||||
}
|
||||
|
||||
@@ -138,6 +139,6 @@ public class AsyncClockEventDelegate extends ClockEventDelegate
|
||||
public void close() {
|
||||
mDestroyed = true;
|
||||
mSettingsCache.unregister(mFormatUri, this);
|
||||
mReceiver.unregisterReceiverSafely(mContext);
|
||||
mReceiver.unregisterReceiverSafely();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,8 +74,7 @@ public class ContextualSearchStateManager {
|
||||
Settings.Secure.getUriFor(Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED);
|
||||
|
||||
private final Runnable mSysUiStateChangeListener = this::updateOverridesToSysUi;
|
||||
private final SimpleBroadcastReceiver mContextualSearchPackageReceiver =
|
||||
new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, (unused) -> requestUpdateProperties());
|
||||
private final SimpleBroadcastReceiver mContextualSearchPackageReceiver;
|
||||
protected final EventLogArray mEventLogArray = new EventLogArray(TAG, MAX_DEBUG_EVENT_SIZE);
|
||||
|
||||
// Cached value whether the ContextualSearch intent filter matched any enabled components.
|
||||
@@ -95,6 +94,9 @@ public class ContextualSearchStateManager {
|
||||
TopTaskTracker topTaskTracker,
|
||||
DaggerSingletonTracker lifeCycle) {
|
||||
mContext = context;
|
||||
mContextualSearchPackageReceiver =
|
||||
new SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR,
|
||||
(unused) -> requestUpdateProperties());
|
||||
mContextualSearchPackage = mContext.getResources().getString(
|
||||
com.android.internal.R.string.config_defaultContextualSearchPackageName);
|
||||
mSystemUiProxy = systemUiProxy;
|
||||
@@ -112,7 +114,7 @@ public class ContextualSearchStateManager {
|
||||
requestUpdateProperties();
|
||||
registerSearchScreenSystemAction();
|
||||
mContextualSearchPackageReceiver.registerPkgActions(
|
||||
context, mContextualSearchPackage, Intent.ACTION_PACKAGE_ADDED,
|
||||
mContextualSearchPackage, Intent.ACTION_PACKAGE_ADDED,
|
||||
Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_PACKAGE_REMOVED);
|
||||
|
||||
SettingsCache.OnChangeListener settingChangedListener =
|
||||
@@ -124,7 +126,7 @@ public class ContextualSearchStateManager {
|
||||
systemUiProxy.addOnStateChangeListener(mSysUiStateChangeListener);
|
||||
|
||||
lifeCycle.addCloseable(() -> {
|
||||
mContextualSearchPackageReceiver.unregisterReceiverSafely(mContext);
|
||||
mContextualSearchPackageReceiver.unregisterReceiverSafely();
|
||||
unregisterSearchScreenSystemAction();
|
||||
settingsCache.unregister(SEARCH_ALL_ENTRYPOINTS_ENABLED_URI, settingChangedListener);
|
||||
systemUiProxy.removeOnStateChangeListener(mSysUiStateChangeListener);
|
||||
|
||||
@@ -300,10 +300,10 @@ public class InvariantDeviceProfile {
|
||||
lifeCycle.addCloseable(() -> prefs.removeListener(prefListener,
|
||||
FIXED_LANDSCAPE_MODE, ENABLE_TWOLINE_ALLAPPS_TOGGLE));
|
||||
|
||||
SimpleBroadcastReceiver localeReceiver = new SimpleBroadcastReceiver(
|
||||
SimpleBroadcastReceiver localeReceiver = new SimpleBroadcastReceiver(context,
|
||||
MAIN_EXECUTOR, i -> onConfigChanged(context));
|
||||
localeReceiver.register(context, Intent.ACTION_LOCALE_CHANGED);
|
||||
lifeCycle.addCloseable(() -> localeReceiver.unregisterReceiverSafely(context));
|
||||
localeReceiver.register(Intent.ACTION_LOCALE_CHANGED);
|
||||
lifeCycle.addCloseable(() -> localeReceiver.unregisterReceiverSafely());
|
||||
}
|
||||
|
||||
private String initGrid(Context context, String gridName) {
|
||||
|
||||
@@ -119,14 +119,13 @@ public class LauncherAppState implements SafeCloseable {
|
||||
}
|
||||
|
||||
SimpleBroadcastReceiver modelChangeReceiver =
|
||||
new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, mModel::onBroadcastIntent);
|
||||
new SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR, mModel::onBroadcastIntent);
|
||||
modelChangeReceiver.register(
|
||||
mContext,
|
||||
ACTION_DEVICE_POLICY_RESOURCE_UPDATED);
|
||||
if (BuildConfig.IS_STUDIO_BUILD) {
|
||||
modelChangeReceiver.register(mContext, RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
|
||||
modelChangeReceiver.register(RECEIVER_EXPORTED, ACTION_FORCE_ROLOAD);
|
||||
}
|
||||
mOnTerminateCallback.add(() -> modelChangeReceiver.unregisterReceiverSafely(mContext));
|
||||
mOnTerminateCallback.add(() -> modelChangeReceiver.unregisterReceiverSafely());
|
||||
|
||||
SafeCloseable userChangeListener = UserCache.INSTANCE.get(mContext)
|
||||
.addUserEventListener(mModel::onUserEvent);
|
||||
|
||||
@@ -62,8 +62,8 @@ constructor(
|
||||
private val listeners = CopyOnWriteArrayList<ThemeChangeListener>()
|
||||
|
||||
init {
|
||||
val receiver = SimpleBroadcastReceiver(MAIN_EXECUTOR) { verifyIconState() }
|
||||
receiver.registerPkgActions(context, "android", ACTION_OVERLAY_CHANGED)
|
||||
val receiver = SimpleBroadcastReceiver(context, MAIN_EXECUTOR) { verifyIconState() }
|
||||
receiver.registerPkgActions("android", ACTION_OVERLAY_CHANGED)
|
||||
|
||||
val prefListener = LauncherPrefChangeListener { key ->
|
||||
when (key) {
|
||||
@@ -74,7 +74,7 @@ constructor(
|
||||
prefs.addListener(prefListener, THEMED_ICONS, PREF_ICON_SHAPE)
|
||||
|
||||
lifecycle.addCloseable {
|
||||
receiver.unregisterReceiverSafely(context)
|
||||
receiver.unregisterReceiverSafely()
|
||||
prefs.removeListener(prefListener)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,10 +81,7 @@ public class UserCache {
|
||||
}
|
||||
|
||||
private final List<BiConsumer<UserHandle, String>> mUserEventListeners = new ArrayList<>();
|
||||
private final SimpleBroadcastReceiver mUserChangeReceiver =
|
||||
new SimpleBroadcastReceiver(MODEL_EXECUTOR, this::onUsersChanged);
|
||||
|
||||
private final Context mContext;
|
||||
private final SimpleBroadcastReceiver mUserChangeReceiver;
|
||||
private final ApiWrapper mApiWrapper;
|
||||
|
||||
@NonNull
|
||||
@@ -99,16 +96,17 @@ public class UserCache {
|
||||
DaggerSingletonTracker tracker,
|
||||
ApiWrapper apiWrapper
|
||||
) {
|
||||
mContext = context;
|
||||
mApiWrapper = apiWrapper;
|
||||
mUserChangeReceiver = new SimpleBroadcastReceiver(context,
|
||||
MODEL_EXECUTOR, this::onUsersChanged);
|
||||
mUserToSerialMap = Collections.emptyMap();
|
||||
MODEL_EXECUTOR.execute(this::initAsync);
|
||||
tracker.addCloseable(() -> mUserChangeReceiver.unregisterReceiverSafely(mContext));
|
||||
tracker.addCloseable(() -> mUserChangeReceiver.unregisterReceiverSafely());
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private void initAsync() {
|
||||
mUserChangeReceiver.register(mContext,
|
||||
mUserChangeReceiver.register(
|
||||
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
|
||||
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
|
||||
Intent.ACTION_MANAGED_PROFILE_REMOVED,
|
||||
|
||||
@@ -107,7 +107,6 @@ public class DisplayController implements ComponentCallbacks,
|
||||
private static final String ACTION_OVERLAY_CHANGED = "android.intent.action.OVERLAY_CHANGED";
|
||||
private static final String TARGET_OVERLAY_PACKAGE = "android";
|
||||
|
||||
private final Context mContext;
|
||||
private final WindowManagerProxy mWMProxy;
|
||||
|
||||
// Null for SDK < S
|
||||
@@ -120,8 +119,7 @@ public class DisplayController implements ComponentCallbacks,
|
||||
|
||||
// We will register broadcast receiver on main thread to ensure not missing changes on
|
||||
// TARGET_OVERLAY_PACKAGE and ACTION_OVERLAY_CHANGED.
|
||||
private final SimpleBroadcastReceiver mReceiver =
|
||||
new SimpleBroadcastReceiver(MAIN_EXECUTOR, this::onIntent);
|
||||
private final SimpleBroadcastReceiver mReceiver;
|
||||
|
||||
private Info mInfo;
|
||||
private boolean mDestroyed = false;
|
||||
@@ -131,7 +129,6 @@ public class DisplayController implements ComponentCallbacks,
|
||||
WindowManagerProxy wmProxy,
|
||||
LauncherPrefs prefs,
|
||||
DaggerSingletonTracker lifecycle) {
|
||||
mContext = context;
|
||||
mWMProxy = wmProxy;
|
||||
|
||||
if (enableTaskbarPinning()) {
|
||||
@@ -155,11 +152,12 @@ public class DisplayController implements ComponentCallbacks,
|
||||
|
||||
Display display = context.getSystemService(DisplayManager.class)
|
||||
.getDisplay(DEFAULT_DISPLAY);
|
||||
mWindowContext = mContext.createWindowContext(display, TYPE_APPLICATION, null);
|
||||
mWindowContext = context.createWindowContext(display, TYPE_APPLICATION, null);
|
||||
mWindowContext.registerComponentCallbacks(this);
|
||||
|
||||
// Initialize navigation mode change listener
|
||||
mReceiver.registerPkgActions(mContext, TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED);
|
||||
mReceiver = new SimpleBroadcastReceiver(context, MAIN_EXECUTOR, this::onIntent);
|
||||
mReceiver.registerPkgActions(TARGET_OVERLAY_PACKAGE, ACTION_OVERLAY_CHANGED);
|
||||
|
||||
mInfo = new Info(mWindowContext, wmProxy,
|
||||
wmProxy.estimateInternalDisplayBounds(mWindowContext));
|
||||
@@ -169,7 +167,7 @@ public class DisplayController implements ComponentCallbacks,
|
||||
lifecycle.addCloseable(() -> {
|
||||
mDestroyed = true;
|
||||
mWindowContext.unregisterComponentCallbacks(this);
|
||||
mReceiver.unregisterReceiverSafely(mContext);
|
||||
mReceiver.unregisterReceiverSafely();
|
||||
wmProxy.unregisterDesktopVisibilityListener(this);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ constructor(@ApplicationContext private val context: Context, lifeCycle: DaggerS
|
||||
|
||||
@VisibleForTesting
|
||||
val userUnlockedReceiver =
|
||||
SimpleBroadcastReceiver(UI_HELPER_EXECUTOR) {
|
||||
SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR) {
|
||||
if (Intent.ACTION_USER_UNLOCKED == it.action) {
|
||||
isUserUnlocked = true
|
||||
}
|
||||
@@ -61,7 +61,6 @@ constructor(@ApplicationContext private val context: Context, lifeCycle: DaggerS
|
||||
isUserUnlockedAtLauncherStartup = isUserUnlocked
|
||||
if (!isUserUnlocked) {
|
||||
userUnlockedReceiver.register(
|
||||
context,
|
||||
{
|
||||
// If user is unlocked while registering broadcast receiver, we should update
|
||||
// [isUserUnlocked], which will call [notifyUserUnlocked] in setter
|
||||
@@ -72,7 +71,7 @@ constructor(@ApplicationContext private val context: Context, lifeCycle: DaggerS
|
||||
Intent.ACTION_USER_UNLOCKED,
|
||||
)
|
||||
}
|
||||
lifeCycle.addCloseable { userUnlockedReceiver.unregisterReceiverSafely(context) }
|
||||
lifeCycle.addCloseable { userUnlockedReceiver.unregisterReceiverSafely() }
|
||||
}
|
||||
|
||||
private fun checkIsUserUnlocked() =
|
||||
@@ -80,7 +79,7 @@ constructor(@ApplicationContext private val context: Context, lifeCycle: DaggerS
|
||||
|
||||
private fun notifyUserUnlocked() {
|
||||
mUserUnlockedActions.executeAllAndDestroy()
|
||||
userUnlockedReceiver.unregisterReceiverSafely(context)
|
||||
userUnlockedReceiver.unregisterReceiverSafely()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,34 +46,31 @@ public class ScreenOnTracker implements SafeCloseable {
|
||||
private final SimpleBroadcastReceiver mReceiver;
|
||||
private final CopyOnWriteArrayList<ScreenOnListener> mListeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
private final Context mContext;
|
||||
private boolean mIsScreenOn;
|
||||
|
||||
@Inject
|
||||
ScreenOnTracker(@ApplicationContext Context context, DaggerSingletonTracker tracker) {
|
||||
// Assume that the screen is on to begin with
|
||||
mContext = context;
|
||||
mReceiver = new SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, this::onReceive);
|
||||
mReceiver = new SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR, this::onReceive);
|
||||
init(tracker);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ScreenOnTracker(@ApplicationContext Context context, SimpleBroadcastReceiver receiver,
|
||||
DaggerSingletonTracker tracker) {
|
||||
mContext = context;
|
||||
mReceiver = receiver;
|
||||
init(tracker);
|
||||
}
|
||||
|
||||
private void init(DaggerSingletonTracker tracker) {
|
||||
mIsScreenOn = true;
|
||||
mReceiver.register(mContext, ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT);
|
||||
mReceiver.register(ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT);
|
||||
tracker.addCloseable(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
mReceiver.unregisterReceiverSafely(mContext);
|
||||
mReceiver.unregisterReceiverSafely();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -25,22 +25,29 @@ import android.os.PatternMatcher;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.AnyThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class SimpleBroadcastReceiver extends BroadcastReceiver {
|
||||
public static final String TAG = "SimpleBroadcastReceiver";
|
||||
// Keeps a strong reference to the context.
|
||||
private final Context mContext;
|
||||
|
||||
private final Consumer<Intent> mIntentConsumer;
|
||||
|
||||
// Handler to register/unregister broadcast receiver
|
||||
private final Handler mHandler;
|
||||
|
||||
public SimpleBroadcastReceiver(LooperExecutor looperExecutor, Consumer<Intent> intentConsumer) {
|
||||
this(looperExecutor.getHandler(), intentConsumer);
|
||||
public SimpleBroadcastReceiver(@NonNull Context context, LooperExecutor looperExecutor,
|
||||
Consumer<Intent> intentConsumer) {
|
||||
this(context, looperExecutor.getHandler(), intentConsumer);
|
||||
}
|
||||
|
||||
public SimpleBroadcastReceiver(Handler handler, Consumer<Intent> intentConsumer) {
|
||||
public SimpleBroadcastReceiver(@NonNull Context context, Handler handler,
|
||||
Consumer<Intent> intentConsumer) {
|
||||
mContext = context;
|
||||
mIntentConsumer = intentConsumer;
|
||||
mHandler = handler;
|
||||
}
|
||||
@@ -50,18 +57,18 @@ public class SimpleBroadcastReceiver extends BroadcastReceiver {
|
||||
mIntentConsumer.accept(intent);
|
||||
}
|
||||
|
||||
/** Calls {@link #register(Context, Runnable, String...)} with null completionCallback. */
|
||||
/** Calls {@link #register(Runnable, String...)} with null completionCallback. */
|
||||
@AnyThread
|
||||
public void register(Context context, String... actions) {
|
||||
register(context, null, actions);
|
||||
public void register(String... actions) {
|
||||
register(null, actions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #register(Context, Runnable, int, String...)} with null completionCallback.
|
||||
* Calls {@link #register(Runnable, int, String...)} with null completionCallback.
|
||||
*/
|
||||
@AnyThread
|
||||
public void register(Context context, int flags, String... actions) {
|
||||
register(context, null, flags, actions);
|
||||
public void register(int flags, String... actions) {
|
||||
register(null, flags, actions);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,19 +81,18 @@ public class SimpleBroadcastReceiver extends BroadcastReceiver {
|
||||
* while registerReceiver() is executed on a binder call.
|
||||
*/
|
||||
@AnyThread
|
||||
public void register(
|
||||
Context context, @Nullable Runnable completionCallback, String... actions) {
|
||||
public void register(@Nullable Runnable completionCallback, String... actions) {
|
||||
if (Looper.myLooper() == mHandler.getLooper()) {
|
||||
registerInternal(context, completionCallback, actions);
|
||||
registerInternal(mContext, completionCallback, actions);
|
||||
} else {
|
||||
mHandler.post(() -> registerInternal(context, completionCallback, actions));
|
||||
mHandler.post(() -> registerInternal(mContext, completionCallback, actions));
|
||||
}
|
||||
}
|
||||
|
||||
/** Register broadcast receiver and run completion callback if passed. */
|
||||
@AnyThread
|
||||
private void registerInternal(
|
||||
Context context, @Nullable Runnable completionCallback, String... actions) {
|
||||
@NonNull Context context, @Nullable Runnable completionCallback, String... actions) {
|
||||
context.registerReceiver(this, getFilter(actions));
|
||||
if (completionCallback != null) {
|
||||
completionCallback.run();
|
||||
@@ -94,37 +100,37 @@ public class SimpleBroadcastReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #register(Context, Runnable, String...)} above but with additional flags
|
||||
* params.
|
||||
* Same as {@link #register(Runnable, String...)} above but with additional flags
|
||||
* params utilizine the original {@link Context}.
|
||||
*/
|
||||
@AnyThread
|
||||
public void register(
|
||||
Context context, @Nullable Runnable completionCallback, int flags, String... actions) {
|
||||
public void register(@Nullable Runnable completionCallback, int flags, String... actions) {
|
||||
if (Looper.myLooper() == mHandler.getLooper()) {
|
||||
registerInternal(context, completionCallback, flags, actions);
|
||||
registerInternal(mContext, completionCallback, flags, actions);
|
||||
} else {
|
||||
mHandler.post(() -> registerInternal(context, completionCallback, flags, actions));
|
||||
mHandler.post(() -> registerInternal(mContext, completionCallback, flags, actions));
|
||||
}
|
||||
}
|
||||
|
||||
/** Register broadcast receiver and run completion callback if passed. */
|
||||
@AnyThread
|
||||
private void registerInternal(
|
||||
Context context, @Nullable Runnable completionCallback, int flags, String... actions) {
|
||||
@NonNull Context context, @Nullable Runnable completionCallback, int flags,
|
||||
String... actions) {
|
||||
context.registerReceiver(this, getFilter(actions), flags);
|
||||
if (completionCallback != null) {
|
||||
completionCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
/** Same as {@link #register(Context, Runnable, String...)} above but with pkg name. */
|
||||
/** Same as {@link #register(Runnable, String...)} above but with pkg name. */
|
||||
@AnyThread
|
||||
public void registerPkgActions(Context context, @Nullable String pkg, String... actions) {
|
||||
public void registerPkgActions(@Nullable String pkg, String... actions) {
|
||||
if (Looper.myLooper() == mHandler.getLooper()) {
|
||||
context.registerReceiver(this, getPackageFilter(pkg, actions));
|
||||
mContext.registerReceiver(this, getPackageFilter(pkg, actions));
|
||||
} else {
|
||||
mHandler.post(() -> {
|
||||
context.registerReceiver(this, getPackageFilter(pkg, actions));
|
||||
mContext.registerReceiver(this, getPackageFilter(pkg, actions));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -135,19 +141,19 @@ public class SimpleBroadcastReceiver extends BroadcastReceiver {
|
||||
* unregister happens on {@link #mHandler}'s looper.
|
||||
*/
|
||||
@AnyThread
|
||||
public void unregisterReceiverSafely(Context context) {
|
||||
public void unregisterReceiverSafely() {
|
||||
if (Looper.myLooper() == mHandler.getLooper()) {
|
||||
unregisterReceiverSafelyInternal(context);
|
||||
unregisterReceiverSafelyInternal(mContext);
|
||||
} else {
|
||||
mHandler.post(() -> {
|
||||
unregisterReceiverSafelyInternal(context);
|
||||
unregisterReceiverSafelyInternal(mContext);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Unregister broadcast receiver ignoring any errors. */
|
||||
@AnyThread
|
||||
private void unregisterReceiverSafelyInternal(Context context) {
|
||||
private void unregisterReceiverSafelyInternal(@NonNull Context context) {
|
||||
try {
|
||||
context.unregisterReceiver(this);
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -31,8 +31,7 @@ public class WallpaperOffsetInterpolator {
|
||||
// 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(UI_HELPER_EXECUTOR, i -> onWallpaperChanged());
|
||||
private final SimpleBroadcastReceiver mWallpaperChangeReceiver;
|
||||
private final Workspace<?> mWorkspace;
|
||||
private final boolean mIsRtl;
|
||||
private final Handler mHandler;
|
||||
@@ -46,6 +45,8 @@ public class WallpaperOffsetInterpolator {
|
||||
|
||||
public WallpaperOffsetInterpolator(Workspace<?> workspace) {
|
||||
mWorkspace = workspace;
|
||||
mWallpaperChangeReceiver = new SimpleBroadcastReceiver(
|
||||
workspace.getContext(), UI_HELPER_EXECUTOR, i -> onWallpaperChanged());
|
||||
mIsRtl = Utilities.isRtl(workspace.getResources());
|
||||
mHandler = new OffsetHandler(workspace.getContext());
|
||||
}
|
||||
@@ -198,11 +199,10 @@ public class WallpaperOffsetInterpolator {
|
||||
public void setWindowToken(IBinder token) {
|
||||
mWindowToken = token;
|
||||
if (mWindowToken == null && mRegistered) {
|
||||
mWallpaperChangeReceiver.unregisterReceiverSafely(mWorkspace.getContext());
|
||||
mWallpaperChangeReceiver.unregisterReceiverSafely();
|
||||
mRegistered = false;
|
||||
} else if (mWindowToken != null && !mRegistered) {
|
||||
mWallpaperChangeReceiver.register(
|
||||
mWorkspace.getContext(), ACTION_WALLPAPER_CHANGED);
|
||||
mWallpaperChangeReceiver.register(ACTION_WALLPAPER_CHANGED);
|
||||
onWallpaperChanged();
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class ScreenOnTrackerTest {
|
||||
|
||||
@Test
|
||||
fun test_default_state() {
|
||||
verify(receiver).register(context, ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT)
|
||||
verify(receiver).register(ACTION_SCREEN_ON, ACTION_SCREEN_OFF, ACTION_USER_PRESENT)
|
||||
assertThat(underTest.isScreenOn).isTrue()
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ class ScreenOnTrackerTest {
|
||||
fun close_unregister_receiver() {
|
||||
underTest.close()
|
||||
|
||||
verify(receiver).unregisterReceiverSafely(context)
|
||||
verify(receiver).unregisterReceiverSafely()
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+12
-10
@@ -52,7 +52,7 @@ class SimpleBroadcastReceiverTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
underTest = SimpleBroadcastReceiver(UI_HELPER_EXECUTOR, intentConsumer)
|
||||
underTest = SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR, intentConsumer)
|
||||
if (Looper.getMainLooper() == null) {
|
||||
Looper.prepareMainLooper()
|
||||
}
|
||||
@@ -60,7 +60,7 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun async_register() {
|
||||
underTest.register(context, "test_action_1", "test_action_2")
|
||||
underTest.register("test_action_1", "test_action_2")
|
||||
awaitTasksCompleted()
|
||||
|
||||
verify(context).registerReceiver(same(underTest), intentFilterCaptor.capture())
|
||||
@@ -72,7 +72,7 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun async_register_withCompletionRunnable() {
|
||||
underTest.register(context, completionRunnable, "test_action_1", "test_action_2")
|
||||
underTest.register(completionRunnable, "test_action_1", "test_action_2")
|
||||
awaitTasksCompleted()
|
||||
|
||||
verify(context).registerReceiver(same(underTest), intentFilterCaptor.capture())
|
||||
@@ -85,7 +85,7 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun async_register_withCompletionRunnable_and_flag() {
|
||||
underTest.register(context, completionRunnable, 1, "test_action_1", "test_action_2")
|
||||
underTest.register(completionRunnable, 1, "test_action_1", "test_action_2")
|
||||
awaitTasksCompleted()
|
||||
|
||||
verify(context).registerReceiver(same(underTest), intentFilterCaptor.capture(), eq(1))
|
||||
@@ -98,7 +98,7 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun async_register_with_package() {
|
||||
underTest.registerPkgActions(context, "pkg", "test_action_1", "test_action_2")
|
||||
underTest.registerPkgActions("pkg", "test_action_1", "test_action_2")
|
||||
|
||||
awaitTasksCompleted()
|
||||
verify(context).registerReceiver(same(underTest), intentFilterCaptor.capture())
|
||||
@@ -112,9 +112,10 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun sync_register_withCompletionRunnable_and_flag() {
|
||||
underTest = SimpleBroadcastReceiver(Handler(Looper.getMainLooper()), intentConsumer)
|
||||
underTest =
|
||||
SimpleBroadcastReceiver(context, Handler(Looper.getMainLooper()), intentConsumer)
|
||||
|
||||
underTest.register(context, completionRunnable, 1, "test_action_1", "test_action_2")
|
||||
underTest.register(completionRunnable, 1, "test_action_1", "test_action_2")
|
||||
getInstrumentation().waitForIdleSync()
|
||||
|
||||
verify(context).registerReceiver(same(underTest), intentFilterCaptor.capture(), eq(1))
|
||||
@@ -127,7 +128,7 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun async_unregister() {
|
||||
underTest.unregisterReceiverSafely(context)
|
||||
underTest.unregisterReceiverSafely()
|
||||
|
||||
awaitTasksCompleted()
|
||||
verify(context).unregisterReceiver(same(underTest))
|
||||
@@ -135,9 +136,10 @@ class SimpleBroadcastReceiverTest {
|
||||
|
||||
@Test
|
||||
fun sync_unregister() {
|
||||
underTest = SimpleBroadcastReceiver(Handler(Looper.getMainLooper()), intentConsumer)
|
||||
underTest =
|
||||
SimpleBroadcastReceiver(context, Handler(Looper.getMainLooper()), intentConsumer)
|
||||
|
||||
underTest.unregisterReceiverSafely(context)
|
||||
underTest.unregisterReceiverSafely()
|
||||
getInstrumentation().waitForIdleSync()
|
||||
|
||||
verify(context).unregisterReceiver(same(underTest))
|
||||
|
||||
Reference in New Issue
Block a user