• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
17 package com.android.server.wm;
18 
19 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
20 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
21 import static android.graphics.GraphicBuffer.USAGE_HW_TEXTURE;
22 import static android.graphics.GraphicBuffer.USAGE_SW_READ_RARELY;
23 
24 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
25 
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.spy;
29 import static org.mockito.Mockito.when;
30 
31 import android.content.ComponentName;
32 import android.content.ContextWrapper;
33 import android.content.res.Resources;
34 import android.graphics.Canvas;
35 import android.graphics.Color;
36 import android.graphics.ColorSpace;
37 import android.graphics.GraphicBuffer;
38 import android.graphics.PixelFormat;
39 import android.graphics.Point;
40 import android.graphics.Rect;
41 import android.hardware.HardwareBuffer;
42 import android.os.UserManager;
43 import android.view.Surface;
44 import android.window.TaskSnapshot;
45 
46 import com.android.server.LocalServices;
47 import com.android.server.pm.UserManagerInternal;
48 import com.android.server.wm.BaseAppSnapshotPersister.PersistInfoProvider;
49 
50 import org.junit.After;
51 import org.junit.AfterClass;
52 import org.junit.Before;
53 import org.junit.BeforeClass;
54 
55 import java.io.File;
56 import java.util.function.Predicate;
57 
58 /**
59  * Base class for tests that use a {@link TaskSnapshotPersister}.
60  */
61 class TaskSnapshotPersisterTestBase extends WindowTestsBase {
62 
63     private static final Rect TEST_CONTENT_INSETS = new Rect(10, 20, 30, 40);
64     private static final Rect TEST_LETTERBOX_INSETS = new Rect();
65     static final File FILES_DIR = getInstrumentation().getTargetContext().getFilesDir();
66     static final long MOCK_SNAPSHOT_ID = 12345678;
67 
68     private ContextWrapper mContextSpy;
69     private Resources mResourcesSpy;
70     SnapshotPersistQueue mSnapshotPersistQueue;
71     TaskSnapshotPersister mPersister;
72     AppSnapshotLoader mLoader;
73     int mTestUserId;
74     float mHighResScale;
75     float mLowResScale;
76 
TaskSnapshotPersisterTestBase(float highResScale, float lowResScale)77     TaskSnapshotPersisterTestBase(float highResScale, float lowResScale) {
78         super();
79         mHighResScale = highResScale;
80         mLowResScale = lowResScale;
81     }
82 
83     @BeforeClass
setUpOnce()84     public static void setUpOnce() {
85         final UserManagerInternal userManager = mock(UserManagerInternal.class);
86         LocalServices.addService(UserManagerInternal.class, userManager);
87     }
88 
89     @AfterClass
tearDownOnce()90     public static void tearDownOnce() {
91         LocalServices.removeServiceForTest(UserManagerInternal.class);
92     }
93 
94     @Before
setUp()95     public void setUp() {
96         final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
97         mTestUserId = um.getProcessUserId();
98 
99         final UserManagerInternal userManagerInternal =
100                 LocalServices.getService(UserManagerInternal.class);
101         when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true);
102 
103         mContextSpy = spy(new ContextWrapper(mWm.mContext));
104         mResourcesSpy = spy(mContextSpy.getResources());
105         when(mContextSpy.getResources()).thenReturn(mResourcesSpy);
106         when(mResourcesSpy.getFloat(
107                 com.android.internal.R.dimen.config_highResTaskSnapshotScale))
108                 .thenReturn(mHighResScale);
109         when(mResourcesSpy.getFloat(
110                 com.android.internal.R.dimen.config_lowResTaskSnapshotScale))
111                 .thenReturn(mLowResScale);
112 
113         mSnapshotPersistQueue = new SnapshotPersistQueue();
114         PersistInfoProvider provider =
115                 TaskSnapshotController.createPersistInfoProvider(mWm, userId -> FILES_DIR);
116         mPersister = new TaskSnapshotPersister(mSnapshotPersistQueue, provider);
117         mLoader = new AppSnapshotLoader(provider);
118         mSnapshotPersistQueue.start();
119     }
120 
121     @After
tearDown()122     public void tearDown() {
123         cleanDirectory();
124     }
125 
cleanDirectory()126     private void cleanDirectory() {
127         final File[] files = new File(FILES_DIR, "snapshots").listFiles();
128         if (files == null) {
129             return;
130         }
131         for (File file : files) {
132             if (!file.isDirectory()) {
133                 file.delete();
134             }
135         }
136     }
137 
createSnapshot()138     TaskSnapshot createSnapshot() {
139         return new TaskSnapshotBuilder().setTopActivityComponent(getUniqueComponentName()).build();
140     }
141 
assertTrueForFiles(File[] files, Predicate<File> predicate, String message)142     protected static void assertTrueForFiles(File[] files, Predicate<File> predicate,
143             String message) {
144         for (File file : files) {
145             assertTrue(file.getName() + message, predicate.test(file));
146         }
147     }
148 
149     /**
150      * Builds a TaskSnapshot.
151      */
152     static class TaskSnapshotBuilder {
153         private static final int SNAPSHOT_WIDTH = 100;
154         private static final int SNAPSHOT_HEIGHT = 100;
155 
156         private float mScaleFraction = 1f;
157         private boolean mIsRealSnapshot = true;
158         private boolean mIsTranslucent = false;
159         private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
160         private int mSystemUiVisibility = 0;
161         private int mRotation = Surface.ROTATION_0;
162         private int mWidth = SNAPSHOT_WIDTH;
163         private int mHeight = SNAPSHOT_HEIGHT;
164         private ComponentName mTopActivityComponent = new ComponentName("", "");
165 
TaskSnapshotBuilder()166         TaskSnapshotBuilder() {
167         }
168 
setTopActivityComponent(ComponentName topActivityComponent)169         TaskSnapshotBuilder setTopActivityComponent(ComponentName topActivityComponent) {
170             mTopActivityComponent = topActivityComponent;
171             return this;
172         }
173 
setScaleFraction(float scale)174         TaskSnapshotBuilder setScaleFraction(float scale) {
175             mScaleFraction = scale;
176             return this;
177         }
178 
setIsRealSnapshot(boolean isRealSnapshot)179         TaskSnapshotBuilder setIsRealSnapshot(boolean isRealSnapshot) {
180             mIsRealSnapshot = isRealSnapshot;
181             return this;
182         }
183 
setIsTranslucent(boolean isTranslucent)184         TaskSnapshotBuilder setIsTranslucent(boolean isTranslucent) {
185             mIsTranslucent = isTranslucent;
186             return this;
187         }
188 
setWindowingMode(int windowingMode)189         TaskSnapshotBuilder setWindowingMode(int windowingMode) {
190             mWindowingMode = windowingMode;
191             return this;
192         }
193 
setSystemUiVisibility(int systemUiVisibility)194         TaskSnapshotBuilder setSystemUiVisibility(int systemUiVisibility) {
195             mSystemUiVisibility = systemUiVisibility;
196             return this;
197         }
198 
setRotation(int rotation)199         TaskSnapshotBuilder setRotation(int rotation) {
200             mRotation = rotation;
201             return this;
202         }
203 
setTaskSize(int width, int height)204         TaskSnapshotBuilder setTaskSize(int width, int height) {
205             mWidth = width;
206             mHeight = height;
207             return this;
208         }
209 
build()210         TaskSnapshot build() {
211             // To satisfy existing tests, ensure the graphics buffer is always 100x100, and
212             // compute the ize of the task according to mScaleFraction.
213             Point taskSize = new Point((int) (mWidth / mScaleFraction),
214                     (int) (mHeight / mScaleFraction));
215             final GraphicBuffer buffer = GraphicBuffer.create(mWidth, mHeight,
216                     PixelFormat.RGBA_8888,
217                     USAGE_HW_TEXTURE | USAGE_SW_READ_RARELY | USAGE_SW_READ_RARELY);
218             Canvas c = buffer.lockCanvas();
219             c.drawColor(Color.RED);
220             buffer.unlockCanvasAndPost(c);
221             return new TaskSnapshot(MOCK_SNAPSHOT_ID, 0 /* captureTime */, mTopActivityComponent,
222                     HardwareBuffer.createFromGraphicBuffer(buffer),
223                     ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
224                     mRotation, taskSize, TEST_CONTENT_INSETS, TEST_LETTERBOX_INSETS,
225                     // When building a TaskSnapshot with the Builder class, isLowResolution
226                     // is always false. Low-res snapshots are only created when loading from
227                     // disk.
228                     false /* isLowResolution */,
229                     mIsRealSnapshot, mWindowingMode, mSystemUiVisibility, mIsTranslucent,
230                     false /* hasImeSurface */);
231         }
232     }
233 }
234