diff options
author | Julia Sullivan <juliansull@google.com> | 2024-05-07 11:28:12 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-05-07 11:30:08 -0700 |
commit | 87a666523229bbb9b0ee9d2d560ee0ebf24ae79e (patch) | |
tree | 763ca2de1887579018cb49d53e2e04f290233f64 | |
parent | 6aecbb4b15e7d33ae684c0e9b110230ec830e182 (diff) | |
download | robolectric-87a666523229bbb9b0ee9d2d560ee0ebf24ae79e.tar.gz |
Rewrites ShadowCaptioningManager so it uses more real code.
Before, this would fake out some, but not all of the functionality of
ShadowCaptioningManager. This lead to a disjointed Shadow. This now has users update
the Settings.Secure as they would on real android and only shadows functions
that call into AccessibilityManager since that calls into a service.
PiperOrigin-RevId: 631491210
-rw-r--r-- | robolectric/src/test/java/org/robolectric/shadows/ShadowCaptioningManagerTest.java | 155 | ||||
-rw-r--r-- | shadows/framework/src/main/java/org/robolectric/shadows/ShadowCaptioningManager.java | 80 |
2 files changed, 140 insertions, 95 deletions
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowCaptioningManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowCaptioningManagerTest.java index 470eeff75..bb9e408fd 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowCaptioningManagerTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowCaptioningManagerTest.java @@ -1,31 +1,81 @@ package org.robolectric.shadows; +import static android.os.Build.VERSION_CODES.KITKAT; +import static android.os.Build.VERSION_CODES.TIRAMISU; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.robolectric.Shadows.shadowOf; import android.content.Context; +import android.os.Looper; +import android.provider.Settings; +import android.provider.Settings.Secure; import android.view.accessibility.CaptioningManager; +import android.view.accessibility.CaptioningManager.CaptionStyle; import android.view.accessibility.CaptioningManager.CaptioningChangeListener; +import androidx.annotation.NonNull; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import java.util.Locale; +import javax.annotation.Nullable; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; /** Tests for the ShadowCaptioningManager. */ @RunWith(AndroidJUnit4.class) -@Config(minSdk = 19) +@Config(minSdk = KITKAT) public final class ShadowCaptioningManagerTest { - @Mock private CaptioningChangeListener captioningChangeListener; + private TestCaptioningChangeListener captioningChangeListener = + new TestCaptioningChangeListener(); + + private static final int ENABLED = 1; + private static final int DISABLED = 0; private CaptioningManager captioningManager; + private Context context; + + public class TestCaptioningChangeListener extends CaptioningChangeListener { + public boolean isEnabled = false; + @Nullable public CaptionStyle captionStyle = null; + @Nullable public Locale locale = null; + public float fontScale = 1.0f; + public boolean systemAudioCaptioningEnabled = false; + public boolean systemAudioCaptioningUiEnabled = false; + + @Override + public void onEnabledChanged(boolean enabled) { + isEnabled = enabled; + } + + @Override + public void onUserStyleChanged(@NonNull CaptionStyle userStyle) { + captionStyle = userStyle; + } + + @Override + public void onLocaleChanged(@Nullable Locale locale) { + this.locale = locale; + } + + @Override + public void onFontScaleChanged(float fontScale) { + this.fontScale = fontScale; + } + + @Override + public void onSystemAudioCaptioningChanged(boolean enabled) { + this.systemAudioCaptioningEnabled = enabled; + } + + @Override + public void onSystemAudioCaptioningUiChanged(boolean enabled) { + this.systemAudioCaptioningUiEnabled = enabled; + } + } @Before public void setUp() { @@ -34,87 +84,106 @@ public final class ShadowCaptioningManagerTest { (CaptioningManager) ApplicationProvider.getApplicationContext() .getSystemService(Context.CAPTIONING_SERVICE); + context = RuntimeEnvironment.getApplication(); } @Test public void setEnabled_true() { - assertThat(captioningManager.isEnabled()).isFalse(); - - shadowOf(captioningManager).setEnabled(true); + Settings.Secure.putInt( + context.getContentResolver(), Secure.ACCESSIBILITY_CAPTIONING_ENABLED, ENABLED); assertThat(captioningManager.isEnabled()).isTrue(); } @Test public void setEnabled_false() { - shadowOf(captioningManager).setEnabled(false); + Settings.Secure.putInt( + context.getContentResolver(), Secure.ACCESSIBILITY_CAPTIONING_ENABLED, DISABLED); assertThat(captioningManager.isEnabled()).isFalse(); } @Test - public void setFontScale_changesValueOfGetFontScale() { - float fontScale = 1.5f; - shadowOf(captioningManager).setFontScale(fontScale); + public void setEnabled_callsCallback() { + captioningManager.addCaptioningChangeListener(captioningChangeListener); + Settings.Secure.putInt( + context.getContentResolver(), Secure.ACCESSIBILITY_CAPTIONING_ENABLED, ENABLED); - assertThat(captioningManager.getFontScale()).isWithin(0.001f).of(fontScale); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(captioningChangeListener.isEnabled).isTrue(); } @Test - public void setFontScale_notifiesObservers() { - float fontScale = 1.5f; - captioningManager.addCaptioningChangeListener(captioningChangeListener); - - shadowOf(captioningManager).setFontScale(fontScale); + public void setFontScale_updatesValue() { + Settings.Secure.putFloat( + context.getContentResolver(), Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, 2.0f); - verify(captioningChangeListener).onFontScaleChanged(fontScale); + assertThat(captioningManager.getFontScale()).isEqualTo(2.0f); } @Test - public void addCaptioningChangeListener_doesNotRegisterSameListenerTwice() { - float fontScale = 1.5f; + public void setFontScale_callsCallback() { captioningManager.addCaptioningChangeListener(captioningChangeListener); + Settings.Secure.putFloat( + context.getContentResolver(), Secure.ACCESSIBILITY_CAPTIONING_FONT_SCALE, 3.0f); - captioningManager.addCaptioningChangeListener(captioningChangeListener); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(captioningChangeListener.fontScale).isEqualTo(3.0f); + } - shadowOf(captioningManager).setFontScale(fontScale); - verify(captioningChangeListener).onFontScaleChanged(fontScale); + @Test + public void setLocale_updatesValue() { + Settings.Secure.putString( + context.getContentResolver(), + Secure.ACCESSIBILITY_CAPTIONING_LOCALE, + Locale.JAPANESE.toLanguageTag()); + + assertThat(captioningManager.getLocale()).isEqualTo(Locale.JAPANESE); } @Test - public void removeCaptioningChangeListener_unregistersFontScaleListener() { + public void setLocale_callsCallback() { captioningManager.addCaptioningChangeListener(captioningChangeListener); + Settings.Secure.putString( + context.getContentResolver(), + Secure.ACCESSIBILITY_CAPTIONING_LOCALE, + Locale.FRENCH.toLanguageTag()); - captioningManager.removeCaptioningChangeListener(captioningChangeListener); - - shadowOf(captioningManager).setFontScale(1.5f); - verifyNoMoreInteractions(captioningChangeListener); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(captioningChangeListener.locale).isEqualTo(Locale.FRENCH); } @Test - public void setLocale_nonNull() { - Locale locale = Locale.US; - assertThat(captioningManager.getLocale()).isNull(); - - shadowOf(captioningManager).setLocale(locale); + @Config(minSdk = TIRAMISU) + public void setSystemAudioCaptioningEnabled_updatesValue() { + captioningManager.setSystemAudioCaptioningEnabled(true); - assertThat(captioningManager.getLocale()).isEqualTo(locale); + assertThat(captioningManager.isSystemAudioCaptioningEnabled()).isEqualTo(true); } @Test - public void setLocale_null() { - shadowOf(captioningManager).setLocale(null); + @Config(minSdk = TIRAMISU) + public void setSystemAudioCaptioningEnabled_callsCallback() { + captioningManager.setSystemAudioCaptioningEnabled(false); - assertThat(captioningManager.getLocale()).isNull(); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(captioningChangeListener.systemAudioCaptioningEnabled).isEqualTo(false); } @Test - public void setLocale_notifiesObservers() { - Locale locale = Locale.US; - captioningManager.addCaptioningChangeListener(captioningChangeListener); + @Config(minSdk = TIRAMISU) + public void setSystemAudioCaptioningUiEnabled_updatesValue() { + captioningManager.setSystemAudioCaptioningUiEnabled(true); + + assertThat(captioningManager.isSystemAudioCaptioningUiEnabled()).isEqualTo(true); + } - shadowOf(captioningManager).setLocale(locale); + @Test + @Config(minSdk = TIRAMISU) + public void setSystemAudioCaptioningUiEnabled_callsCallback() { + captioningManager.setSystemAudioCaptioningUiEnabled(false); - verify(captioningChangeListener).onLocaleChanged(locale); + shadowOf(Looper.getMainLooper()).idle(); + assertThat(captioningChangeListener.systemAudioCaptioningUiEnabled).isEqualTo(false); } } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCaptioningManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCaptioningManager.java index 19762d193..203e43968 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCaptioningManager.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowCaptioningManager.java @@ -1,72 +1,48 @@ package org.robolectric.shadows; -import android.annotation.NonNull; -import android.util.ArraySet; +import static android.os.Build.VERSION_CODES.TIRAMISU; +import static org.robolectric.util.reflector.Reflector.reflector; + +import android.content.ContentResolver; +import android.provider.Settings; import android.view.accessibility.CaptioningManager; -import android.view.accessibility.CaptioningManager.CaptioningChangeListener; -import java.util.Locale; -import javax.annotation.Nullable; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.annotation.RealObject; +import org.robolectric.util.reflector.Accessor; +import org.robolectric.util.reflector.ForType; /** Shadow of {@link android.view.accessibility.CaptioningManager}. */ @Implements(CaptioningManager.class) public class ShadowCaptioningManager { - private float fontScale = 1; - private boolean isEnabled = false; - @Nullable private Locale locale; - - private final ArraySet<CaptioningChangeListener> listeners = new ArraySet<>(); - - /** Returns 1.0 as default or the most recent value passed to {@link #setFontScale()} */ - @Implementation(minSdk = 19) - protected float getFontScale() { - return fontScale; - } - - /** Sets the value to be returned by {@link CaptioningManager#getFontScale()} */ - public void setFontScale(float fontScale) { - this.fontScale = fontScale; + @RealObject private CaptioningManager realCaptioningManager; - for (CaptioningChangeListener captioningChangeListener : listeners) { - captioningChangeListener.onFontScaleChanged(fontScale); - } + @Implementation(minSdk = TIRAMISU) + protected void setSystemAudioCaptioningEnabled(boolean isEnabled) { + Settings.Secure.putInt( + getContentResolver(), Settings.Secure.ODI_CAPTIONS_ENABLED, isEnabled ? 1 : 0); } - /** Returns false or the most recent value passed to {@link #setEnabled(boolean)} */ - @Implementation(minSdk = 19) - protected boolean isEnabled() { - return isEnabled; + @Implementation(minSdk = TIRAMISU) + protected void setSystemAudioCaptioningUiEnabled(boolean isEnabled) { + Settings.Secure.putInt( + getContentResolver(), Settings.Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED, isEnabled ? 1 : 0); } - /** Sets the value to be returned by {@link CaptioningManager#isEnabled()} */ - public void setEnabled(boolean isEnabled) { - this.isEnabled = isEnabled; + @Implementation(minSdk = TIRAMISU) + protected boolean isSystemAudioCaptioningUiEnabled() { + return Settings.Secure.getInt( + getContentResolver(), Settings.Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED, 1) + == 1; } - @Implementation(minSdk = 19) - protected void addCaptioningChangeListener(@NonNull CaptioningChangeListener listener) { - listeners.add(listener); + private ContentResolver getContentResolver() { + return reflector(CaptioningManagerReflector.class, realCaptioningManager).getContentResolver(); } - @Implementation(minSdk = 19) - protected void removeCaptioningChangeListener(@NonNull CaptioningChangeListener listener) { - listeners.remove(listener); - } - - /** Returns null or the most recent value passed to {@link #setLocale(Locale)} */ - @Implementation(minSdk = 19) - @Nullable - protected Locale getLocale() { - return locale; - } - - /** Sets the value to be returned by {@link CaptioningManager#getLocale()} */ - public void setLocale(@Nullable Locale locale) { - this.locale = locale; - - for (CaptioningChangeListener captioningChangeListener : listeners) { - captioningChangeListener.onLocaleChanged(locale); - } + @ForType(CaptioningManager.class) + interface CaptioningManagerReflector { + @Accessor("mContentResolver") + ContentResolver getContentResolver(); } } |