1 /* 2 * Copyright (C) 2022 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 android.permission.cts 18 19 import android.app.Instrumentation 20 import android.app.UiAutomation 21 import android.content.Context 22 import android.content.Intent 23 import android.content.res.Resources 24 import android.os.Build 25 import android.os.UserHandle 26 import android.provider.DeviceConfig 27 import android.safetycenter.SafetyCenterIssue 28 import android.safetycenter.SafetyCenterManager 29 import androidx.annotation.RequiresApi 30 import androidx.test.platform.app.InstrumentationRegistry 31 import androidx.test.uiautomator.By 32 import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity 33 import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity 34 import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject 35 import com.android.safetycenter.internaldata.SafetyCenterIds 36 import com.android.safetycenter.internaldata.SafetyCenterIssueId 37 import com.android.safetycenter.internaldata.SafetyCenterIssueKey 38 import org.junit.Assert 39 import org.junit.Assume.assumeTrue 40 41 object SafetyCenterUtils { 42 /** Name of the flag that determines whether SafetyCenter is enabled. */ 43 const val PROPERTY_SAFETY_CENTER_ENABLED = "safety_center_is_enabled" 44 45 private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() 46 47 /** Returns whether the device supports Safety Center. */ 48 @JvmStatic deviceSupportsSafetyCenternull49 fun deviceSupportsSafetyCenter(context: Context): Boolean { 50 return context.resources.getBoolean( 51 Resources.getSystem().getIdentifier("config_enableSafetyCenter", "bool", "android") 52 ) 53 } 54 55 /** Enabled or disable Safety Center */ 56 @JvmStatic setSafetyCenterEnablednull57 fun setSafetyCenterEnabled(enabled: Boolean) { 58 setDeviceConfigPrivacyProperty(PROPERTY_SAFETY_CENTER_ENABLED, enabled.toString()) 59 val safetyCenterManager = 60 instrumentation.targetContext.getSystemService(SafetyCenterManager::class.java) 61 assumeTrue( 62 "Cannot toggle Safety Center", 63 callWithShellPermissionIdentity { 64 safetyCenterManager?.isSafetyCenterEnabled ?: false 65 } == enabled 66 ) 67 } 68 69 @RequiresApi(Build.VERSION_CODES.TIRAMISU) 70 @JvmStatic startSafetyCenterActivitynull71 fun startSafetyCenterActivity(context: Context) { 72 context.startActivity( 73 Intent(Intent.ACTION_SAFETY_CENTER) 74 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 75 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) 76 ) 77 } 78 79 @JvmStatic assertSafetyCenterStartednull80 fun assertSafetyCenterStarted() { 81 // CollapsingToolbar title can't be found by text, so using description instead. 82 waitFindObject(By.desc("Security & privacy")) 83 } 84 85 @JvmStatic setDeviceConfigPrivacyPropertynull86 fun setDeviceConfigPrivacyProperty( 87 propertyName: String, 88 value: String, 89 uiAutomation: UiAutomation = instrumentation.uiAutomation 90 ) { 91 runWithShellPermissionIdentity(uiAutomation) { 92 val valueWasSet = 93 DeviceConfig.setProperty( 94 DeviceConfig.NAMESPACE_PRIVACY, 95 /* name = */ propertyName, 96 /* value = */ value, 97 /* makeDefault = */ false 98 ) 99 check(valueWasSet) { "Could not set $propertyName to $value" } 100 } 101 } 102 103 @JvmStatic deleteDeviceConfigPrivacyPropertynull104 fun deleteDeviceConfigPrivacyProperty( 105 propertyName: String, 106 uiAutomation: UiAutomation = instrumentation.uiAutomation 107 ) { 108 runWithShellPermissionIdentity(uiAutomation) { 109 DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_PRIVACY, propertyName) 110 } 111 } 112 113 @JvmStatic getSafetyCenterIssuesnull114 private fun getSafetyCenterIssues( 115 automation: UiAutomation = instrumentation.uiAutomation 116 ): List<SafetyCenterIssue> { 117 val safetyCenterManager = 118 instrumentation.targetContext.getSystemService(SafetyCenterManager::class.java) 119 val issues = ArrayList<SafetyCenterIssue>() 120 runWithShellPermissionIdentity(automation) { 121 val safetyCenterData = safetyCenterManager!!.safetyCenterData 122 issues.addAll(safetyCenterData.issues) 123 } 124 return issues 125 } 126 127 @JvmStatic assertSafetyCenterIssueExistnull128 fun assertSafetyCenterIssueExist( 129 sourceId: String, 130 issueId: String, 131 issueTypeId: String, 132 automation: UiAutomation = instrumentation.uiAutomation 133 ) { 134 val safetyCenterIssueId = safetyCenterIssueId(sourceId, issueId, issueTypeId) 135 Assert.assertTrue( 136 "Expect issues in safety center", 137 getSafetyCenterIssues(automation).any { safetyCenterIssueId == it.id } 138 ) 139 } 140 141 @JvmStatic assertSafetyCenterIssueDoesNotExistnull142 fun assertSafetyCenterIssueDoesNotExist( 143 sourceId: String, 144 issueId: String, 145 issueTypeId: String, 146 automation: UiAutomation = instrumentation.uiAutomation 147 ) { 148 val safetyCenterIssueId = safetyCenterIssueId(sourceId, issueId, issueTypeId) 149 Assert.assertTrue( 150 "Expect no issue in safety center", 151 getSafetyCenterIssues(automation).none { safetyCenterIssueId == it.id } 152 ) 153 } 154 safetyCenterIssueIdnull155 private fun safetyCenterIssueId(sourceId: String, sourceIssueId: String, issueTypeId: String) = 156 SafetyCenterIds.encodeToString( 157 SafetyCenterIssueId.newBuilder() 158 .setSafetyCenterIssueKey( 159 SafetyCenterIssueKey.newBuilder() 160 .setSafetySourceId(sourceId) 161 .setSafetySourceIssueId(sourceIssueId) 162 .setUserId(UserHandle.myUserId()) 163 .build() 164 ) 165 .setIssueTypeId(issueTypeId) 166 .build() 167 ) 168 } 169