/* * Copyright (C) 2023 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.app.Notification import android.app.PendingIntent import android.content.ComponentName import android.content.Intent import android.graphics.Bitmap import android.graphics.drawable.Icon import android.net.Uri import android.os.UserHandle import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.screenshot.ScreenshotController.SaveImageInBackgroundData import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider.ScreenshotSmartActionType import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever import java.util.concurrent.CompletableFuture import java.util.function.Supplier import org.junit.Assert.assertEquals import org.junit.Assert.assertNull import org.junit.Before import org.junit.Test @SmallTest class SaveImageInBackgroundTaskTest : SysuiTestCase() { private val imageExporter = mock() private val smartActions = mock() private val smartActionsProvider = mock() private val saveImageData = SaveImageInBackgroundData() private val sharedTransitionSupplier = mock>() private val testScreenshotId: String = "testScreenshotId" private val testBitmap = mock() private val testUser = UserHandle.getUserHandleForUid(0) private val testIcon = mock() private val testImageTime = 1234.toLong() private val flags = FakeFeatureFlags() private val smartActionsUriFuture = mock>>() private val smartActionsFuture = mock>>() private val testUri: Uri = Uri.parse("testUri") private val intent = Intent(Intent.ACTION_SEND) .setComponent( ComponentName.unflattenFromString( "com.google.android.test/com.google.android.test.TestActivity" ) ) private val immutablePendingIntent = PendingIntent.getBroadcast( mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE ) private val mutablePendingIntent = PendingIntent.getBroadcast( mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE ) private val saveImageTask = SaveImageInBackgroundTask( mContext, flags, imageExporter, smartActions, saveImageData, sharedTransitionSupplier, smartActionsProvider, ) @Before fun setup() { whenever( smartActions.getSmartActionsFuture( eq(testScreenshotId), any(Uri::class.java), eq(testBitmap), eq(smartActionsProvider), any(ScreenshotSmartActionType::class.java), any(Boolean::class.java), eq(testUser) ) ) .thenReturn(smartActionsUriFuture) whenever( smartActions.getSmartActionsFuture( eq(testScreenshotId), eq(null), eq(testBitmap), eq(smartActionsProvider), any(ScreenshotSmartActionType::class.java), any(Boolean::class.java), eq(testUser) ) ) .thenReturn(smartActionsFuture) } @Test fun testQueryQuickShare_noAction() { whenever( smartActions.getSmartActions( eq(testScreenshotId), eq(smartActionsFuture), any(Int::class.java), eq(smartActionsProvider), eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION) ) ) .thenReturn(ArrayList()) val quickShareAction = saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri) assertNull(quickShareAction) } @Test fun testQueryQuickShare_withActions() { val actions = ArrayList() actions.add(constructAction("Action One", mutablePendingIntent)) actions.add(constructAction("Action Two", mutablePendingIntent)) whenever( smartActions.getSmartActions( eq(testScreenshotId), eq(smartActionsUriFuture), any(Int::class.java), eq(smartActionsProvider), eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION) ) ) .thenReturn(actions) val quickShareAction = saveImageTask.queryQuickShareAction(testScreenshotId, testBitmap, testUser, testUri)!! assertEquals("Action One", quickShareAction.title) assertEquals(mutablePendingIntent, quickShareAction.actionIntent) } @Test fun testCreateQuickShareAction_originalWasNull_returnsNull() { val quickShareAction = saveImageTask.createQuickShareAction( null, testScreenshotId, testUri, testImageTime, testBitmap, testUser ) assertNull(quickShareAction) } @Test fun testCreateQuickShareAction_immutableIntentDifferentAction_returnsNull() { val actions = ArrayList() actions.add(constructAction("New Test Action", immutablePendingIntent)) whenever( smartActions.getSmartActions( eq(testScreenshotId), eq(smartActionsUriFuture), any(Int::class.java), eq(smartActionsProvider), eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION) ) ) .thenReturn(actions) val origAction = constructAction("Old Test Action", immutablePendingIntent) val quickShareAction = saveImageTask.createQuickShareAction( origAction, testScreenshotId, testUri, testImageTime, testBitmap, testUser, ) assertNull(quickShareAction) } @Test fun testCreateQuickShareAction_mutableIntent_returnsSafeIntent() { val actions = ArrayList() val action = constructAction("Action One", mutablePendingIntent) actions.add(action) whenever( smartActions.getSmartActions( eq(testScreenshotId), eq(smartActionsUriFuture), any(Int::class.java), eq(smartActionsProvider), eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION) ) ) .thenReturn(actions) val quickShareAction = saveImageTask.createQuickShareAction( constructAction("Test Action", mutablePendingIntent), testScreenshotId, testUri, testImageTime, testBitmap, testUser ) val quickSharePendingIntent = quickShareAction.actionIntent.intent.extras!!.getParcelable( ScreenshotController.EXTRA_ACTION_INTENT, PendingIntent::class.java ) assertEquals("Test Action", quickShareAction.title) assertEquals(mutablePendingIntent, quickSharePendingIntent) } @Test fun testCreateQuickShareAction_immutableIntent_returnsSafeIntent() { val actions = ArrayList() val action = constructAction("Test Action", immutablePendingIntent) actions.add(action) whenever( smartActions.getSmartActions( eq(testScreenshotId), eq(smartActionsUriFuture), any(Int::class.java), eq(smartActionsProvider), eq(ScreenshotSmartActionType.QUICK_SHARE_ACTION) ) ) .thenReturn(actions) val quickShareAction = saveImageTask.createQuickShareAction( constructAction("Test Action", immutablePendingIntent), testScreenshotId, testUri, testImageTime, testBitmap, testUser, )!! assertEquals("Test Action", quickShareAction.title) assertEquals( immutablePendingIntent, quickShareAction.actionIntent.intent.extras!!.getParcelable( ScreenshotController.EXTRA_ACTION_INTENT, PendingIntent::class.java ) ) } private fun constructAction(title: String, intent: PendingIntent): Notification.Action { return Notification.Action.Builder(testIcon, title, intent).build() } }