1 /* 2 * Copyright (C) 2023 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.systemui.qs.pipeline.domain.interactor 18 19 import android.content.pm.UserInfo 20 import android.os.UserManager 21 import androidx.test.ext.junit.runners.AndroidJUnit4 22 import androidx.test.filters.MediumTest 23 import com.android.systemui.SysuiTestCase 24 import com.android.systemui.coroutines.collectLastValue 25 import com.android.systemui.kosmos.testScope 26 import com.android.systemui.plugins.qs.QSTile 27 import com.android.systemui.qs.FakeQSFactory 28 import com.android.systemui.qs.FakeQSTile 29 import com.android.systemui.qs.pipeline.data.model.RestoreData 30 import com.android.systemui.qs.pipeline.data.repository.fakeRestoreRepository 31 import com.android.systemui.qs.pipeline.data.repository.fakeTileSpecRepository 32 import com.android.systemui.qs.pipeline.shared.TileSpec 33 import com.android.systemui.qs.qsTileFactory 34 import com.android.systemui.settings.fakeUserTracker 35 import com.android.systemui.settings.userTracker 36 import com.android.systemui.testKosmos 37 import com.google.common.truth.Truth.assertThat 38 import kotlinx.coroutines.test.TestScope 39 import kotlinx.coroutines.test.runCurrent 40 import kotlinx.coroutines.test.runTest 41 import org.junit.Before 42 import org.junit.Test 43 import org.junit.runner.RunWith 44 45 /** 46 * This integration test is for testing the solution to b/314781280. In particular, there are two 47 * issues we want to verify after a restore of a device with a work profile and a work mode tile: 48 * * When the work profile is re-enabled in the target device, it is auto-added. 49 * * The tile is auto-added in the same position that it was in the restored device. 50 */ 51 @MediumTest 52 @RunWith(AndroidJUnit4::class) 53 class WorkProfileAutoAddedAfterRestoreTest : SysuiTestCase() { 54 <lambda>null55 private val kosmos by lazy { 56 testKosmos().apply { fakeUserTracker.set(listOf(USER_0_INFO), 0) } 57 } 58 // Getter here so it can change when there is a managed profile. 59 private val workTileAvailable: Boolean 60 get() = hasManagedProfile() 61 62 private val currentUser: Int 63 get() = kosmos.userTracker.userId 64 65 private val testScope: TestScope 66 get() = kosmos.testScope 67 68 @Before setUpnull69 fun setUp() { 70 kosmos.qsTileFactory = FakeQSFactory(::tileCreator) 71 kosmos.restoreReconciliationInteractor.start() 72 kosmos.autoAddInteractor.init(kosmos.currentTilesInteractor) 73 } 74 75 @Test workTileRestoredAndPreviouslyAutoAdded_notAvailable_willBeAutoaddedInCorrectPositionnull76 fun workTileRestoredAndPreviouslyAutoAdded_notAvailable_willBeAutoaddedInCorrectPosition() = 77 testScope.runTest { 78 val tiles by collectLastValue(kosmos.currentTilesInteractor.currentTiles) 79 80 // Set up 81 val currentTiles = listOf("a".toTileSpec()) 82 kosmos.fakeTileSpecRepository.setTiles(currentUser, currentTiles) 83 84 val restoredTiles = 85 listOf(WORK_TILE_SPEC) + listOf("b", "c", "d").map { it.toTileSpec() } 86 val restoredAutoAdded = setOf(WORK_TILE_SPEC) 87 88 val restoreData = RestoreData(restoredTiles, restoredAutoAdded, currentUser) 89 90 // WHEN we restore tiles that auto-added the WORK tile and it's not available (there 91 // are no managed profiles) 92 kosmos.fakeRestoreRepository.onDataRestored(restoreData) 93 94 // THEN the work tile is not part of the current tiles 95 assertThat(tiles!!).hasSize(3) 96 assertThat(tiles!!.map { it.spec }).doesNotContain(WORK_TILE_SPEC) 97 98 // WHEN we add a work profile 99 createManagedProfileAndAdd() 100 101 // THEN the work profile is added in the correct place 102 assertThat(tiles!!.first().spec).isEqualTo(WORK_TILE_SPEC) 103 } 104 105 @Test workTileNotRestoredAndPreviouslyAutoAdded_wontBeAutoAddedWhenWorkProfileIsAddednull106 fun workTileNotRestoredAndPreviouslyAutoAdded_wontBeAutoAddedWhenWorkProfileIsAdded() = 107 testScope.runTest { 108 val tiles by collectLastValue(kosmos.currentTilesInteractor.currentTiles) 109 110 // Set up 111 val currentTiles = listOf("a".toTileSpec()) 112 kosmos.fakeTileSpecRepository.setTiles(currentUser, currentTiles) 113 runCurrent() 114 115 val restoredTiles = listOf("b", "c", "d").map { it.toTileSpec() } 116 val restoredAutoAdded = setOf(WORK_TILE_SPEC) 117 118 val restoreData = RestoreData(restoredTiles, restoredAutoAdded, currentUser) 119 120 // WHEN we restore tiles that auto-added the WORK tile 121 kosmos.fakeRestoreRepository.onDataRestored(restoreData) 122 123 // THEN the work tile is not part of the current tiles 124 assertThat(tiles!!).hasSize(3) 125 assertThat(tiles!!.map { it.spec }).doesNotContain(WORK_TILE_SPEC) 126 127 // WHEN we add a work profile 128 createManagedProfileAndAdd() 129 130 // THEN the work profile is not added because the user had manually removed it in the 131 // past 132 assertThat(tiles!!.map { it.spec }).doesNotContain(WORK_TILE_SPEC) 133 } 134 tileCreatornull135 private fun tileCreator(spec: String): QSTile { 136 return if (spec == WORK_TILE_SPEC.spec) { 137 FakeQSTile(currentUser, workTileAvailable) 138 } else { 139 FakeQSTile(currentUser) 140 } 141 } 142 hasManagedProfilenull143 private fun hasManagedProfile(): Boolean { 144 return kosmos.userTracker.userProfiles.any { it.isManagedProfile } 145 } 146 TestScopenull147 private fun TestScope.createManagedProfileAndAdd() { 148 kosmos.fakeUserTracker.set(listOf(USER_0_INFO, MANAGED_USER_INFO), 0) 149 runCurrent() 150 } 151 152 private companion object { 153 val WORK_TILE_SPEC = "work".toTileSpec() 154 val USER_0_INFO = UserInfo(0, "zero", "", UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL) 155 val MANAGED_USER_INFO = 156 UserInfo(10, "ten-managed", "", 0, UserManager.USER_TYPE_PROFILE_MANAGED) 157 toTileSpecnull158 fun String.toTileSpec() = TileSpec.create(this) 159 } 160 } 161