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