Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2016 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 |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 14 | * limitations under the License. |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 15 | */ |
| 16 | |
| 17 | package com.android.server.wm; |
| 18 | |
| 19 | import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; |
Jorim Jaggi | d635a4a | 2017-05-03 15:21:26 +0200 | [diff] [blame] | 20 | import static android.view.WindowManager.LayoutParams.FLAG_SECURE; |
Brett Chabot | a26eda9 | 2018-07-23 13:08:30 -0700 | [diff] [blame] | 21 | |
Riddle Hsu | c802e4b | 2019-12-20 16:54:33 +0800 | [diff] [blame] | 22 | import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; |
| 23 | import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 24 | import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_APP_THEME; |
| 25 | import static com.android.server.wm.TaskSnapshotController.SNAPSHOT_MODE_REAL; |
Brett Chabot | a26eda9 | 2018-07-23 13:08:30 -0700 | [diff] [blame] | 26 | |
Tadashi G. Takaoka | 82eb7a5 | 2019-03-26 18:22:01 +0900 | [diff] [blame] | 27 | import static org.junit.Assert.assertEquals; |
Peter Kalauskas | 84f02a8 | 2020-01-22 16:06:18 -0800 | [diff] [blame] | 28 | import static org.junit.Assert.assertFalse; |
Riddle Hsu | c802e4b | 2019-12-20 16:54:33 +0800 | [diff] [blame] | 29 | import static org.junit.Assert.assertNotEquals; |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 30 | import static org.junit.Assert.assertSame; |
| 31 | import static org.junit.Assert.assertTrue; |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 32 | |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 33 | import android.app.ActivityManager; |
| 34 | import android.app.WindowConfiguration; |
| 35 | import android.content.ComponentName; |
| 36 | import android.content.res.Configuration; |
| 37 | import android.graphics.ColorSpace; |
| 38 | import android.graphics.GraphicBuffer; |
| 39 | import android.graphics.PixelFormat; |
Peter Kalauskas | fe0a413 | 2020-01-31 16:50:42 -0800 | [diff] [blame] | 40 | import android.graphics.Point; |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 41 | import android.graphics.Rect; |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 42 | import android.platform.test.annotations.Presubmit; |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 43 | import android.util.ArraySet; |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 44 | import android.view.View; |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 45 | |
Brett Chabot | a26eda9 | 2018-07-23 13:08:30 -0700 | [diff] [blame] | 46 | import androidx.test.filters.SmallTest; |
Brett Chabot | a26eda9 | 2018-07-23 13:08:30 -0700 | [diff] [blame] | 47 | |
Winson Chung | 23aa7b1 | 2018-02-01 11:41:43 -0800 | [diff] [blame] | 48 | import com.google.android.collect.Sets; |
Brett Chabot | a26eda9 | 2018-07-23 13:08:30 -0700 | [diff] [blame] | 49 | |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 50 | import org.junit.Test; |
Louis Chang | 2453d06 | 2019-11-19 22:30:48 +0800 | [diff] [blame] | 51 | import org.junit.runner.RunWith; |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 52 | import org.mockito.Mockito; |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 53 | |
| 54 | /** |
| 55 | * Test class for {@link TaskSnapshotController}. |
| 56 | * |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 57 | * Build/Install/Run: |
Andrii Kulian | f5d1411 | 2019-10-31 17:37:54 -0700 | [diff] [blame] | 58 | * * atest WmTests:TaskSnapshotControllerTest |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 59 | */ |
| 60 | @SmallTest |
| 61 | @Presubmit |
Louis Chang | 2453d06 | 2019-11-19 22:30:48 +0800 | [diff] [blame] | 62 | @RunWith(WindowTestRunner.class) |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 63 | public class TaskSnapshotControllerTest extends WindowTestsBase { |
| 64 | |
| 65 | @Test |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 66 | public void testGetClosingApps_closing() { |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 67 | final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW, |
| 68 | "closingWindow"); |
Issei Suzuki | 2bcbd68 | 2019-11-08 13:20:14 +0100 | [diff] [blame] | 69 | closingWindow.mActivityRecord.commitVisibility( |
| 70 | false /* visible */, true /* performLayout */); |
Garfield Tan | e8d84ab | 2019-10-11 09:49:40 -0700 | [diff] [blame] | 71 | final ArraySet<ActivityRecord> closingApps = new ArraySet<>(); |
| 72 | closingApps.add(closingWindow.mActivityRecord); |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 73 | final ArraySet<Task> closingTasks = new ArraySet<>(); |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 74 | mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks); |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 75 | assertEquals(1, closingTasks.size()); |
Garfield Tan | e8d84ab | 2019-10-11 09:49:40 -0700 | [diff] [blame] | 76 | assertEquals(closingWindow.mActivityRecord.getTask(), closingTasks.valueAt(0)); |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 77 | } |
| 78 | |
| 79 | @Test |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 80 | public void testGetClosingApps_notClosing() { |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 81 | final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW, |
| 82 | "closingWindow"); |
| 83 | final WindowState openingWindow = createAppWindow(closingWindow.getTask(), |
| 84 | FIRST_APPLICATION_WINDOW, "openingWindow"); |
Issei Suzuki | 2bcbd68 | 2019-11-08 13:20:14 +0100 | [diff] [blame] | 85 | closingWindow.mActivityRecord.commitVisibility( |
| 86 | false /* visible */, true /* performLayout */); |
| 87 | openingWindow.mActivityRecord.commitVisibility( |
| 88 | true /* visible */, true /* performLayout */); |
Garfield Tan | e8d84ab | 2019-10-11 09:49:40 -0700 | [diff] [blame] | 89 | final ArraySet<ActivityRecord> closingApps = new ArraySet<>(); |
| 90 | closingApps.add(closingWindow.mActivityRecord); |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 91 | final ArraySet<Task> closingTasks = new ArraySet<>(); |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 92 | mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks); |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 93 | assertEquals(0, closingTasks.size()); |
| 94 | } |
Jorim Jaggi | 0fe7ce96 | 2017-02-22 16:45:48 +0100 | [diff] [blame] | 95 | |
| 96 | @Test |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 97 | public void testGetClosingApps_skipClosingAppsSnapshotTasks() { |
Winson Chung | 23aa7b1 | 2018-02-01 11:41:43 -0800 | [diff] [blame] | 98 | final WindowState closingWindow = createWindow(null, FIRST_APPLICATION_WINDOW, |
| 99 | "closingWindow"); |
Issei Suzuki | 2bcbd68 | 2019-11-08 13:20:14 +0100 | [diff] [blame] | 100 | closingWindow.mActivityRecord.commitVisibility( |
| 101 | false /* visible */, true /* performLayout */); |
Garfield Tan | e8d84ab | 2019-10-11 09:49:40 -0700 | [diff] [blame] | 102 | final ArraySet<ActivityRecord> closingApps = new ArraySet<>(); |
| 103 | closingApps.add(closingWindow.mActivityRecord); |
Winson Chung | 23aa7b1 | 2018-02-01 11:41:43 -0800 | [diff] [blame] | 104 | final ArraySet<Task> closingTasks = new ArraySet<>(); |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 105 | mWm.mTaskSnapshotController.addSkipClosingAppSnapshotTasks( |
Garfield Tan | e8d84ab | 2019-10-11 09:49:40 -0700 | [diff] [blame] | 106 | Sets.newArraySet(closingWindow.mActivityRecord.getTask())); |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 107 | mWm.mTaskSnapshotController.getClosingTasks(closingApps, closingTasks); |
Winson Chung | 23aa7b1 | 2018-02-01 11:41:43 -0800 | [diff] [blame] | 108 | assertEquals(0, closingTasks.size()); |
| 109 | } |
| 110 | |
| 111 | @Test |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 112 | public void testGetSnapshotMode() { |
Jorim Jaggi | 0fe7ce96 | 2017-02-22 16:45:48 +0100 | [diff] [blame] | 113 | final WindowState disabledWindow = createWindow(null, |
Wale Ogunwale | 11cc516 | 2017-04-25 20:29:13 -0700 | [diff] [blame] | 114 | FIRST_APPLICATION_WINDOW, mDisplayContent, "disabledWindow"); |
Garfield Tan | e8d84ab | 2019-10-11 09:49:40 -0700 | [diff] [blame] | 115 | disabledWindow.mActivityRecord.setDisablePreviewScreenshots(true); |
Jorim Jaggi | 8f4fe6e | 2017-03-14 18:21:40 +0100 | [diff] [blame] | 116 | assertEquals(SNAPSHOT_MODE_APP_THEME, |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 117 | mWm.mTaskSnapshotController.getSnapshotMode(disabledWindow.getTask())); |
Jorim Jaggi | d635a4a | 2017-05-03 15:21:26 +0200 | [diff] [blame] | 118 | |
Jorim Jaggi | 0fe7ce96 | 2017-02-22 16:45:48 +0100 | [diff] [blame] | 119 | final WindowState normalWindow = createWindow(null, |
Wale Ogunwale | 11cc516 | 2017-04-25 20:29:13 -0700 | [diff] [blame] | 120 | FIRST_APPLICATION_WINDOW, mDisplayContent, "normalWindow"); |
Jorim Jaggi | 8f4fe6e | 2017-03-14 18:21:40 +0100 | [diff] [blame] | 121 | assertEquals(SNAPSHOT_MODE_REAL, |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 122 | mWm.mTaskSnapshotController.getSnapshotMode(normalWindow.getTask())); |
Jorim Jaggi | d635a4a | 2017-05-03 15:21:26 +0200 | [diff] [blame] | 123 | |
| 124 | final WindowState secureWindow = createWindow(null, |
| 125 | FIRST_APPLICATION_WINDOW, mDisplayContent, "secureWindow"); |
| 126 | secureWindow.mAttrs.flags |= FLAG_SECURE; |
| 127 | assertEquals(SNAPSHOT_MODE_APP_THEME, |
Tadashi G. Takaoka | b6e148c | 2018-11-03 02:59:06 -0700 | [diff] [blame] | 128 | mWm.mTaskSnapshotController.getSnapshotMode(secureWindow.getTask())); |
Jorim Jaggi | 0fe7ce96 | 2017-02-22 16:45:48 +0100 | [diff] [blame] | 129 | } |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 130 | |
| 131 | @Test |
| 132 | public void testSnapshotBuilder() { |
| 133 | final GraphicBuffer buffer = Mockito.mock(GraphicBuffer.class); |
| 134 | final ColorSpace sRGB = ColorSpace.get(ColorSpace.Named.SRGB); |
| 135 | final long id = 1234L; |
| 136 | final ComponentName activityComponent = new ComponentName("package", ".Class"); |
| 137 | final int windowingMode = WindowConfiguration.WINDOWING_MODE_FULLSCREEN; |
| 138 | final int systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN; |
| 139 | final int pixelFormat = PixelFormat.RGBA_8888; |
| 140 | final int orientation = Configuration.ORIENTATION_PORTRAIT; |
| 141 | final float scaleFraction = 0.25f; |
| 142 | final Rect contentInsets = new Rect(1, 2, 3, 4); |
Peter Kalauskas | fe0a413 | 2020-01-31 16:50:42 -0800 | [diff] [blame] | 143 | final Point taskSize = new Point(5, 6); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 144 | |
| 145 | try { |
| 146 | ActivityManager.TaskSnapshot.Builder builder = |
| 147 | new ActivityManager.TaskSnapshot.Builder(); |
| 148 | builder.setId(id); |
| 149 | builder.setTopActivityComponent(activityComponent); |
| 150 | builder.setSystemUiVisibility(systemUiVisibility); |
| 151 | builder.setWindowingMode(windowingMode); |
| 152 | builder.setColorSpace(sRGB); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 153 | builder.setOrientation(orientation); |
| 154 | builder.setContentInsets(contentInsets); |
| 155 | builder.setIsTranslucent(true); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 156 | builder.setSnapshot(buffer); |
| 157 | builder.setIsRealSnapshot(true); |
| 158 | builder.setPixelFormat(pixelFormat); |
Peter Kalauskas | fe0a413 | 2020-01-31 16:50:42 -0800 | [diff] [blame] | 159 | builder.setTaskSize(taskSize); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 160 | |
| 161 | // Not part of TaskSnapshot itself, used in screenshot process |
| 162 | assertEquals(pixelFormat, builder.getPixelFormat()); |
| 163 | |
| 164 | ActivityManager.TaskSnapshot snapshot = builder.build(); |
| 165 | assertEquals(id, snapshot.getId()); |
| 166 | assertEquals(activityComponent, snapshot.getTopActivityComponent()); |
| 167 | assertEquals(systemUiVisibility, snapshot.getSystemUiVisibility()); |
| 168 | assertEquals(windowingMode, snapshot.getWindowingMode()); |
| 169 | assertEquals(sRGB, snapshot.getColorSpace()); |
Peter Kalauskas | 84f02a8 | 2020-01-22 16:06:18 -0800 | [diff] [blame] | 170 | // Snapshots created with the Builder class are always high-res. The only way to get a |
| 171 | // low-res snapshot is to load it from the disk in TaskSnapshotLoader. |
| 172 | assertFalse(snapshot.isLowResolution()); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 173 | assertEquals(orientation, snapshot.getOrientation()); |
| 174 | assertEquals(contentInsets, snapshot.getContentInsets()); |
| 175 | assertTrue(snapshot.isTranslucent()); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 176 | assertSame(buffer, snapshot.getSnapshot()); |
| 177 | assertTrue(snapshot.isRealSnapshot()); |
Peter Kalauskas | fe0a413 | 2020-01-31 16:50:42 -0800 | [diff] [blame] | 178 | assertEquals(taskSize, snapshot.getTaskSize()); |
Mark Renouf | 98ba8e6 | 2019-11-18 12:42:16 -0500 | [diff] [blame] | 179 | } finally { |
| 180 | if (buffer != null) { |
| 181 | buffer.destroy(); |
| 182 | } |
| 183 | } |
| 184 | } |
Riddle Hsu | c802e4b | 2019-12-20 16:54:33 +0800 | [diff] [blame] | 185 | |
| 186 | @Test |
| 187 | public void testPrepareTaskSnapshot() { |
| 188 | mAppWindow.mWinAnimator.mLastAlpha = 1f; |
| 189 | spyOn(mAppWindow.mWinAnimator); |
| 190 | doReturn(true).when(mAppWindow.mWinAnimator).getShown(); |
| 191 | doReturn(true).when(mAppWindow.mActivityRecord).isSurfaceShowing(); |
| 192 | |
| 193 | final ActivityManager.TaskSnapshot.Builder builder = |
| 194 | new ActivityManager.TaskSnapshot.Builder(); |
Riddle Hsu | c802e4b | 2019-12-20 16:54:33 +0800 | [diff] [blame] | 195 | mWm.mTaskSnapshotController.prepareTaskSnapshot(mAppWindow.mActivityRecord.getTask(), |
Peter Kalauskas | fe0a413 | 2020-01-31 16:50:42 -0800 | [diff] [blame] | 196 | PixelFormat.UNKNOWN, builder); |
Riddle Hsu | c802e4b | 2019-12-20 16:54:33 +0800 | [diff] [blame] | 197 | |
Riddle Hsu | c802e4b | 2019-12-20 16:54:33 +0800 | [diff] [blame] | 198 | // The pixel format should be selected automatically. |
| 199 | assertNotEquals(PixelFormat.UNKNOWN, builder.getPixelFormat()); |
| 200 | } |
Jorim Jaggi | 02886a8 | 2016-12-06 09:10:06 -0800 | [diff] [blame] | 201 | } |