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