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