• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher;
26 
27 import static org.mockito.Mockito.doReturn;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.spy;
30 import static org.robolectric.shadows.ShadowLooper.shadowMainLooper;
31 
32 import android.app.WallpaperManager;
33 import android.content.Context;
34 import android.graphics.drawable.BitmapDrawable;
35 import android.util.Log;
36 
37 import androidx.annotation.Nullable;
38 import androidx.test.platform.app.InstrumentationRegistry;
39 
40 import com.android.wallpaper.model.WallpaperInfo;
41 import com.android.wallpaper.module.DefaultWallpaperPersisterTest.TestSetWallpaperCallback.SetWallpaperStatus;
42 import com.android.wallpaper.module.WallpaperPersister.SetWallpaperCallback;
43 import com.android.wallpaper.module.logging.TestUserEventLogger;
44 import com.android.wallpaper.network.Requester;
45 import com.android.wallpaper.picker.category.wrapper.WallpaperCategoryWrapper;
46 import com.android.wallpaper.picker.customization.data.repository.WallpaperRepository;
47 import com.android.wallpaper.picker.customization.domain.interactor.WallpaperInteractor;
48 import com.android.wallpaper.testing.FakeCurrentWallpaperInfoFactory;
49 import com.android.wallpaper.testing.FakeDisplaysProvider;
50 import com.android.wallpaper.testing.FakeWallpaperClient;
51 import com.android.wallpaper.testing.FakeWallpaperRefresher;
52 import com.android.wallpaper.testing.TestAsset;
53 import com.android.wallpaper.testing.TestBitmapCropper;
54 import com.android.wallpaper.testing.TestInjector;
55 import com.android.wallpaper.testing.TestPackageStatusNotifier;
56 import com.android.wallpaper.testing.TestStaticWallpaperInfo;
57 import com.android.wallpaper.testing.TestWallpaperPreferences;
58 import com.android.wallpaper.testing.TestWallpaperStatusChecker;
59 import com.android.wallpaper.util.DisplayUtils;
60 import com.android.wallpaper.util.DisplaysProvider;
61 
62 import kotlinx.coroutines.test.TestDispatcher;
63 import kotlinx.coroutines.test.TestScope;
64 import kotlinx.coroutines.test.TestScopeKt;
65 
66 import org.junit.Before;
67 import org.junit.Test;
68 import org.junit.runner.RunWith;
69 import org.robolectric.RobolectricTestRunner;
70 import org.robolectric.android.util.concurrent.PausedExecutorService;
71 import org.robolectric.shadows.ShadowPausedAsyncTask;
72 
73 import java.util.ArrayList;
74 import java.util.List;
75 
76 
77 @RunWith(RobolectricTestRunner.class)
78 public class DefaultWallpaperPersisterTest {
79     private static final String TAG = "DefaultWallpaperPersisterTest";
80     private static final String ACTION_URL = "http://google.com";
81 
82     private Context mContext;
83     /** DefaultWallpaperPersister object under test */
84     private DefaultWallpaperPersister mPersister;
85     /** Spy on real WallpaperManager instance  */
86     private WallpaperManager mManager;
87     /** Fake instance of WallpaperPreferences */
88     private TestWallpaperPreferences mPrefs;
89     /** Executor to use for AsyncTask */
90     private final PausedExecutorService mPausedExecutor = new PausedExecutorService();
91 
92     private TestPackageStatusNotifier mTestPackageStatusNotifier;
93 
94     @Before
setUp()95     public void setUp() {
96         mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
97 
98         mManager = spy(WallpaperManager.getInstance(mContext));
99         mPrefs = new TestWallpaperPreferences();
100         WallpaperChangedNotifier changedNotifier = spy(WallpaperChangedNotifier.getInstance());
101         DisplayUtils displayUtils = new DisplayUtils(mContext, new FakeDisplaysProvider(mContext));
102         TestBitmapCropper cropper = new TestBitmapCropper();
103         TestWallpaperStatusChecker statusChecker = new TestWallpaperStatusChecker();
104         TestDispatcher testDispatcher = StandardTestDispatcher(null, null);
105         TestScope testScope = TestScopeKt.TestScope(testDispatcher);
106         mTestPackageStatusNotifier = new TestPackageStatusNotifier();
107         WallpaperInteractor wallpaperInteractor =
108                 new WallpaperInteractor(
109                         new WallpaperRepository(
110                                 testScope.getBackgroundScope(),
111                                 new FakeWallpaperClient(),
112                                 new TestWallpaperPreferences(),
113                                 testDispatcher
114                         )
115                 );
116         FakeWallpaperRefresher refresher = new FakeWallpaperRefresher(mPrefs);
117         FakeCurrentWallpaperInfoFactory wallpaperInfoFactory =
118                 new FakeCurrentWallpaperInfoFactory(refresher);
119 
120         InjectorProvider.setInjector(new TestInjector(
121                 new TestUserEventLogger(),
122                 new DisplayUtils(mContext, mock(DisplaysProvider.class)),
123                 mock(Requester.class),
124                 mock(NetworkStatusNotifier.class),
125                 mock(PartnerProvider.class),
126                 new FakeWallpaperClient(),
127                 wallpaperInteractor,
128                 mPrefs,
129                 mock(WallpaperCategoryWrapper.class),
130                 mTestPackageStatusNotifier,
131                 wallpaperInfoFactory,
132                 refresher
133         ));
134 
135 
136         mPersister = new DefaultWallpaperPersister(mContext, mManager, mPrefs, changedNotifier,
137                 displayUtils, cropper, statusChecker, wallpaperInfoFactory, false);
138     }
139 
140     @Test
isSeparateLockScreenWallpaperSet_trueIfSet()141     public void isSeparateLockScreenWallpaperSet_trueIfSet() {
142         doReturn(-1).when(mManager).getWallpaperId(FLAG_LOCK);
143 
144         assertThat(mPersister.getDefaultWhichWallpaper()).isEqualTo(FLAG_SYSTEM | FLAG_LOCK);
145     }
146 
147     @Test
isSeparateLockScreenWallpaperSet_falseIfUnset()148     public void isSeparateLockScreenWallpaperSet_falseIfUnset() {
149         doReturn(1).when(mManager).getWallpaperId(FLAG_LOCK);
150 
151         assertThat(mPersister.getDefaultWhichWallpaper()).isEqualTo(FLAG_SYSTEM);
152     }
153 
154     @Test
setBitmapWallpaper_succeeds()155     public void setBitmapWallpaper_succeeds() {
156         TestStaticWallpaperInfo wallpaperInfo = newStaticWallpaperInfo();
157         prepareWallpaperSetFromInfo(wallpaperInfo);
158         TestSetWallpaperCallback callback = new TestSetWallpaperCallback();
159 
160         mPersister.setIndividualWallpaper(wallpaperInfo, wallpaperInfo.getAsset(mContext), null,
161                 1.0f, DEST_BOTH, callback);
162 
163         verifyWallpaperSetSuccess(callback);
164     }
165 
166     @Test
setBitmapWallpaper_setsActionUrl()167     public void setBitmapWallpaper_setsActionUrl() {
168         TestStaticWallpaperInfo wallpaperInfo = newStaticWallpaperInfo();
169         prepareWallpaperSetFromInfo(wallpaperInfo);
170         TestSetWallpaperCallback callback = new TestSetWallpaperCallback();
171 
172         mPersister.setIndividualWallpaper(wallpaperInfo, wallpaperInfo.getAsset(mContext), null,
173                 1.0f, DEST_BOTH, callback);
174 
175         verifyWallpaperSetSuccess(callback);
176         assertThat(mPrefs.getHomeWallpaperActionUrl()).isEqualTo(ACTION_URL);
177         assertThat(mPrefs.getLockWallpaperActionUrl()).isEqualTo(ACTION_URL);
178     }
179 
180      // Creates a basic test wallpaper info instance.
newStaticWallpaperInfo()181     private static TestStaticWallpaperInfo newStaticWallpaperInfo() {
182         List<String> attributions = new ArrayList<>();
183         attributions.add("Title");
184         attributions.add("Subtitle 1");
185         attributions.add("Subtitle 2");
186         TestStaticWallpaperInfo wallpaperInfo = new TestStaticWallpaperInfo(
187                 TestStaticWallpaperInfo.COLOR_DEFAULT);
188         wallpaperInfo.setAttributions(attributions);
189         wallpaperInfo.setCollectionId("collectionStatic");
190         wallpaperInfo.setWallpaperId("wallpaperStatic");
191         wallpaperInfo.setActionUrl(ACTION_URL);
192         return wallpaperInfo;
193     }
194 
195     // Call this method to prepare for a call to setIndividualWallpaper with non-streamable bitmap.
prepareWallpaperSetFromInfo(TestStaticWallpaperInfo wallpaperInfo)196     private void prepareWallpaperSetFromInfo(TestStaticWallpaperInfo wallpaperInfo) {
197         // Retrieve the bitmap to be set by the given WallpaperInfo, and override the return value
198         // from WallpaperManager.getDrawable().
199         TestAsset asset = (TestAsset) wallpaperInfo.getAsset(mContext);
200         doReturn(new BitmapDrawable(mContext.getResources(), asset.getBitmap())).when(mManager)
201                 .getDrawable();
202         // Override the background executor for AsyncTask to that we can explicitly execute its
203         // tasks - otherwise this will remain in the queue even after main looper idle.
204         ShadowPausedAsyncTask.overrideExecutor(mPausedExecutor);
205     }
206 
verifyWallpaperSetSuccess(TestSetWallpaperCallback callback)207     private void verifyWallpaperSetSuccess(TestSetWallpaperCallback callback) {
208         // Execute pending Asset#decodeBitmap; queues SetWallpaperTask background job
209         shadowMainLooper().idle();
210         // Execute SetWallpaperTask background job; queues onPostExecute on main thread
211         mPausedExecutor.runAll();
212         // Execute SetWallpaperTask#onPostExecute
213         shadowMainLooper().idle();
214 
215         assertThat(callback.getStatus()).isEqualTo(SetWallpaperStatus.SUCCESS);
216     }
217 
218     /**
219      * Simple wallpaper callback to either record success or log on failure.
220      */
221     static class TestSetWallpaperCallback implements SetWallpaperCallback {
222         enum SetWallpaperStatus {
223             UNCALLED,
224             SUCCESS,
225             FAILURE
226         }
227         SetWallpaperStatus mStatus = SetWallpaperStatus.UNCALLED;
228         @Override
onSuccess(WallpaperInfo wallpaperInfo, int destination)229         public void onSuccess(WallpaperInfo wallpaperInfo, int destination) {
230             mStatus = SetWallpaperStatus.SUCCESS;
231         }
232 
233         @Override
onError(@ullable Throwable throwable)234         public void onError(@Nullable Throwable throwable) {
235             mStatus = SetWallpaperStatus.FAILURE;
236             Log.e(TAG, "Set wallpaper failed", throwable);
237         }
238 
getStatus()239         public SetWallpaperStatus getStatus() {
240             return mStatus;
241         }
242     }
243 }
244