blob: 70d71bc627c0d02d01c6590cfe3da7c99e63d570 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.window.TaskSnapshot;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
import android.view.Surface;
import androidx.test.filters.MediumTest;
import com.android.server.wm.TaskSnapshotLoader.PreRLegacySnapshotConfig;
import com.android.server.wm.TaskSnapshotPersister.RemoveObsoleteFilesQueueItem;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoSession;
import java.io.File;
/**
* Test class for {@link TaskSnapshotPersister} and {@link TaskSnapshotLoader}
*
* Build/Install/Run:
* atest TaskSnapshotPersisterLoaderTest
*/
@MediumTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class TaskSnapshotPersisterLoaderTest extends TaskSnapshotPersisterTestBase {
private static final float DELTA = 0.00001f;
private static final Rect TEST_INSETS = new Rect(10, 20, 30, 40);
public TaskSnapshotPersisterLoaderTest() {
super(0.8f, 0.5f);
}
@Test
public void testPersistAndLoadSnapshot() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.waitForQueueEmpty();
final File[] files = new File[]{new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg")};
assertTrueForFiles(files, File::exists, " must exist");
final TaskSnapshot snapshot = mLoader.loadTask(1, mTestUserId, false /* isLowResolution */);
assertNotNull(snapshot);
assertEquals(MOCK_SNAPSHOT_ID, snapshot.getId());
assertEquals(TEST_INSETS, snapshot.getContentInsets());
assertNotNull(snapshot.getSnapshot());
assertEquals(Configuration.ORIENTATION_PORTRAIT, snapshot.getOrientation());
}
@Test
public void testTaskRemovedFromRecents() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.onTaskRemovedFromRecents(1, mTestUserId);
mPersister.waitForQueueEmpty();
assertFalse(new File(FILES_DIR.getPath() + "/snapshots/1.proto").exists());
assertFalse(new File(FILES_DIR.getPath() + "/snapshots/1.jpg").exists());
assertFalse(new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg").exists());
}
/**
* Tests that persisting a couple of snapshots is being throttled.
*/
@Test
public void testThrottling() {
long ms = SystemClock.elapsedRealtime();
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[]{mTestUserId});
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[]{mTestUserId});
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[]{mTestUserId});
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[]{mTestUserId});
mPersister.waitForQueueEmpty();
assertTrue(SystemClock.elapsedRealtime() - ms > 500);
}
/**
* Tests that too many store write queue items are being purged.
*/
@Test
public void testPurging() {
mPersister.persistSnapshot(100, mTestUserId, createSnapshot());
mPersister.waitForQueueEmpty();
mPersister.setPaused(true);
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.removeObsoleteFiles(new ArraySet<>(), new int[]{mTestUserId});
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mPersister.persistSnapshot(3, mTestUserId, createSnapshot());
mPersister.persistSnapshot(4, mTestUserId, createSnapshot());
mPersister.setPaused(false);
mPersister.waitForQueueEmpty();
// Make sure 1,2 were purged but removeObsoleteFiles wasn't.
final File[] existsFiles = new File[]{
new File(FILES_DIR.getPath() + "/snapshots/3.proto"),
new File(FILES_DIR.getPath() + "/snapshots/4.proto")};
final File[] nonExistsFiles = new File[]{
new File(FILES_DIR.getPath() + "/snapshots/100.proto"),
new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
new File(FILES_DIR.getPath() + "/snapshots/1.proto")};
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
@Test
public void testGetTaskId() {
RemoveObsoleteFilesQueueItem removeObsoleteFilesQueueItem =
mPersister.new RemoveObsoleteFilesQueueItem(new ArraySet<>(), new int[]{});
assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("blablablulp"));
assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("nothing.err"));
assertEquals(-1, removeObsoleteFilesQueueItem.getTaskId("/invalid/"));
assertEquals(12, removeObsoleteFilesQueueItem.getTaskId("12.jpg"));
assertEquals(12, removeObsoleteFilesQueueItem.getTaskId("12.proto"));
assertEquals(1, removeObsoleteFilesQueueItem.getTaskId("1.jpg"));
assertEquals(1, removeObsoleteFilesQueueItem.getTaskId("1_reduced.jpg"));
}
@Test
public void testLegacyPLowRamConfig() throws Exception {
MockitoSession mockSession = mockitoSession()
.initMocks(this)
.mockStatic(ActivityManager.class)
.startMocking();
when(ActivityManager.isLowRamDeviceStatic()).thenReturn(true);
// taskWidth and legacyScale as would be defined in the proto, and presence of a *.jpg file,
// for any P low_ram device
final int taskWidth = 0;
final float legacyScale = 0f;
final boolean hasHighResFile = false;
PreRLegacySnapshotConfig highResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, false /* loadLowResolutionBitmap */);
assertNotNull(highResConf);
assertEquals(highResConf.mScale, 0.6f, DELTA);
assertTrue(highResConf.mForceLoadReducedJpeg);
PreRLegacySnapshotConfig lowResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, true /* loadLowResolutionBitmap */);
assertNotNull(lowResConf);
assertEquals(lowResConf.mScale, 0.6f, DELTA);
assertTrue(lowResConf.mForceLoadReducedJpeg);
mockSession.finishMocking();
}
@Test
public void testLegacyPNonLowRamConfig() throws Exception {
MockitoSession mockSession = mockitoSession()
.initMocks(this)
.mockStatic(ActivityManager.class)
.startMocking();
when(ActivityManager.isLowRamDeviceStatic()).thenReturn(false);
// taskWidth and legacyScale as would be defined in the proto, and presence of a *.jpg file,
// for any O device, or a P non-low_ram device
final int taskWidth = 0;
final float legacyScale = 0f;
final boolean hasHighResFile = true;
PreRLegacySnapshotConfig highResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, false /* loadLowResolutionBitmap */);
assertNotNull(highResConf);
assertEquals(highResConf.mScale, 1.0f, DELTA);
assertFalse(highResConf.mForceLoadReducedJpeg);
PreRLegacySnapshotConfig lowResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, true /* loadLowResolutionBitmap */);
assertNotNull(lowResConf);
assertEquals(lowResConf.mScale, 0.5f, DELTA);
assertFalse(lowResConf.mForceLoadReducedJpeg);
mockSession.finishMocking();
}
@Test
public void testLegacyQLowRamConfig() throws Exception {
MockitoSession mockSession = mockitoSession()
.initMocks(this)
.mockStatic(ActivityManager.class)
.startMocking();
when(ActivityManager.isLowRamDeviceStatic()).thenReturn(true);
// taskWidth and legacyScale as would be defined in the proto, and presence of a *.jpg file,
// for any Q low_ram device
final int taskWidth = 0;
final float legacyScale = 0.6f;
final boolean hasHighResFile = false;
PreRLegacySnapshotConfig highResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, false /* loadLowResolutionBitmap */);
assertNotNull(highResConf);
assertEquals(highResConf.mScale, legacyScale, DELTA);
assertEquals(highResConf.mScale, 0.6f, DELTA);
assertTrue(highResConf.mForceLoadReducedJpeg);
PreRLegacySnapshotConfig lowResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, true /* loadLowResolutionBitmap */);
assertNotNull(lowResConf);
assertEquals(lowResConf.mScale, legacyScale, DELTA);
assertEquals(lowResConf.mScale, 0.6f, DELTA);
assertTrue(lowResConf.mForceLoadReducedJpeg);
mockSession.finishMocking();
}
@Test
public void testLegacyQNonLowRamConfig() throws Exception {
MockitoSession mockSession = mockitoSession()
.initMocks(this)
.mockStatic(ActivityManager.class)
.startMocking();
when(ActivityManager.isLowRamDeviceStatic()).thenReturn(false);
// taskWidth and legacyScale as would be defined in the proto, and presence of a *.jpg file,
// for any Q non-low_ram device
final int taskWidth = 0;
final float legacyScale = 0.8f;
final boolean hasHighResFile = true;
PreRLegacySnapshotConfig highResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, false /* loadLowResolutionBitmap */);
assertNotNull(highResConf);
assertEquals(highResConf.mScale, legacyScale, DELTA);
assertEquals(highResConf.mScale, 0.8f, DELTA);
assertFalse(highResConf.mForceLoadReducedJpeg);
PreRLegacySnapshotConfig lowResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, true /* loadLowResolutionBitmap */);
assertNotNull(lowResConf);
assertEquals(lowResConf.mScale, 0.5f * legacyScale, DELTA);
assertEquals(lowResConf.mScale, 0.5f * 0.8f, DELTA);
assertFalse(lowResConf.mForceLoadReducedJpeg);
mockSession.finishMocking();
}
@Test
public void testNonLegacyRConfig() throws Exception {
// taskWidth and legacyScale as would be defined in the proto, and presence of a *.jpg file,
// for any R device
final int taskWidth = 1440;
final float legacyScale = 0f;
final boolean hasHighResFile = true;
PreRLegacySnapshotConfig highResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, false /* loadLowResolutionBitmap */);
assertNull(highResConf);
PreRLegacySnapshotConfig lowResConf = mLoader.getLegacySnapshotConfig(
taskWidth, legacyScale, hasHighResFile, true /* loadLowResolutionBitmap */);
assertNull(lowResConf);
}
@Test
public void testIsRealSnapshotPersistAndLoadSnapshot() {
TaskSnapshot a = new TaskSnapshotBuilder()
.setIsRealSnapshot(true)
.build();
TaskSnapshot b = new TaskSnapshotBuilder()
.setIsRealSnapshot(false)
.build();
assertTrue(a.isRealSnapshot());
assertFalse(b.isRealSnapshot());
mPersister.persistSnapshot(1, mTestUserId, a);
mPersister.persistSnapshot(2, mTestUserId, b);
mPersister.waitForQueueEmpty();
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId,
false /* isLowResolution */);
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId,
false /* isLowResolution */);
assertNotNull(snapshotA);
assertNotNull(snapshotB);
assertTrue(snapshotA.isRealSnapshot());
assertFalse(snapshotB.isRealSnapshot());
}
@Test
public void testWindowingModePersistAndLoadSnapshot() {
TaskSnapshot a = new TaskSnapshotBuilder()
.setWindowingMode(WINDOWING_MODE_FULLSCREEN)
.build();
TaskSnapshot b = new TaskSnapshotBuilder()
.setWindowingMode(WINDOWING_MODE_PINNED)
.build();
assertEquals(WINDOWING_MODE_FULLSCREEN, a.getWindowingMode());
assertEquals(WINDOWING_MODE_PINNED, b.getWindowingMode());
mPersister.persistSnapshot(1, mTestUserId, a);
mPersister.persistSnapshot(2, mTestUserId, b);
mPersister.waitForQueueEmpty();
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId,
false /* isLowResolution */);
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId,
false /* isLowResolution */);
assertNotNull(snapshotA);
assertNotNull(snapshotB);
assertEquals(WINDOWING_MODE_FULLSCREEN, snapshotA.getWindowingMode());
assertEquals(WINDOWING_MODE_PINNED, snapshotB.getWindowingMode());
}
@Test
public void testIsTranslucentPersistAndLoadSnapshot() {
TaskSnapshot a = new TaskSnapshotBuilder()
.setIsTranslucent(true)
.build();
TaskSnapshot b = new TaskSnapshotBuilder()
.setIsTranslucent(false)
.build();
assertTrue(a.isTranslucent());
assertFalse(b.isTranslucent());
mPersister.persistSnapshot(1, mTestUserId, a);
mPersister.persistSnapshot(2, mTestUserId, b);
mPersister.waitForQueueEmpty();
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId,
false /* isLowResolution */);
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId,
false /* isLowResolution */);
assertNotNull(snapshotA);
assertNotNull(snapshotB);
assertTrue(snapshotA.isTranslucent());
assertFalse(snapshotB.isTranslucent());
}
@Test
public void testAppearancePersistAndLoadSnapshot() {
final int lightBarFlags = APPEARANCE_LIGHT_STATUS_BARS | APPEARANCE_LIGHT_NAVIGATION_BARS;
TaskSnapshot a = new TaskSnapshotBuilder()
.setSystemUiVisibility(0)
.build();
TaskSnapshot b = new TaskSnapshotBuilder()
.setSystemUiVisibility(lightBarFlags)
.build();
assertEquals(0, a.getAppearance());
assertEquals(lightBarFlags, b.getAppearance());
mPersister.persistSnapshot(1, mTestUserId, a);
mPersister.persistSnapshot(2, mTestUserId, b);
mPersister.waitForQueueEmpty();
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId,
false /* isLowResolution */);
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId,
false /* isLowResolution */);
assertNotNull(snapshotA);
assertNotNull(snapshotB);
assertEquals(0, snapshotA.getAppearance());
assertEquals(lightBarFlags, snapshotB.getAppearance());
}
@Test
public void testScalePersistAndLoadSnapshot() {
TaskSnapshot a = new TaskSnapshotBuilder()
.setScaleFraction(0.25f)
.build();
TaskSnapshot b = new TaskSnapshotBuilder()
.setScaleFraction(0.75f)
.build();
mPersister.persistSnapshot(1, mTestUserId, a);
mPersister.persistSnapshot(2, mTestUserId, b);
mPersister.waitForQueueEmpty();
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId,
false /* isLowResolution */);
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId,
false /* isLowResolution */);
assertNotNull(snapshotA);
assertNotNull(snapshotB);
}
@Test
public void testRemoveObsoleteFiles() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
final ArraySet<Integer> taskIds = new ArraySet<>();
taskIds.add(1);
mPersister.removeObsoleteFiles(taskIds, new int[]{mTestUserId});
mPersister.waitForQueueEmpty();
final File[] existsFiles = new File[]{
new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg")};
final File[] nonExistsFiles = new File[]{
new File(FILES_DIR.getPath() + "/snapshots/2.proto"),
new File(FILES_DIR.getPath() + "/snapshots/2.jpg"),
new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
assertTrueForFiles(existsFiles, File::exists, " must exist");
assertTrueForFiles(nonExistsFiles, file -> !file.exists(), " must not exist");
}
@Test
public void testRemoveObsoleteFiles_addedOneInTheMeantime() {
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
final ArraySet<Integer> taskIds = new ArraySet<>();
taskIds.add(1);
mPersister.removeObsoleteFiles(taskIds, new int[]{mTestUserId});
mPersister.persistSnapshot(2, mTestUserId, createSnapshot());
mPersister.waitForQueueEmpty();
final File[] existsFiles = new File[]{
new File(FILES_DIR.getPath() + "/snapshots/1.proto"),
new File(FILES_DIR.getPath() + "/snapshots/1.jpg"),
new File(FILES_DIR.getPath() + "/snapshots/1_reduced.jpg"),
new File(FILES_DIR.getPath() + "/snapshots/2.proto"),
new File(FILES_DIR.getPath() + "/snapshots/2.jpg"),
new File(FILES_DIR.getPath() + "/snapshots/2_reduced.jpg")};
assertTrueForFiles(existsFiles, File::exists, " must exist");
}
@Test
public void testRotationPersistAndLoadSnapshot() {
TaskSnapshot a = new TaskSnapshotBuilder()
.setRotation(Surface.ROTATION_270)
.build();
mPersister.persistSnapshot(1, mTestUserId, createSnapshot());
mPersister.persistSnapshot(2, mTestUserId, a);
mPersister.waitForQueueEmpty();
final TaskSnapshot snapshotA = mLoader.loadTask(1, mTestUserId,
false /* isLowResolution */);
final TaskSnapshot snapshotB = mLoader.loadTask(2, mTestUserId,
false /* isLowResolution */);
assertEquals(Surface.ROTATION_0, snapshotA.getRotation());
assertEquals(Surface.ROTATION_270, snapshotB.getRotation());
}
}