Loading packages/SystemUI/src/com/android/systemui/communal/CommunalSourceMonitor.java +59 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,17 @@ package com.android.systemui.communal; import android.database.ContentObserver; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import androidx.annotation.MainThread; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.util.settings.SecureSettings; import com.google.android.collect.Lists; Loading @@ -31,10 +40,15 @@ import javax.inject.Inject; */ @SysUISingleton public class CommunalSourceMonitor { private static final String TAG = "CommunalSourceMonitor"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); // A list of {@link Callback} that have registered to receive updates. private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList(); private final SecureSettings mSecureSettings; private CommunalSource mCurrentSource; private boolean mCommunalEnabled; private CommunalSource.Callback mSourceCallback = new CommunalSource.Callback() { @Override Loading @@ -46,7 +60,22 @@ public class CommunalSourceMonitor { @VisibleForTesting @Inject public CommunalSourceMonitor() { public CommunalSourceMonitor( @MainThread Handler mainThreadHandler, SecureSettings secureSettings) { mSecureSettings = secureSettings; ContentObserver settingsObserver = new ContentObserver(mainThreadHandler) { @Override public void onChange(boolean selfChange) { reloadSettings(); } }; mSecureSettings.registerContentObserverForUser( Settings.Secure.COMMUNAL_MODE_ENABLED, /* notifyForDescendants= */false, settingsObserver, UserHandle.USER_ALL); reloadSettings(); } /** Loading @@ -62,13 +91,8 @@ public class CommunalSourceMonitor { mCurrentSource = source; // If the new source is valid, inform registered Callbacks of its presence. for (int i = 0; i < mCallbacks.size(); i++) { Callback cb = mCallbacks.get(i).get(); if (cb != null) { cb.onSourceAvailable( mCurrentSource != null ? new WeakReference<>(mCurrentSource) : null); } if (mCommunalEnabled) { executeOnSourceAvailableCallbacks(); } // Add callback to be informed when the source disconnects. Loading @@ -77,6 +101,18 @@ public class CommunalSourceMonitor { } } private void executeOnSourceAvailableCallbacks() { // If the new source is valid, inform registered Callbacks of its presence. for (WeakReference<Callback> callback : mCallbacks) { Callback cb = callback.get(); if (cb != null) { cb.onSourceAvailable( (mCommunalEnabled && mCurrentSource != null) ? new WeakReference<>( mCurrentSource) : null); } } } /** * Adds a {@link Callback} to receive {@link CommunalSource} updates. * Loading @@ -86,7 +122,7 @@ public class CommunalSourceMonitor { mCallbacks.add(new WeakReference<>(callback)); // Inform the callback of any already present CommunalSource. if (mCurrentSource != null) { if (mCommunalEnabled && mCurrentSource != null) { callback.onSourceAvailable(new WeakReference<>(mCurrentSource)); } } Loading @@ -100,6 +136,20 @@ public class CommunalSourceMonitor { mCallbacks.removeIf(el -> el.get() == callback); } private void reloadSettings() { boolean newCommunalEnabled = mSecureSettings.getInt(Settings.Secure.COMMUNAL_MODE_ENABLED, 1) == 1; if (DEBUG) { Log.d(TAG, "communal mode settings reloaded with value:" + newCommunalEnabled); } if (mCommunalEnabled != newCommunalEnabled) { mCommunalEnabled = newCommunalEnabled; executeOnSourceAvailableCallbacks(); } } /** * Interface implemented to be notified when new {@link CommunalSource} become available. */ Loading packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourceMonitorTest.java 0 → 100644 +151 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.communal; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Handler; import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.util.settings.FakeSettings; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.MockitoAnnotations; import java.lang.ref.WeakReference; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class CommunalSourceMonitorTest extends SysuiTestCase { private CommunalSourceMonitor mCommunalSourceMonitor; private FakeSettings mSecureSettings; @Before public void setup() { MockitoAnnotations.initMocks(this); mSecureSettings = new FakeSettings(); mCommunalSourceMonitor = new CommunalSourceMonitor( Handler.createAsync(TestableLooper.get(this).getLooper()), mSecureSettings); } @Test public void testSourceAddedBeforeCallbackAdded() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.setSource(source); mCommunalSourceMonitor.addCallback(callback); verifyOnSourceAvailableCalledWith(callback, source); } @Test public void testRemoveCallback() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.removeCallback(callback); mCommunalSourceMonitor.setSource(source); verify(callback, never()).onSourceAvailable(any()); } @Test public void testAddCallbackWithDefaultSetting() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); verifyOnSourceAvailableCalledWith(callback, source); } @Test public void testAddCallbackWithSettingDisabled() { setCommunalEnabled(false); final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); verify(callback, never()).onSourceAvailable(any()); } @Test public void testSettingEnabledAfterCallbackAdded() { setCommunalEnabled(false); final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); // The callback should not have executed since communal is disabled. verify(callback, never()).onSourceAvailable(any()); // The callback should execute when the user changes the setting to enabled. setCommunalEnabled(true); verifyOnSourceAvailableCalledWith(callback, source); } @Test public void testSettingDisabledAfterCallbackAdded() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); verifyOnSourceAvailableCalledWith(callback, source); // The callback should execute again when the setting is disabled, with a value of null. setCommunalEnabled(false); verify(callback).onSourceAvailable(null); } private void setCommunalEnabled(boolean enabled) { mSecureSettings.putInt(Settings.Secure.COMMUNAL_MODE_ENABLED, enabled ? 1 : 0); TestableLooper.get(this).processAllMessages(); } private void verifyOnSourceAvailableCalledWith(CommunalSourceMonitor.Callback callback, CommunalSource source) { final ArgumentCaptor<WeakReference<CommunalSource>> sourceCapture = ArgumentCaptor.forClass(WeakReference.class); verify(callback).onSourceAvailable(sourceCapture.capture()); assertThat(sourceCapture.getValue().get()).isEqualTo(source); } } Loading
packages/SystemUI/src/com/android/systemui/communal/CommunalSourceMonitor.java +59 −9 Original line number Diff line number Diff line Loading @@ -16,8 +16,17 @@ package com.android.systemui.communal; import android.database.ContentObserver; import android.os.Handler; import android.os.UserHandle; import android.provider.Settings; import android.util.Log; import androidx.annotation.MainThread; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.util.settings.SecureSettings; import com.google.android.collect.Lists; Loading @@ -31,10 +40,15 @@ import javax.inject.Inject; */ @SysUISingleton public class CommunalSourceMonitor { private static final String TAG = "CommunalSourceMonitor"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); // A list of {@link Callback} that have registered to receive updates. private final ArrayList<WeakReference<Callback>> mCallbacks = Lists.newArrayList(); private final SecureSettings mSecureSettings; private CommunalSource mCurrentSource; private boolean mCommunalEnabled; private CommunalSource.Callback mSourceCallback = new CommunalSource.Callback() { @Override Loading @@ -46,7 +60,22 @@ public class CommunalSourceMonitor { @VisibleForTesting @Inject public CommunalSourceMonitor() { public CommunalSourceMonitor( @MainThread Handler mainThreadHandler, SecureSettings secureSettings) { mSecureSettings = secureSettings; ContentObserver settingsObserver = new ContentObserver(mainThreadHandler) { @Override public void onChange(boolean selfChange) { reloadSettings(); } }; mSecureSettings.registerContentObserverForUser( Settings.Secure.COMMUNAL_MODE_ENABLED, /* notifyForDescendants= */false, settingsObserver, UserHandle.USER_ALL); reloadSettings(); } /** Loading @@ -62,13 +91,8 @@ public class CommunalSourceMonitor { mCurrentSource = source; // If the new source is valid, inform registered Callbacks of its presence. for (int i = 0; i < mCallbacks.size(); i++) { Callback cb = mCallbacks.get(i).get(); if (cb != null) { cb.onSourceAvailable( mCurrentSource != null ? new WeakReference<>(mCurrentSource) : null); } if (mCommunalEnabled) { executeOnSourceAvailableCallbacks(); } // Add callback to be informed when the source disconnects. Loading @@ -77,6 +101,18 @@ public class CommunalSourceMonitor { } } private void executeOnSourceAvailableCallbacks() { // If the new source is valid, inform registered Callbacks of its presence. for (WeakReference<Callback> callback : mCallbacks) { Callback cb = callback.get(); if (cb != null) { cb.onSourceAvailable( (mCommunalEnabled && mCurrentSource != null) ? new WeakReference<>( mCurrentSource) : null); } } } /** * Adds a {@link Callback} to receive {@link CommunalSource} updates. * Loading @@ -86,7 +122,7 @@ public class CommunalSourceMonitor { mCallbacks.add(new WeakReference<>(callback)); // Inform the callback of any already present CommunalSource. if (mCurrentSource != null) { if (mCommunalEnabled && mCurrentSource != null) { callback.onSourceAvailable(new WeakReference<>(mCurrentSource)); } } Loading @@ -100,6 +136,20 @@ public class CommunalSourceMonitor { mCallbacks.removeIf(el -> el.get() == callback); } private void reloadSettings() { boolean newCommunalEnabled = mSecureSettings.getInt(Settings.Secure.COMMUNAL_MODE_ENABLED, 1) == 1; if (DEBUG) { Log.d(TAG, "communal mode settings reloaded with value:" + newCommunalEnabled); } if (mCommunalEnabled != newCommunalEnabled) { mCommunalEnabled = newCommunalEnabled; executeOnSourceAvailableCallbacks(); } } /** * Interface implemented to be notified when new {@link CommunalSource} become available. */ Loading
packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourceMonitorTest.java 0 → 100644 +151 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.communal; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Handler; import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.util.settings.FakeSettings; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.MockitoAnnotations; import java.lang.ref.WeakReference; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper public class CommunalSourceMonitorTest extends SysuiTestCase { private CommunalSourceMonitor mCommunalSourceMonitor; private FakeSettings mSecureSettings; @Before public void setup() { MockitoAnnotations.initMocks(this); mSecureSettings = new FakeSettings(); mCommunalSourceMonitor = new CommunalSourceMonitor( Handler.createAsync(TestableLooper.get(this).getLooper()), mSecureSettings); } @Test public void testSourceAddedBeforeCallbackAdded() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.setSource(source); mCommunalSourceMonitor.addCallback(callback); verifyOnSourceAvailableCalledWith(callback, source); } @Test public void testRemoveCallback() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.removeCallback(callback); mCommunalSourceMonitor.setSource(source); verify(callback, never()).onSourceAvailable(any()); } @Test public void testAddCallbackWithDefaultSetting() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); verifyOnSourceAvailableCalledWith(callback, source); } @Test public void testAddCallbackWithSettingDisabled() { setCommunalEnabled(false); final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); verify(callback, never()).onSourceAvailable(any()); } @Test public void testSettingEnabledAfterCallbackAdded() { setCommunalEnabled(false); final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); // The callback should not have executed since communal is disabled. verify(callback, never()).onSourceAvailable(any()); // The callback should execute when the user changes the setting to enabled. setCommunalEnabled(true); verifyOnSourceAvailableCalledWith(callback, source); } @Test public void testSettingDisabledAfterCallbackAdded() { final CommunalSourceMonitor.Callback callback = mock(CommunalSourceMonitor.Callback.class); final CommunalSource source = mock(CommunalSource.class); mCommunalSourceMonitor.addCallback(callback); mCommunalSourceMonitor.setSource(source); verifyOnSourceAvailableCalledWith(callback, source); // The callback should execute again when the setting is disabled, with a value of null. setCommunalEnabled(false); verify(callback).onSourceAvailable(null); } private void setCommunalEnabled(boolean enabled) { mSecureSettings.putInt(Settings.Secure.COMMUNAL_MODE_ENABLED, enabled ? 1 : 0); TestableLooper.get(this).processAllMessages(); } private void verifyOnSourceAvailableCalledWith(CommunalSourceMonitor.Callback callback, CommunalSource source) { final ArgumentCaptor<WeakReference<CommunalSource>> sourceCapture = ArgumentCaptor.forClass(WeakReference.class); verify(callback).onSourceAvailable(sourceCapture.capture()); assertThat(sourceCapture.getValue().get()).isEqualTo(source); } }