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.runWithShellPermissionIdentity
33 import com.android.compatibility.common.util.UiAutomatorUtils2.waitFindObject
34 import com.android.safetycenter.internaldata.SafetyCenterIds
35 import com.android.safetycenter.internaldata.SafetyCenterIssueId
36 import com.android.safetycenter.internaldata.SafetyCenterIssueKey
37 import org.junit.Assert
38 
39 object SafetyCenterUtils {
40     /** Name of the flag that determines whether SafetyCenter is enabled. */
41     const val PROPERTY_SAFETY_CENTER_ENABLED = "safety_center_is_enabled"
42 
43     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
44 
45     /** Returns whether the device supports Safety Center. */
46     @JvmStatic
deviceSupportsSafetyCenternull47     fun deviceSupportsSafetyCenter(context: Context): Boolean {
48         return context.resources.getBoolean(
49             Resources.getSystem().getIdentifier("config_enableSafetyCenter", "bool", "android")
50         )
51     }
52 
53     /** Enabled or disable Safety Center */
54     @JvmStatic
setSafetyCenterEnablednull55     fun setSafetyCenterEnabled(enabled: Boolean) {
56         setDeviceConfigPrivacyProperty(PROPERTY_SAFETY_CENTER_ENABLED, enabled.toString())
57     }
58 
59     @RequiresApi(Build.VERSION_CODES.TIRAMISU)
60     @JvmStatic
startSafetyCenterActivitynull61     fun startSafetyCenterActivity(context: Context) {
62         context.startActivity(
63             Intent(Intent.ACTION_SAFETY_CENTER)
64                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
65                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
66         )
67     }
68 
69     @JvmStatic
assertSafetyCenterStartednull70     fun assertSafetyCenterStarted() {
71         // CollapsingToolbar title can't be found by text, so using description instead.
72         waitFindObject(By.desc("Security & privacy"))
73     }
74 
75     @JvmStatic
setDeviceConfigPrivacyPropertynull76     fun setDeviceConfigPrivacyProperty(
77         propertyName: String,
78         value: String,
79         uiAutomation: UiAutomation = instrumentation.uiAutomation
80     ) {
81         runWithShellPermissionIdentity(uiAutomation) {
82             val valueWasSet =
83                 DeviceConfig.setProperty(
84                     DeviceConfig.NAMESPACE_PRIVACY,
85                     /* name = */ propertyName,
86                     /* value = */ value,
87                     /* makeDefault = */ false
88                 )
89             check(valueWasSet) { "Could not set $propertyName to $value" }
90         }
91     }
92 
93     @JvmStatic
deleteDeviceConfigPrivacyPropertynull94     fun deleteDeviceConfigPrivacyProperty(
95         propertyName: String,
96         uiAutomation: UiAutomation = instrumentation.uiAutomation
97     ) {
98         runWithShellPermissionIdentity(uiAutomation) {
99             DeviceConfig.deleteProperty(DeviceConfig.NAMESPACE_PRIVACY, propertyName)
100         }
101     }
102 
103     @JvmStatic
getSafetyCenterIssuesnull104     private fun getSafetyCenterIssues(
105         automation: UiAutomation = instrumentation.uiAutomation
106     ): List<SafetyCenterIssue> {
107         val safetyCenterManager =
108             instrumentation.targetContext.getSystemService(SafetyCenterManager::class.java)
109         val issues = ArrayList<SafetyCenterIssue>()
110         runWithShellPermissionIdentity(automation) {
111             val safetyCenterData = safetyCenterManager!!.safetyCenterData
112             issues.addAll(safetyCenterData.issues)
113         }
114         return issues
115     }
116 
117     @JvmStatic
assertSafetyCenterIssueExistnull118     fun assertSafetyCenterIssueExist(
119         sourceId: String,
120         issueId: String,
121         issueTypeId: String,
122         automation: UiAutomation = instrumentation.uiAutomation
123     ) {
124         val safetyCenterIssueId = safetyCenterIssueId(sourceId, issueId, issueTypeId)
125         Assert.assertTrue(
126             "Expect issues in safety center",
127             getSafetyCenterIssues(automation).any { safetyCenterIssueId == it.id }
128         )
129     }
130 
131     @JvmStatic
assertSafetyCenterIssueDoesNotExistnull132     fun assertSafetyCenterIssueDoesNotExist(
133         sourceId: String,
134         issueId: String,
135         issueTypeId: String,
136         automation: UiAutomation = instrumentation.uiAutomation
137     ) {
138         val safetyCenterIssueId = safetyCenterIssueId(sourceId, issueId, issueTypeId)
139         Assert.assertTrue(
140             "Expect no issue in safety center",
141             getSafetyCenterIssues(automation).none { safetyCenterIssueId == it.id }
142         )
143     }
144 
safetyCenterIssueIdnull145     private fun safetyCenterIssueId(sourceId: String, sourceIssueId: String, issueTypeId: String) =
146         SafetyCenterIds.encodeToString(
147             SafetyCenterIssueId.newBuilder()
148                 .setSafetyCenterIssueKey(
149                     SafetyCenterIssueKey.newBuilder()
150                         .setSafetySourceId(sourceId)
151                         .setSafetySourceIssueId(sourceIssueId)
152                         .setUserId(UserHandle.myUserId())
153                         .build()
154                 )
155                 .setIssueTypeId(issueTypeId)
156                 .build()
157         )
158 }
159