Loading packages/SettingsLib/IllustrationPreference/Android.bp +22 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ android_library { "SettingsLibColor", "androidx.preference_preference", "lottie", "settingslib_illustrationpreference_flags_lib", ], sdk_version: "system_current", Loading @@ -31,3 +32,24 @@ android_library { "com.android.permission", ], } aconfig_declarations { name: "settingslib_illustrationpreference_flags", package: "com.android.settingslib.widget.flags", container: "system", srcs: [ "aconfig/illustrationpreference.aconfig", ], } java_aconfig_library { name: "settingslib_illustrationpreference_flags_lib", aconfig_declarations: "settingslib_illustrationpreference_flags", min_sdk_version: "30", apex_available: [ "//apex_available:platform", "com.android.permission", ], } packages/SettingsLib/IllustrationPreference/aconfig/illustrationpreference.aconfig 0 → 100644 +12 −0 Original line number Diff line number Diff line package: "com.android.settingslib.widget.flags" container: "system" flag { name: "auto_hide_empty_lottie_res" namespace: "android_settings" description: "Hides IllustrationPreference when Lottie resource is an empty file" bug: "337873972" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java +24 −2 Original line number Diff line number Diff line Loading @@ -39,12 +39,14 @@ import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; import androidx.vectordrawable.graphics.drawable.Animatable2Compat; import com.android.settingslib.widget.flags.Flags; import com.android.settingslib.widget.preference.illustration.R; import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieDrawable; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** Loading Loading @@ -142,7 +144,7 @@ public class IllustrationPreference extends Preference { illustrationFrame.setLayoutParams(lp); illustrationView.setCacheComposition(mCacheComposition); handleImageWithAnimation(illustrationView); handleImageWithAnimation(illustrationView, illustrationFrame); handleImageFrameMaxHeight(backgroundView, illustrationView); if (mIsAutoScale) { Loading Loading @@ -332,7 +334,8 @@ public class IllustrationPreference extends Preference { } } private void handleImageWithAnimation(LottieAnimationView illustrationView) { private void handleImageWithAnimation(LottieAnimationView illustrationView, ViewGroup container) { if (mImageDrawable != null) { resetAnimations(illustrationView); illustrationView.setImageDrawable(mImageDrawable); Loading @@ -356,6 +359,25 @@ public class IllustrationPreference extends Preference { } if (mImageResId > 0) { if (Flags.autoHideEmptyLottieRes()) { // Check if resource is empty try (InputStream is = illustrationView.getResources() .openRawResource(mImageResId)) { int check = is.read(); // -1 = end of stream. if first read is end of stream, then file is empty if (check == -1) { illustrationView.setVisibility(View.GONE); container.setVisibility(View.GONE); return; } } catch (IOException e) { Log.w(TAG, "Unable to open Lottie raw resource", e); } illustrationView.setVisibility(View.VISIBLE); container.setVisibility(View.VISIBLE); } resetAnimations(illustrationView); illustrationView.setImageResource(mImageResId); final Drawable drawable = illustrationView.getDrawable(); Loading packages/SettingsLib/tests/robotests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ android_robolectric_test { "androidx.core_core", "flag-junit", "settingslib_media_flags_lib", "settingslib_illustrationpreference_flags_lib", "testng", // TODO: remove once JUnit on Android provides assertThrows ], java_resource_dirs: ["config"], Loading packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java +60 −3 Original line number Diff line number Diff line Loading @@ -26,10 +26,14 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.AnimatedImageDrawable; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimationDrawable; import android.net.Uri; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; Loading @@ -39,11 +43,13 @@ import android.widget.ImageView; import androidx.preference.PreferenceViewHolder; import androidx.test.core.app.ApplicationProvider; import com.android.settingslib.widget.flags.Flags; import com.android.settingslib.widget.preference.illustration.R; import com.airbnb.lottie.LottieAnimationView; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -51,10 +57,14 @@ import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import java.io.ByteArrayInputStream; @RunWith(RobolectricTestRunner.class) public class IllustrationPreferenceTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private ViewGroup mRootView; private Uri mImageUri; Loading @@ -66,6 +76,7 @@ public class IllustrationPreferenceTest { private final Context mContext = ApplicationProvider.getApplicationContext(); private IllustrationPreference.OnBindListener mOnBindListener; private LottieAnimationView mOnBindListenerAnimationView; private FrameLayout mIllustrationFrame; @Before public void setUp() { Loading @@ -75,14 +86,14 @@ public class IllustrationPreferenceTest { mBackgroundView = new ImageView(mContext); mAnimationView = spy(new LottieAnimationView(mContext)); mMiddleGroundLayout = new FrameLayout(mContext); final FrameLayout illustrationFrame = new FrameLayout(mContext); illustrationFrame.setLayoutParams( mIllustrationFrame = new FrameLayout(mContext); mIllustrationFrame.setLayoutParams( new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); doReturn(mMiddleGroundLayout).when(mRootView).findViewById(R.id.middleground_layout); doReturn(mBackgroundView).when(mRootView).findViewById(R.id.background_view); doReturn(mAnimationView).when(mRootView).findViewById(R.id.lottie_view); doReturn(illustrationFrame).when(mRootView).findViewById(R.id.illustration_frame); doReturn(mIllustrationFrame).when(mRootView).findViewById(R.id.illustration_frame); mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(mRootView)); final AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); Loading Loading @@ -158,11 +169,13 @@ public class IllustrationPreferenceTest { } @Test @DisableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void playLottieAnimationWithResource_verifyFailureListener() { // fake the valid lottie image final int fakeValidResId = 111; doNothing().when(mAnimationView).setImageResource(fakeValidResId); doReturn(null).when(mAnimationView).getDrawable(); doNothing().when(mAnimationView).setAnimation(fakeValidResId); mPreference.setLottieAnimationResId(fakeValidResId); mPreference.onBindViewHolder(mViewHolder); Loading @@ -170,6 +183,50 @@ public class IllustrationPreferenceTest { verify(mAnimationView).setFailureListener(any()); } @Test @DisableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void handleImageWithAnimation_emptyInputStreamDisabledFlag_verifyContainerVisible() { doNothing().when(mAnimationView).setImageResource(111); doReturn(null).when(mAnimationView).getDrawable(); mPreference.setLottieAnimationResId(111); mPreference.onBindViewHolder(mViewHolder); assertThat(mAnimationView.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mIllustrationFrame.getVisibility()).isEqualTo(View.VISIBLE); } @Test @EnableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void handleImageWithAnimation_emptyInputStreamEnabledFlag_verifyContainerHidden() { Resources res = spy(mContext.getResources()); doReturn(res).when(mAnimationView).getResources(); doReturn(new ByteArrayInputStream(new byte[] {})).when(res).openRawResource(111); mPreference.setLottieAnimationResId(111); mPreference.onBindViewHolder(mViewHolder); assertThat(mAnimationView.getVisibility()).isEqualTo(View.GONE); assertThat(mIllustrationFrame.getVisibility()).isEqualTo(View.GONE); } @Test @EnableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void handleImageWithAnimation_nonEmptyInputStreamEnabledFlag_verifyContainerVisible() { Resources res = spy(mContext.getResources()); doReturn(res).when(mAnimationView).getResources(); doReturn(new ByteArrayInputStream(new byte[] { 1, 2, 3 })).when(res).openRawResource(111); doNothing().when(mAnimationView).setImageResource(111); doNothing().when(mAnimationView).setAnimation(111); doReturn(null).when(mAnimationView).getDrawable(); mPreference.setLottieAnimationResId(111); mPreference.onBindViewHolder(mViewHolder); assertThat(mAnimationView.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mIllustrationFrame.getVisibility()).isEqualTo(View.VISIBLE); } @Test public void setMaxHeight_smallerThanRestrictedHeight_matchResult() { final int restrictedHeight = Loading Loading
packages/SettingsLib/IllustrationPreference/Android.bp +22 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ android_library { "SettingsLibColor", "androidx.preference_preference", "lottie", "settingslib_illustrationpreference_flags_lib", ], sdk_version: "system_current", Loading @@ -31,3 +32,24 @@ android_library { "com.android.permission", ], } aconfig_declarations { name: "settingslib_illustrationpreference_flags", package: "com.android.settingslib.widget.flags", container: "system", srcs: [ "aconfig/illustrationpreference.aconfig", ], } java_aconfig_library { name: "settingslib_illustrationpreference_flags_lib", aconfig_declarations: "settingslib_illustrationpreference_flags", min_sdk_version: "30", apex_available: [ "//apex_available:platform", "com.android.permission", ], }
packages/SettingsLib/IllustrationPreference/aconfig/illustrationpreference.aconfig 0 → 100644 +12 −0 Original line number Diff line number Diff line package: "com.android.settingslib.widget.flags" container: "system" flag { name: "auto_hide_empty_lottie_res" namespace: "android_settings" description: "Hides IllustrationPreference when Lottie resource is an empty file" bug: "337873972" metadata { purpose: PURPOSE_BUGFIX } } No newline at end of file
packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java +24 −2 Original line number Diff line number Diff line Loading @@ -39,12 +39,14 @@ import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; import androidx.vectordrawable.graphics.drawable.Animatable2Compat; import com.android.settingslib.widget.flags.Flags; import com.android.settingslib.widget.preference.illustration.R; import com.airbnb.lottie.LottieAnimationView; import com.airbnb.lottie.LottieDrawable; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** Loading Loading @@ -142,7 +144,7 @@ public class IllustrationPreference extends Preference { illustrationFrame.setLayoutParams(lp); illustrationView.setCacheComposition(mCacheComposition); handleImageWithAnimation(illustrationView); handleImageWithAnimation(illustrationView, illustrationFrame); handleImageFrameMaxHeight(backgroundView, illustrationView); if (mIsAutoScale) { Loading Loading @@ -332,7 +334,8 @@ public class IllustrationPreference extends Preference { } } private void handleImageWithAnimation(LottieAnimationView illustrationView) { private void handleImageWithAnimation(LottieAnimationView illustrationView, ViewGroup container) { if (mImageDrawable != null) { resetAnimations(illustrationView); illustrationView.setImageDrawable(mImageDrawable); Loading @@ -356,6 +359,25 @@ public class IllustrationPreference extends Preference { } if (mImageResId > 0) { if (Flags.autoHideEmptyLottieRes()) { // Check if resource is empty try (InputStream is = illustrationView.getResources() .openRawResource(mImageResId)) { int check = is.read(); // -1 = end of stream. if first read is end of stream, then file is empty if (check == -1) { illustrationView.setVisibility(View.GONE); container.setVisibility(View.GONE); return; } } catch (IOException e) { Log.w(TAG, "Unable to open Lottie raw resource", e); } illustrationView.setVisibility(View.VISIBLE); container.setVisibility(View.VISIBLE); } resetAnimations(illustrationView); illustrationView.setImageResource(mImageResId); final Drawable drawable = illustrationView.getDrawable(); Loading
packages/SettingsLib/tests/robotests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ android_robolectric_test { "androidx.core_core", "flag-junit", "settingslib_media_flags_lib", "settingslib_illustrationpreference_flags_lib", "testng", // TODO: remove once JUnit on Android provides assertThrows ], java_resource_dirs: ["config"], Loading
packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/IllustrationPreferenceTest.java +60 −3 Original line number Diff line number Diff line Loading @@ -26,10 +26,14 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.AnimatedImageDrawable; import android.graphics.drawable.AnimatedVectorDrawable; import android.graphics.drawable.AnimationDrawable; import android.net.Uri; import android.platform.test.annotations.DisableFlags; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; Loading @@ -39,11 +43,13 @@ import android.widget.ImageView; import androidx.preference.PreferenceViewHolder; import androidx.test.core.app.ApplicationProvider; import com.android.settingslib.widget.flags.Flags; import com.android.settingslib.widget.preference.illustration.R; import com.airbnb.lottie.LottieAnimationView; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -51,10 +57,14 @@ import org.mockito.MockitoAnnotations; import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; import java.io.ByteArrayInputStream; @RunWith(RobolectricTestRunner.class) public class IllustrationPreferenceTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); @Mock private ViewGroup mRootView; private Uri mImageUri; Loading @@ -66,6 +76,7 @@ public class IllustrationPreferenceTest { private final Context mContext = ApplicationProvider.getApplicationContext(); private IllustrationPreference.OnBindListener mOnBindListener; private LottieAnimationView mOnBindListenerAnimationView; private FrameLayout mIllustrationFrame; @Before public void setUp() { Loading @@ -75,14 +86,14 @@ public class IllustrationPreferenceTest { mBackgroundView = new ImageView(mContext); mAnimationView = spy(new LottieAnimationView(mContext)); mMiddleGroundLayout = new FrameLayout(mContext); final FrameLayout illustrationFrame = new FrameLayout(mContext); illustrationFrame.setLayoutParams( mIllustrationFrame = new FrameLayout(mContext); mIllustrationFrame.setLayoutParams( new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); doReturn(mMiddleGroundLayout).when(mRootView).findViewById(R.id.middleground_layout); doReturn(mBackgroundView).when(mRootView).findViewById(R.id.background_view); doReturn(mAnimationView).when(mRootView).findViewById(R.id.lottie_view); doReturn(illustrationFrame).when(mRootView).findViewById(R.id.illustration_frame); doReturn(mIllustrationFrame).when(mRootView).findViewById(R.id.illustration_frame); mViewHolder = spy(PreferenceViewHolder.createInstanceForTests(mRootView)); final AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); Loading Loading @@ -158,11 +169,13 @@ public class IllustrationPreferenceTest { } @Test @DisableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void playLottieAnimationWithResource_verifyFailureListener() { // fake the valid lottie image final int fakeValidResId = 111; doNothing().when(mAnimationView).setImageResource(fakeValidResId); doReturn(null).when(mAnimationView).getDrawable(); doNothing().when(mAnimationView).setAnimation(fakeValidResId); mPreference.setLottieAnimationResId(fakeValidResId); mPreference.onBindViewHolder(mViewHolder); Loading @@ -170,6 +183,50 @@ public class IllustrationPreferenceTest { verify(mAnimationView).setFailureListener(any()); } @Test @DisableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void handleImageWithAnimation_emptyInputStreamDisabledFlag_verifyContainerVisible() { doNothing().when(mAnimationView).setImageResource(111); doReturn(null).when(mAnimationView).getDrawable(); mPreference.setLottieAnimationResId(111); mPreference.onBindViewHolder(mViewHolder); assertThat(mAnimationView.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mIllustrationFrame.getVisibility()).isEqualTo(View.VISIBLE); } @Test @EnableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void handleImageWithAnimation_emptyInputStreamEnabledFlag_verifyContainerHidden() { Resources res = spy(mContext.getResources()); doReturn(res).when(mAnimationView).getResources(); doReturn(new ByteArrayInputStream(new byte[] {})).when(res).openRawResource(111); mPreference.setLottieAnimationResId(111); mPreference.onBindViewHolder(mViewHolder); assertThat(mAnimationView.getVisibility()).isEqualTo(View.GONE); assertThat(mIllustrationFrame.getVisibility()).isEqualTo(View.GONE); } @Test @EnableFlags(Flags.FLAG_AUTO_HIDE_EMPTY_LOTTIE_RES) public void handleImageWithAnimation_nonEmptyInputStreamEnabledFlag_verifyContainerVisible() { Resources res = spy(mContext.getResources()); doReturn(res).when(mAnimationView).getResources(); doReturn(new ByteArrayInputStream(new byte[] { 1, 2, 3 })).when(res).openRawResource(111); doNothing().when(mAnimationView).setImageResource(111); doNothing().when(mAnimationView).setAnimation(111); doReturn(null).when(mAnimationView).getDrawable(); mPreference.setLottieAnimationResId(111); mPreference.onBindViewHolder(mViewHolder); assertThat(mAnimationView.getVisibility()).isEqualTo(View.VISIBLE); assertThat(mIllustrationFrame.getVisibility()).isEqualTo(View.VISIBLE); } @Test public void setMaxHeight_smallerThanRestrictedHeight_matchResult() { final int restrictedHeight = Loading