Merge changes Id72c0f2b,Ied9a3769 into udc-qpr-dev
* changes: Debounce messages in BrightnessController Add non-blocking message processing
This commit is contained in:
committed by
Android (Google) Code Review
commit
9d2331c1fa
@@ -58,6 +58,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
|
||||
private final BrightnessSliderController mBrightnessSliderController;
|
||||
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
|
||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||
private boolean mListening;
|
||||
|
||||
private View.OnTouchListener mTileLayoutTouchListener = new View.OnTouchListener() {
|
||||
@Override
|
||||
@@ -159,12 +160,15 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
|
||||
public void setListening(boolean listening, boolean expanded) {
|
||||
setListening(listening && expanded);
|
||||
|
||||
// Set the listening as soon as the QS fragment starts listening regardless of the
|
||||
//expansion, so it will update the current brightness before the slider is visible.
|
||||
if (listening) {
|
||||
mBrightnessController.registerCallbacks();
|
||||
} else {
|
||||
mBrightnessController.unregisterCallbacks();
|
||||
if (listening != mListening) {
|
||||
mListening = listening;
|
||||
// Set the listening as soon as the QS fragment starts listening regardless of the
|
||||
//expansion, so it will update the current brightness before the slider is visible.
|
||||
if (listening) {
|
||||
mBrightnessController.registerCallbacks();
|
||||
} else {
|
||||
mBrightnessController.unregisterCallbacks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import static com.android.settingslib.display.BrightnessUtils.convertLinearToGam
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.display.BrightnessInfo;
|
||||
@@ -31,10 +30,10 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
@@ -43,6 +42,8 @@ import android.service.vr.IVrStateCallbacks;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.display.BrightnessSynchronizer;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
@@ -52,10 +53,13 @@ import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.settings.DisplayTracker;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
|
||||
import com.android.systemui.util.settings.SecureSettings;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import dagger.assisted.Assisted;
|
||||
import dagger.assisted.AssistedFactory;
|
||||
import dagger.assisted.AssistedInject;
|
||||
|
||||
public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
|
||||
private static final String TAG = "CentralSurfaces.BrightnessController";
|
||||
@@ -75,8 +79,11 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
private final DisplayManager mDisplayManager;
|
||||
private final UserTracker mUserTracker;
|
||||
private final DisplayTracker mDisplayTracker;
|
||||
@Nullable
|
||||
private final IVrManager mVrManager;
|
||||
|
||||
private final SecureSettings mSecureSettings;
|
||||
|
||||
private final Executor mMainExecutor;
|
||||
private final Handler mBackgroundHandler;
|
||||
private final BrightnessObserver mBrightnessObserver;
|
||||
@@ -106,6 +113,8 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
/** ContentObserver to watch brightness */
|
||||
private class BrightnessObserver extends ContentObserver {
|
||||
|
||||
private boolean mObserving = false;
|
||||
|
||||
BrightnessObserver(Handler handler) {
|
||||
super(handler);
|
||||
}
|
||||
@@ -124,19 +133,17 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
}
|
||||
|
||||
public void startObserving() {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
cr.unregisterContentObserver(this);
|
||||
cr.registerContentObserver(
|
||||
BRIGHTNESS_MODE_URI,
|
||||
false, this, UserHandle.USER_ALL);
|
||||
mDisplayTracker.addBrightnessChangeCallback(mBrightnessListener,
|
||||
new HandlerExecutor(mHandler));
|
||||
if (!mObserving) {
|
||||
mObserving = true;
|
||||
mSecureSettings.registerContentObserverForUser(
|
||||
BRIGHTNESS_MODE_URI,
|
||||
false, this, UserHandle.USER_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopObserving() {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
cr.unregisterContentObserver(this);
|
||||
mDisplayTracker.removeCallback(mBrightnessListener);
|
||||
mSecureSettings.unregisterContentObserver(this);
|
||||
mObserving = false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -159,6 +166,8 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
}
|
||||
|
||||
mBrightnessObserver.startObserving();
|
||||
mDisplayTracker.addBrightnessChangeCallback(mBrightnessListener,
|
||||
new HandlerExecutor(mMainHandler));
|
||||
mUserTracker.addCallback(mUserChangedCallback, mMainExecutor);
|
||||
|
||||
// Update the slider and mode before attaching the listener so we don't
|
||||
@@ -166,7 +175,7 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
mUpdateModeRunnable.run();
|
||||
mUpdateSliderRunnable.run();
|
||||
|
||||
mHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
|
||||
mMainHandler.sendEmptyMessage(MSG_ATTACH_LISTENER);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -187,9 +196,10 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
}
|
||||
|
||||
mBrightnessObserver.stopObserving();
|
||||
mDisplayTracker.removeCallback(mBrightnessListener);
|
||||
mUserTracker.removeCallback(mUserChangedCallback);
|
||||
|
||||
mHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
|
||||
mMainHandler.sendEmptyMessage(MSG_DETACH_LISTENER);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -225,7 +235,7 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
mBrightnessMin = info.brightnessMinimum;
|
||||
// Value is passed as intbits, since this is what the message takes.
|
||||
final int valueAsIntBits = Float.floatToIntBits(info.brightness);
|
||||
mHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
|
||||
mMainHandler.obtainMessage(MSG_UPDATE_SLIDER, valueAsIntBits,
|
||||
inVrMode ? 1 : 0).sendToTarget();
|
||||
}
|
||||
};
|
||||
@@ -233,14 +243,14 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
private final IVrStateCallbacks mVrStateCallbacks = new IVrStateCallbacks.Stub() {
|
||||
@Override
|
||||
public void onVrStateChanged(boolean enabled) {
|
||||
mHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
|
||||
mMainHandler.obtainMessage(MSG_VR_MODE_CHANGED, enabled ? 1 : 0, 0)
|
||||
.sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
private final Handler.Callback mHandlerCallback = new Handler.Callback() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
public boolean handleMessage(Message msg) {
|
||||
mExternalChange = true;
|
||||
try {
|
||||
switch (msg.what) {
|
||||
@@ -257,14 +267,18 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
updateVrMode(msg.arg1 != 0);
|
||||
break;
|
||||
default:
|
||||
super.handleMessage(msg);
|
||||
return false;
|
||||
|
||||
}
|
||||
} finally {
|
||||
mExternalChange = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private final Handler mMainHandler;
|
||||
|
||||
private final UserTracker.Callback mUserChangedCallback =
|
||||
new UserTracker.Callback() {
|
||||
@Override
|
||||
@@ -274,12 +288,17 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
}
|
||||
};
|
||||
|
||||
@AssistedInject
|
||||
public BrightnessController(
|
||||
Context context,
|
||||
ToggleSlider control,
|
||||
@Assisted ToggleSlider control,
|
||||
UserTracker userTracker,
|
||||
DisplayTracker displayTracker,
|
||||
DisplayManager displayManager,
|
||||
SecureSettings secureSettings,
|
||||
@Nullable IVrManager iVrManager,
|
||||
@Main Executor mainExecutor,
|
||||
@Main Looper mainLooper,
|
||||
@Background Handler bgHandler) {
|
||||
mContext = context;
|
||||
mControl = control;
|
||||
@@ -288,22 +307,23 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
mBackgroundHandler = bgHandler;
|
||||
mUserTracker = userTracker;
|
||||
mDisplayTracker = displayTracker;
|
||||
mBrightnessObserver = new BrightnessObserver(mHandler);
|
||||
|
||||
mSecureSettings = secureSettings;
|
||||
mDisplayId = mContext.getDisplayId();
|
||||
PowerManager pm = context.getSystemService(PowerManager.class);
|
||||
mDisplayManager = displayManager;
|
||||
mVrManager = iVrManager;
|
||||
|
||||
mDisplayManager = context.getSystemService(DisplayManager.class);
|
||||
mVrManager = IVrManager.Stub.asInterface(ServiceManager.getService(
|
||||
Context.VR_SERVICE));
|
||||
mMainHandler = new Handler(mainLooper, mHandlerCallback);
|
||||
mBrightnessObserver = new BrightnessObserver(mMainHandler);
|
||||
}
|
||||
|
||||
public void registerCallbacks() {
|
||||
mBackgroundHandler.removeCallbacks(mStartListeningRunnable);
|
||||
mBackgroundHandler.post(mStartListeningRunnable);
|
||||
}
|
||||
|
||||
/** Unregister all call backs, both to and from the controller */
|
||||
public void unregisterCallbacks() {
|
||||
mBackgroundHandler.removeCallbacks(mStopListeningRunnable);
|
||||
mBackgroundHandler.post(mStopListeningRunnable);
|
||||
mControlValueInitialized = false;
|
||||
}
|
||||
@@ -418,38 +438,12 @@ public class BrightnessController implements ToggleSlider.Listener, MirroredBrig
|
||||
mSliderAnimator.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Factory for creating a {@link BrightnessController}. */
|
||||
public static class Factory {
|
||||
private final Context mContext;
|
||||
private final UserTracker mUserTracker;
|
||||
private final DisplayTracker mDisplayTracker;
|
||||
private final Executor mMainExecutor;
|
||||
private final Handler mBackgroundHandler;
|
||||
|
||||
@Inject
|
||||
public Factory(
|
||||
Context context,
|
||||
UserTracker userTracker,
|
||||
DisplayTracker displayTracker,
|
||||
@Main Executor mainExecutor,
|
||||
@Background Handler bgHandler) {
|
||||
mContext = context;
|
||||
mUserTracker = userTracker;
|
||||
mDisplayTracker = displayTracker;
|
||||
mMainExecutor = mainExecutor;
|
||||
mBackgroundHandler = bgHandler;
|
||||
}
|
||||
|
||||
@AssistedFactory
|
||||
public interface Factory {
|
||||
/** Create a {@link BrightnessController} */
|
||||
public BrightnessController create(ToggleSlider toggleSlider) {
|
||||
return new BrightnessController(
|
||||
mContext,
|
||||
toggleSlider,
|
||||
mUserTracker,
|
||||
mDisplayTracker,
|
||||
mMainExecutor,
|
||||
mBackgroundHandler);
|
||||
}
|
||||
BrightnessController create(ToggleSlider toggleSlider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import static android.view.WindowManagerPolicyConstants.EXTRA_FROM_BRIGHTNESS_KE
|
||||
import android.app.Activity;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
@@ -37,10 +36,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.dagger.qualifiers.Background;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
import com.android.systemui.settings.DisplayTracker;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor;
|
||||
|
||||
@@ -56,26 +52,21 @@ public class BrightnessDialog extends Activity {
|
||||
|
||||
private BrightnessController mBrightnessController;
|
||||
private final BrightnessSliderController.Factory mToggleSliderFactory;
|
||||
private final UserTracker mUserTracker;
|
||||
private final DisplayTracker mDisplayTracker;
|
||||
private final BrightnessController.Factory mBrightnessControllerFactory;
|
||||
private final DelayableExecutor mMainExecutor;
|
||||
private final Handler mBackgroundHandler;
|
||||
private final AccessibilityManagerWrapper mAccessibilityMgr;
|
||||
private Runnable mCancelTimeoutRunnable;
|
||||
|
||||
@Inject
|
||||
public BrightnessDialog(
|
||||
UserTracker userTracker,
|
||||
DisplayTracker displayTracker,
|
||||
BrightnessSliderController.Factory factory,
|
||||
BrightnessSliderController.Factory brightnessSliderfactory,
|
||||
BrightnessController.Factory brightnessControllerFactory,
|
||||
@Main DelayableExecutor mainExecutor,
|
||||
@Background Handler bgHandler,
|
||||
AccessibilityManagerWrapper accessibilityMgr) {
|
||||
mUserTracker = userTracker;
|
||||
mDisplayTracker = displayTracker;
|
||||
mToggleSliderFactory = factory;
|
||||
AccessibilityManagerWrapper accessibilityMgr
|
||||
) {
|
||||
mToggleSliderFactory = brightnessSliderfactory;
|
||||
mBrightnessControllerFactory = brightnessControllerFactory;
|
||||
mMainExecutor = mainExecutor;
|
||||
mBackgroundHandler = bgHandler;
|
||||
mAccessibilityMgr = accessibilityMgr;
|
||||
}
|
||||
|
||||
@@ -121,8 +112,7 @@ public class BrightnessDialog extends Activity {
|
||||
controller.init();
|
||||
frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
|
||||
|
||||
mBrightnessController = new BrightnessController(
|
||||
this, controller, mUserTracker, mDisplayTracker, mMainExecutor, mBackgroundHandler);
|
||||
mBrightnessController = mBrightnessControllerFactory.create(controller);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -154,6 +154,21 @@ class QSPanelControllerTest : SysuiTestCase() {
|
||||
verify(qsPanel).setCanCollapse(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun multipleListeningOnlyCallsBrightnessControllerOnce() {
|
||||
controller.setListening(true, true)
|
||||
controller.setListening(true, false)
|
||||
controller.setListening(true, true)
|
||||
|
||||
verify(brightnessController).registerCallbacks()
|
||||
|
||||
controller.setListening(false, true)
|
||||
controller.setListening(false, false)
|
||||
controller.setListening(false, true)
|
||||
|
||||
verify(brightnessController).unregisterCallbacks()
|
||||
}
|
||||
|
||||
private fun setShouldUseSplitShade(shouldUse: Boolean) {
|
||||
testableResources.addOverride(R.bool.config_use_split_notification_shade, shouldUse)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.systemui.settings.brightness
|
||||
|
||||
import android.hardware.display.DisplayManager
|
||||
import android.os.Handler
|
||||
import android.service.vr.IVrManager
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.settings.DisplayTracker
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.settings.FakeSettings
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper
|
||||
class BrightnessControllerTest : SysuiTestCase() {
|
||||
|
||||
private val executor = FakeExecutor(FakeSystemClock())
|
||||
private val secureSettings = FakeSettings()
|
||||
@Mock private lateinit var toggleSlider: ToggleSlider
|
||||
@Mock private lateinit var userTracker: UserTracker
|
||||
@Mock private lateinit var displayTracker: DisplayTracker
|
||||
@Mock private lateinit var displayManager: DisplayManager
|
||||
@Mock private lateinit var iVrManager: IVrManager
|
||||
|
||||
private lateinit var testableLooper: TestableLooper
|
||||
|
||||
private lateinit var underTest: BrightnessController
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
testableLooper = TestableLooper.get(this)
|
||||
|
||||
underTest =
|
||||
BrightnessController(
|
||||
context,
|
||||
toggleSlider,
|
||||
userTracker,
|
||||
displayTracker,
|
||||
displayManager,
|
||||
secureSettings,
|
||||
iVrManager,
|
||||
executor,
|
||||
mock(),
|
||||
Handler(testableLooper.looper)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun registerCallbacksMultipleTimes_onlyOneRegistration() {
|
||||
val repeats = 100
|
||||
repeat(repeats) { underTest.registerCallbacks() }
|
||||
val messagesProcessed = testableLooper.processMessagesNonBlocking(repeats)
|
||||
|
||||
verify(displayTracker).addBrightnessChangeCallback(any(), any())
|
||||
verify(iVrManager).registerListener(any())
|
||||
|
||||
assertThat(messagesProcessed).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unregisterCallbacksMultipleTimes_onlyOneUnregistration() {
|
||||
val repeats = 100
|
||||
underTest.registerCallbacks()
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
repeat(repeats) { underTest.unregisterCallbacks() }
|
||||
val messagesProcessed = testableLooper.processMessagesNonBlocking(repeats)
|
||||
|
||||
verify(displayTracker).removeCallback(any())
|
||||
verify(iVrManager).unregisterListener(any())
|
||||
|
||||
assertThat(messagesProcessed).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package com.android.systemui.settings.brightness
|
||||
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.os.Handler
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.view.View
|
||||
@@ -29,8 +28,6 @@ import androidx.test.rule.ActivityTestRule
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.activity.SingleActivityFactory
|
||||
import com.android.systemui.settings.FakeDisplayTracker
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper
|
||||
import com.android.systemui.util.concurrency.DelayableExecutor
|
||||
import com.android.systemui.util.concurrency.FakeExecutor
|
||||
@@ -53,28 +50,24 @@ import org.mockito.MockitoAnnotations
|
||||
@TestableLooper.RunWithLooper
|
||||
class BrightnessDialogTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var userTracker: UserTracker
|
||||
@Mock private lateinit var brightnessSliderControllerFactory: BrightnessSliderController.Factory
|
||||
@Mock private lateinit var backgroundHandler: Handler
|
||||
@Mock private lateinit var brightnessSliderController: BrightnessSliderController
|
||||
@Mock private lateinit var brightnessControllerFactory: BrightnessController.Factory
|
||||
@Mock private lateinit var brightnessController: BrightnessController
|
||||
@Mock private lateinit var accessibilityMgr: AccessibilityManagerWrapper
|
||||
|
||||
private val clock = FakeSystemClock()
|
||||
private val mainExecutor = FakeExecutor(clock)
|
||||
|
||||
private var displayTracker = FakeDisplayTracker(mContext)
|
||||
|
||||
@Rule
|
||||
@JvmField
|
||||
var activityRule =
|
||||
ActivityTestRule(
|
||||
/* activityFactory= */ SingleActivityFactory {
|
||||
TestDialog(
|
||||
userTracker,
|
||||
displayTracker,
|
||||
brightnessSliderControllerFactory,
|
||||
brightnessControllerFactory,
|
||||
mainExecutor,
|
||||
backgroundHandler,
|
||||
accessibilityMgr
|
||||
)
|
||||
},
|
||||
@@ -88,6 +81,7 @@ class BrightnessDialogTest : SysuiTestCase() {
|
||||
`when`(brightnessSliderControllerFactory.create(any(), any()))
|
||||
.thenReturn(brightnessSliderController)
|
||||
`when`(brightnessSliderController.rootView).thenReturn(View(context))
|
||||
`when`(brightnessControllerFactory.create(any())).thenReturn(brightnessController)
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -178,19 +172,15 @@ class BrightnessDialogTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
class TestDialog(
|
||||
userTracker: UserTracker,
|
||||
displayTracker: FakeDisplayTracker,
|
||||
brightnessSliderControllerFactory: BrightnessSliderController.Factory,
|
||||
brightnessControllerFactory: BrightnessController.Factory,
|
||||
mainExecutor: DelayableExecutor,
|
||||
backgroundHandler: Handler,
|
||||
accessibilityMgr: AccessibilityManagerWrapper
|
||||
) :
|
||||
BrightnessDialog(
|
||||
userTracker,
|
||||
displayTracker,
|
||||
brightnessSliderControllerFactory,
|
||||
brightnessControllerFactory,
|
||||
mainExecutor,
|
||||
backgroundHandler,
|
||||
accessibilityMgr
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This is a wrapper around {@link TestLooperManager} to make it easier to manage
|
||||
@@ -55,7 +56,6 @@ public class TestableLooper {
|
||||
private MessageHandler mMessageHandler;
|
||||
|
||||
private Handler mHandler;
|
||||
private Runnable mEmptyMessage;
|
||||
private TestLooperManager mQueueWrapper;
|
||||
|
||||
static {
|
||||
@@ -121,14 +121,39 @@ public class TestableLooper {
|
||||
* @param num Number of messages to parse
|
||||
*/
|
||||
public int processMessages(int num) {
|
||||
return processMessagesInternal(num, null);
|
||||
}
|
||||
|
||||
private int processMessagesInternal(int num, Runnable barrierRunnable) {
|
||||
for (int i = 0; i < num; i++) {
|
||||
if (!parseMessageInt()) {
|
||||
if (!processSingleMessage(barrierRunnable)) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process up to a certain number of messages, not blocking if the queue has less messages than
|
||||
* that
|
||||
* @param num the maximum number of messages to process
|
||||
* @return the number of messages processed. This will be at most {@code num}.
|
||||
*/
|
||||
|
||||
public int processMessagesNonBlocking(int num) {
|
||||
final AtomicBoolean reachedBarrier = new AtomicBoolean(false);
|
||||
Runnable barrierRunnable = () -> {
|
||||
reachedBarrier.set(true);
|
||||
};
|
||||
mHandler.post(barrierRunnable);
|
||||
waitForMessage(mQueueWrapper, mHandler, barrierRunnable);
|
||||
try {
|
||||
return processMessagesInternal(num, barrierRunnable) + (reachedBarrier.get() ? -1 : 0);
|
||||
} finally {
|
||||
mHandler.removeCallbacks(barrierRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process messages in the queue until no more are found.
|
||||
*/
|
||||
@@ -165,19 +190,20 @@ public class TestableLooper {
|
||||
|
||||
private int processQueuedMessages() {
|
||||
int count = 0;
|
||||
mEmptyMessage = () -> { };
|
||||
mHandler.post(mEmptyMessage);
|
||||
waitForMessage(mQueueWrapper, mHandler, mEmptyMessage);
|
||||
while (parseMessageInt()) count++;
|
||||
Runnable barrierRunnable = () -> { };
|
||||
mHandler.post(barrierRunnable);
|
||||
waitForMessage(mQueueWrapper, mHandler, barrierRunnable);
|
||||
while (processSingleMessage(barrierRunnable)) count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
private boolean parseMessageInt() {
|
||||
private boolean processSingleMessage(Runnable barrierRunnable) {
|
||||
try {
|
||||
Message result = mQueueWrapper.next();
|
||||
if (result != null) {
|
||||
// This is a break message.
|
||||
if (result.getCallback() == mEmptyMessage) {
|
||||
if (result.getCallback() == barrierRunnable) {
|
||||
mQueueWrapper.execute(result);
|
||||
mQueueWrapper.recycle(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,12 +27,6 @@ import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
@@ -40,6 +34,11 @@ import android.test.suitebuilder.annotation.SmallTest;
|
||||
import android.testing.TestableLooper.MessageHandler;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@RunWithLooper
|
||||
@@ -240,4 +239,33 @@ public class TestableLooperTest {
|
||||
inOrder.verify(handler).dispatchMessage(messageC);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessagesNonBlocking_onlyArgNumber() {
|
||||
Handler h = new Handler(mTestableLooper.getLooper());
|
||||
Runnable r = mock(Runnable.class);
|
||||
|
||||
h.post(r);
|
||||
h.post(r);
|
||||
h.post(r);
|
||||
|
||||
int processed = mTestableLooper.processMessagesNonBlocking(2);
|
||||
|
||||
verify(r, times(2)).run();
|
||||
assertEquals(2, processed);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessMessagesNonBlocking_lessMessagesThanArg() {
|
||||
Handler h = new Handler(mTestableLooper.getLooper());
|
||||
Runnable r = mock(Runnable.class);
|
||||
|
||||
h.post(r);
|
||||
h.post(r);
|
||||
h.post(r);
|
||||
|
||||
int processed = mTestableLooper.processMessagesNonBlocking(5);
|
||||
|
||||
verify(r, times(3)).run();
|
||||
assertEquals(3, processed);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user