1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.wallpaper.module; 17 18 import static android.app.WallpaperManager.FLAG_LOCK; 19 import static android.app.WallpaperManager.FLAG_SYSTEM; 20 21 import static com.android.wallpaper.module.WallpaperPersister.DEST_BOTH; 22 23 import static com.google.common.truth.Truth.assertThat; 24 25 import static org.mockito.Mockito.doReturn; 26 import static org.mockito.Mockito.spy; 27 import static org.robolectric.shadows.ShadowLooper.shadowMainLooper; 28 29 import android.app.WallpaperManager; 30 import android.content.Context; 31 import android.graphics.drawable.BitmapDrawable; 32 import android.util.Log; 33 34 import androidx.annotation.Nullable; 35 import androidx.test.platform.app.InstrumentationRegistry; 36 37 import com.android.wallpaper.model.WallpaperInfo; 38 import com.android.wallpaper.module.DefaultWallpaperPersisterTest.TestSetWallpaperCallback.SetWallpaperStatus; 39 import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback; 40 import com.android.wallpaper.module.logging.TestUserEventLogger; 41 import com.android.wallpaper.testing.FakeDisplaysProvider; 42 import com.android.wallpaper.testing.TestAsset; 43 import com.android.wallpaper.testing.TestBitmapCropper; 44 import com.android.wallpaper.testing.TestCurrentWallpaperInfoFactory; 45 import com.android.wallpaper.testing.TestInjector; 46 import com.android.wallpaper.testing.TestStaticWallpaperInfo; 47 import com.android.wallpaper.testing.TestWallpaperPreferences; 48 import com.android.wallpaper.testing.TestWallpaperStatusChecker; 49 import com.android.wallpaper.util.DisplayUtils; 50 51 import org.junit.Before; 52 import org.junit.Test; 53 import org.junit.runner.RunWith; 54 import org.robolectric.RobolectricTestRunner; 55 import org.robolectric.android.util.concurrent.PausedExecutorService; 56 import org.robolectric.shadows.ShadowPausedAsyncTask; 57 58 import java.util.ArrayList; 59 import java.util.List; 60 61 @RunWith(RobolectricTestRunner.class) 62 public class DefaultWallpaperPersisterTest { 63 private static final String TAG = "DefaultWallpaperPersisterTest"; 64 private static final String ACTION_URL = "http://google.com"; 65 66 private Context mContext; 67 /** DefaultWallpaperPersister object under test */ 68 private DefaultWallpaperPersister mPersister; 69 /** Spy on real WallpaperManager instance */ 70 private WallpaperManager mManager; 71 /** Fake instance of WallpaperPreferences */ 72 private TestWallpaperPreferences mPrefs; 73 /** Executor to use for AsyncTask */ 74 private final PausedExecutorService mPausedExecutor = new PausedExecutorService(); 75 76 @Before setUp()77 public void setUp() { 78 InjectorProvider.setInjector(new TestInjector(new TestUserEventLogger())); 79 mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 80 mManager = spy(WallpaperManager.getInstance(mContext)); 81 mPrefs = new TestWallpaperPreferences(); 82 WallpaperChangedNotifier changedNotifier = spy(WallpaperChangedNotifier.getInstance()); 83 DisplayUtils displayUtils = new DisplayUtils(mContext, new FakeDisplaysProvider(mContext)); 84 TestBitmapCropper cropper = new TestBitmapCropper(); 85 TestWallpaperStatusChecker statusChecker = new TestWallpaperStatusChecker(); 86 TestCurrentWallpaperInfoFactory wallpaperInfoFactory = 87 new TestCurrentWallpaperInfoFactory(mContext); 88 89 mPersister = new DefaultWallpaperPersister(mContext, mManager, mPrefs, changedNotifier, 90 displayUtils, cropper, statusChecker, wallpaperInfoFactory, false); 91 } 92 93 @Test isSeparateLockScreenWallpaperSet_trueIfSet()94 public void isSeparateLockScreenWallpaperSet_trueIfSet() { 95 doReturn(-1).when(mManager).getWallpaperId(FLAG_LOCK); 96 97 assertThat(mPersister.getDefaultWhichWallpaper()).isEqualTo(FLAG_SYSTEM | FLAG_LOCK); 98 } 99 100 @Test isSeparateLockScreenWallpaperSet_falseIfUnset()101 public void isSeparateLockScreenWallpaperSet_falseIfUnset() { 102 doReturn(1).when(mManager).getWallpaperId(FLAG_LOCK); 103 104 assertThat(mPersister.getDefaultWhichWallpaper()).isEqualTo(FLAG_SYSTEM); 105 } 106 107 @Test setBitmapWallpaper_succeeds()108 public void setBitmapWallpaper_succeeds() { 109 TestStaticWallpaperInfo wallpaperInfo = newStaticWallpaperInfo(); 110 prepareWallpaperSetFromInfo(wallpaperInfo); 111 TestSetWallpaperCallback callback = new TestSetWallpaperCallback(); 112 113 mPersister.setIndividualWallpaper(wallpaperInfo, wallpaperInfo.getAsset(mContext), null, 114 1.0f, DEST_BOTH, callback); 115 116 verifyWallpaperSetSuccess(callback); 117 } 118 119 @Test setBitmapWallpaper_setsActionUrl()120 public void setBitmapWallpaper_setsActionUrl() { 121 TestStaticWallpaperInfo wallpaperInfo = newStaticWallpaperInfo(); 122 prepareWallpaperSetFromInfo(wallpaperInfo); 123 TestSetWallpaperCallback callback = new TestSetWallpaperCallback(); 124 125 mPersister.setIndividualWallpaper(wallpaperInfo, wallpaperInfo.getAsset(mContext), null, 126 1.0f, DEST_BOTH, callback); 127 128 verifyWallpaperSetSuccess(callback); 129 assertThat(mPrefs.getHomeWallpaperActionUrl()).isEqualTo(ACTION_URL); 130 assertThat(mPrefs.getLockWallpaperActionUrl()).isEqualTo(ACTION_URL); 131 } 132 133 // Creates a basic test wallpaper info instance. newStaticWallpaperInfo()134 private static TestStaticWallpaperInfo newStaticWallpaperInfo() { 135 List<String> attributions = new ArrayList<>(); 136 attributions.add("Title"); 137 attributions.add("Subtitle 1"); 138 attributions.add("Subtitle 2"); 139 TestStaticWallpaperInfo wallpaperInfo = new TestStaticWallpaperInfo( 140 TestStaticWallpaperInfo.COLOR_DEFAULT); 141 wallpaperInfo.setAttributions(attributions); 142 wallpaperInfo.setCollectionId("collectionStatic"); 143 wallpaperInfo.setWallpaperId("wallpaperStatic"); 144 wallpaperInfo.setActionUrl(ACTION_URL); 145 return wallpaperInfo; 146 } 147 148 // Call this method to prepare for a call to setIndividualWallpaper with non-streamable bitmap. prepareWallpaperSetFromInfo(TestStaticWallpaperInfo wallpaperInfo)149 private void prepareWallpaperSetFromInfo(TestStaticWallpaperInfo wallpaperInfo) { 150 // Retrieve the bitmap to be set by the given WallpaperInfo, and override the return value 151 // from WallpaperManager.getDrawable(). 152 TestAsset asset = (TestAsset) wallpaperInfo.getAsset(mContext); 153 doReturn(new BitmapDrawable(mContext.getResources(), asset.getBitmap())).when(mManager) 154 .getDrawable(); 155 // Override the background executor for AsyncTask to that we can explicitly execute its 156 // tasks - otherwise this will remain in the queue even after main looper idle. 157 ShadowPausedAsyncTask.overrideExecutor(mPausedExecutor); 158 } 159 verifyWallpaperSetSuccess(TestSetWallpaperCallback callback)160 private void verifyWallpaperSetSuccess(TestSetWallpaperCallback callback) { 161 // Execute pending Asset#decodeBitmap; queues SetWallpaperTask background job 162 shadowMainLooper().idle(); 163 // Execute SetWallpaperTask background job; queues onPostExecute on main thread 164 mPausedExecutor.runAll(); 165 // Execute SetWallpaperTask#onPostExecute 166 shadowMainLooper().idle(); 167 168 assertThat(callback.getStatus()).isEqualTo(SetWallpaperStatus.SUCCESS); 169 } 170 171 /** 172 * Simple wallpaper callback to either record success or log on failure. 173 */ 174 static class TestSetWallpaperCallback implements SetWallpaperCallback { 175 enum SetWallpaperStatus { 176 UNCALLED, 177 SUCCESS, 178 FAILURE 179 } 180 SetWallpaperStatus mStatus = SetWallpaperStatus.UNCALLED; 181 @Override onSuccess(WallpaperInfo wallpaperInfo, int destination)182 public void onSuccess(WallpaperInfo wallpaperInfo, int destination) { 183 mStatus = SetWallpaperStatus.SUCCESS; 184 } 185 186 @Override onError(@ullable Throwable throwable)187 public void onError(@Nullable Throwable throwable) { 188 mStatus = SetWallpaperStatus.FAILURE; 189 Log.e(TAG, "Set wallpaper failed", throwable); 190 } 191 getStatus()192 public SetWallpaperStatus getStatus() { 193 return mStatus; 194 } 195 } 196 } 197