diff options
| author | 2024-08-30 19:43:30 +0000 | |
|---|---|---|
| committer | 2024-08-30 19:43:30 +0000 | |
| commit | de6e85d0fffe356ef28e2a8e8f79ef3a82fe84c6 (patch) | |
| tree | c778d9f9ee21562393cfeba300f0dd565aeafe75 | |
| parent | 68a8da476d82e2b9a10cb9a42c83fce8433ef19d (diff) | |
| parent | 193c9e869adf155bbac8bf275e9b34fd7e11b57f (diff) | |
Merge "Remove screenshot_private_profile_behavior_fix flag" into main
7 files changed, 18 insertions, 324 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 97206de346c5..1ce171609e5b 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -606,16 +606,6 @@ flag { } flag { - name: "screenshot_private_profile_behavior_fix" - namespace: "systemui" - description: "Private profile support for screenshots" - bug: "327613051" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "screenshot_save_image_exporter" namespace: "systemui" description: "Save all screenshots using ImageExporter" diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt index 474afa8bcb9d..56afb79c40d4 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/MessageContainerController.kt @@ -9,7 +9,6 @@ import android.view.ViewGroup.MarginLayoutParams import android.view.ViewTreeObserver import android.view.animation.AccelerateDecelerateInterpolator import androidx.constraintlayout.widget.Guideline -import com.android.systemui.Flags.screenshotPrivateProfileBehaviorFix import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.res.R import com.android.systemui.screenshot.message.ProfileMessageController @@ -49,44 +48,19 @@ constructor( } fun onScreenshotTaken(screenshot: ScreenshotData) { - if (screenshotPrivateProfileBehaviorFix()) { - mainScope.launch { - val profileData = profileMessageController.onScreenshotTaken(screenshot.userHandle) - var notifiedApps: List<CharSequence> = - screenshotDetectionController.maybeNotifyOfScreenshot(screenshot) - - // If profile first run needs to show, bias towards that, otherwise show screenshot - // detection notification if needed. - if (profileData != null) { - workProfileFirstRunView.visibility = View.VISIBLE - detectionNoticeView.visibility = View.GONE - profileMessageController.bindView(workProfileFirstRunView, profileData) { - animateOutMessageContainer() - } - animateInMessageContainer() - } else if (notifiedApps.isNotEmpty()) { - detectionNoticeView.visibility = View.VISIBLE - workProfileFirstRunView.visibility = View.GONE - screenshotDetectionController.populateView(detectionNoticeView, notifiedApps) - animateInMessageContainer() - } - } - } else { - val workProfileData = - workProfileMessageController.onScreenshotTaken(screenshot.userHandle) + mainScope.launch { + val profileData = profileMessageController.onScreenshotTaken(screenshot.userHandle) var notifiedApps: List<CharSequence> = screenshotDetectionController.maybeNotifyOfScreenshot(screenshot) - // If work profile first run needs to show, bias towards that, otherwise show screenshot + // If profile first run needs to show, bias towards that, otherwise show screenshot // detection notification if needed. - if (workProfileData != null) { + if (profileData != null) { workProfileFirstRunView.visibility = View.VISIBLE detectionNoticeView.visibility = View.GONE - workProfileMessageController.populateView( - workProfileFirstRunView, - workProfileData, - this::animateOutMessageContainer - ) + profileMessageController.bindView(workProfileFirstRunView, profileData) { + animateOutMessageContainer() + } animateInMessageContainer() } else if (notifiedApps.isNotEmpty()) { detectionNoticeView.visibility = View.VISIBLE diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt deleted file mode 100644 index 922997d08c25..000000000000 --- a/packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.screenshot - -import android.util.Log -import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE - -/** Implementation of [ScreenshotRequestProcessor] */ -class RequestProcessor( - private val capture: ImageCapture, - private val policy: ScreenshotPolicy, -) : ScreenshotRequestProcessor { - - override suspend fun process(screenshot: ScreenshotData): ScreenshotData { - var result = screenshot - - // Apply work profile screenshots policy: - // - // If the focused app belongs to a work profile, transforms a full screen - // (or partial) screenshot request to a task snapshot (provided image) screenshot. - - // Whenever displayContentInfo is fetched, the topComponent is also populated - // regardless of the managed profile status. - - if (screenshot.type != TAKE_SCREENSHOT_PROVIDED_IMAGE) { - val info = policy.findPrimaryContent(screenshot.displayId) - Log.d(TAG, "findPrimaryContent: $info") - result.taskId = info.taskId - result.topComponent = info.component - result.userHandle = info.user - - if (policy.isManagedProfile(info.user.identifier)) { - val image = - capture.captureTask(info.taskId) - ?: throw RequestProcessorException("Task snapshot returned a null Bitmap!") - - // Provide the task snapshot as the screenshot - result.type = TAKE_SCREENSHOT_PROVIDED_IMAGE - result.bitmap = image - result.screenBounds = info.bounds - } - } - - return result - } -} - -private const val TAG = "RequestProcessor" diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt index 3ad4075a2b89..ee1008d26414 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotRequestProcessor.kt @@ -27,5 +27,5 @@ fun interface ScreenshotRequestProcessor { suspend fun process(original: ScreenshotData): ScreenshotData } -/** Exception thrown by [RequestProcessor] if something goes wrong. */ +/** Exception thrown by [ScreenshotRequestProcessor] if something goes wrong. */ class RequestProcessorException(message: String) : IllegalStateException(message) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt b/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt index 44f767aa321e..2cb9fe7f1a9d 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt +++ b/packages/SystemUI/src/com/android/systemui/screenshot/policy/ScreenshotPolicyModule.kt @@ -19,14 +19,11 @@ package com.android.systemui.screenshot.policy import android.content.ComponentName import android.content.Context import android.os.Process -import com.android.systemui.Flags.screenshotPrivateProfileBehaviorFix import com.android.systemui.SystemUIService import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.screenshot.ImageCapture -import com.android.systemui.screenshot.RequestProcessor -import com.android.systemui.screenshot.ScreenshotPolicy import com.android.systemui.screenshot.ScreenshotRequestProcessor import com.android.systemui.screenshot.data.repository.DisplayContentRepository import com.android.systemui.screenshot.data.repository.DisplayContentRepositoryImpl @@ -68,23 +65,18 @@ interface ScreenshotPolicyModule { @Application context: Context, @Background background: CoroutineDispatcher, imageCapture: ImageCapture, - policyProvider: Provider<ScreenshotPolicy>, - displayContentRepoProvider: Provider<DisplayContentRepository>, + displayContentRepo: DisplayContentRepository, policyListProvider: Provider<List<CapturePolicy>>, ): ScreenshotRequestProcessor { - return if (screenshotPrivateProfileBehaviorFix()) { - PolicyRequestProcessor( - background = background, - capture = imageCapture, - displayTasks = displayContentRepoProvider.get(), - policies = policyListProvider.get(), - defaultOwner = Process.myUserHandle(), - defaultComponent = - ComponentName(context.packageName, SystemUIService::class.java.toString()) - ) - } else { - RequestProcessor(imageCapture, policyProvider.get()) - } + return PolicyRequestProcessor( + background = background, + capture = imageCapture, + displayTasks = displayContentRepo, + policies = policyListProvider.get(), + defaultOwner = Process.myUserHandle(), + defaultComponent = + ComponentName(context.packageName, SystemUIService::class.java.toString()) + ) } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt index b31d21e7f8b2..15da77dfe33d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/MessageContainerControllerTest.kt @@ -2,8 +2,6 @@ package com.android.systemui.screenshot import android.graphics.drawable.Drawable import android.os.UserHandle -import android.platform.test.annotations.DisableFlags -import android.platform.test.annotations.EnableFlags import android.view.View import android.view.ViewGroup import android.widget.FrameLayout @@ -90,20 +88,6 @@ class MessageContainerControllerTest : SysuiTestCase() { } @Test - @DisableFlags(com.android.systemui.Flags.FLAG_SCREENSHOT_PRIVATE_PROFILE_BEHAVIOR_FIX) - fun testOnScreenshotTakenUserHandle_withWorkProfileFirstRun() { - whenever(workProfileMessageController.onScreenshotTaken(eq(userHandle))) - .thenReturn(workProfileData) - messageContainer.onScreenshotTaken(screenshotData) - - verify(workProfileMessageController) - .populateView(eq(workProfileFirstRunView), eq(workProfileData), any()) - assertEquals(View.VISIBLE, workProfileFirstRunView.visibility) - assertEquals(View.GONE, detectionNoticeView.visibility) - } - - @Test - @EnableFlags(com.android.systemui.Flags.FLAG_SCREENSHOT_PRIVATE_PROFILE_BEHAVIOR_FIX) fun testOnScreenshotTakenUserHandle_withProfileProfileFirstRun() = runTest { val profileData = ProfileMessageController.ProfileFirstRunData( diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt deleted file mode 100644 index 0847f01f12d3..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.screenshot - -import android.content.ComponentName -import android.graphics.Bitmap -import android.graphics.ColorSpace -import android.graphics.Insets -import android.graphics.Rect -import android.hardware.HardwareBuffer -import android.os.UserHandle -import android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_OTHER -import android.view.WindowManager.ScreenshotSource.SCREENSHOT_OTHER -import android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN -import android.view.WindowManager.TAKE_SCREENSHOT_PROVIDED_IMAGE -import com.android.internal.util.ScreenshotRequest -import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo -import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.runBlocking -import org.junit.Assert -import org.junit.Test - -private const val USER_ID = 1 -private const val TASK_ID = 1 - -class RequestProcessorTest { - private val imageCapture = FakeImageCapture() - private val component = ComponentName("android.test", "android.test.Component") - private val bounds = Rect(25, 25, 75, 75) - - private val policy = FakeScreenshotPolicy() - - @Test - fun testFullScreenshot() = runBlocking { - // Indicate that the primary content belongs to a normal user - policy.setManagedProfile(USER_ID, false) - policy.setDisplayContentInfo( - policy.getDefaultDisplayId(), - DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID) - ) - - val request = - ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_OTHER).build() - val processor = RequestProcessor(imageCapture, policy) - - val processedData = processor.process(ScreenshotData.fromRequest(request)) - - // Request has topComponent added, but otherwise unchanged. - assertThat(processedData.type).isEqualTo(TAKE_SCREENSHOT_FULLSCREEN) - assertThat(processedData.source).isEqualTo(SCREENSHOT_OTHER) - assertThat(processedData.topComponent).isEqualTo(component) - } - - @Test - fun testFullScreenshot_managedProfile() = runBlocking { - // Provide a fake task bitmap when asked - val bitmap = makeHardwareBitmap(100, 100) - imageCapture.image = bitmap - - // Indicate that the primary content belongs to a manged profile - policy.setManagedProfile(USER_ID, true) - policy.setDisplayContentInfo( - policy.getDefaultDisplayId(), - DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID) - ) - - val request = - ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build() - val processor = RequestProcessor(imageCapture, policy) - - val processedData = processor.process(ScreenshotData.fromRequest(request)) - - // Expect a task snapshot is taken, overriding the full screen mode - assertThat(processedData.type).isEqualTo(TAKE_SCREENSHOT_PROVIDED_IMAGE) - assertThat(processedData.bitmap).isEqualTo(bitmap) - assertThat(processedData.screenBounds).isEqualTo(bounds) - assertThat(processedData.insets).isEqualTo(Insets.NONE) - assertThat(processedData.taskId).isEqualTo(TASK_ID) - assertThat(imageCapture.requestedTaskId).isEqualTo(TASK_ID) - } - - @Test - fun testFullScreenshot_managedProfile_nullBitmap() { - // Provide a null task bitmap when asked - imageCapture.image = null - - // Indicate that the primary content belongs to a manged profile - policy.setManagedProfile(USER_ID, true) - policy.setDisplayContentInfo( - policy.getDefaultDisplayId(), - DisplayContentInfo(component, bounds, UserHandle.of(USER_ID), TASK_ID) - ) - - val request = - ScreenshotRequest.Builder(TAKE_SCREENSHOT_FULLSCREEN, SCREENSHOT_KEY_OTHER).build() - val processor = RequestProcessor(imageCapture, policy) - - Assert.assertThrows(IllegalStateException::class.java) { - runBlocking { processor.process(ScreenshotData.fromRequest(request)) } - } - } - - @Test - fun testProvidedImageScreenshot() = runBlocking { - val bounds = Rect(50, 50, 150, 150) - val processor = RequestProcessor(imageCapture, policy) - - policy.setManagedProfile(USER_ID, false) - - val bitmap = makeHardwareBitmap(100, 100) - - val request = - ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER) - .setTopComponent(component) - .setTaskId(TASK_ID) - .setUserId(USER_ID) - .setBitmap(bitmap) - .setBoundsOnScreen(bounds) - .setInsets(Insets.NONE) - .build() - - val screenshotData = ScreenshotData.fromRequest(request) - val processedData = processor.process(screenshotData) - - assertThat(processedData).isEqualTo(screenshotData) - } - - @Test - fun testProvidedImageScreenshot_managedProfile() = runBlocking { - val bounds = Rect(50, 50, 150, 150) - val processor = RequestProcessor(imageCapture, policy) - - // Indicate that the screenshot belongs to a manged profile - policy.setManagedProfile(USER_ID, true) - - val bitmap = makeHardwareBitmap(100, 100) - - val request = - ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OTHER) - .setTopComponent(component) - .setTaskId(TASK_ID) - .setUserId(USER_ID) - .setBitmap(bitmap) - .setBoundsOnScreen(bounds) - .setInsets(Insets.NONE) - .build() - - val screenshotData = ScreenshotData.fromRequest(request) - val processedData = processor.process(screenshotData) - - // Work profile, but already a task snapshot, so no changes - assertThat(processedData).isEqualTo(screenshotData) - } - - private fun makeHardwareBitmap(width: Int, height: Int): Bitmap { - val buffer = - HardwareBuffer.create( - width, - height, - HardwareBuffer.RGBA_8888, - 1, - HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE - ) - return Bitmap.wrapHardwareBuffer(buffer, ColorSpace.get(ColorSpace.Named.SRGB))!! - } - - private fun Bitmap.equalsHardwareBitmap(bitmap: Bitmap): Boolean { - return bitmap.hardwareBuffer == this.hardwareBuffer && bitmap.colorSpace == this.colorSpace - } -} |