1 /*
2  * Copyright (C) 2020 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.privacy.logging
18 
19 import android.icu.text.SimpleDateFormat
20 import android.permission.PermissionGroupUsage
21 import com.android.systemui.log.LogBuffer
22 import com.android.systemui.log.core.LogLevel
23 import com.android.systemui.log.core.LogMessage
24 import com.android.systemui.log.dagger.PrivacyLog
25 import com.android.systemui.privacy.PrivacyDialog
26 import com.android.systemui.privacy.PrivacyDialogV2
27 import com.android.systemui.privacy.PrivacyItem
28 import java.util.Locale
29 import javax.inject.Inject
30 
31 private const val TAG = "PrivacyLog"
32 private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US)
33 class PrivacyLogger @Inject constructor(
34     @PrivacyLog private val buffer: LogBuffer
35 ) {
36 
logUpdatedItemFromAppOpsnull37     fun logUpdatedItemFromAppOps(code: Int, uid: Int, packageName: String, active: Boolean) {
38         log(LogLevel.INFO, {
39             int1 = code
40             int2 = uid
41             str1 = packageName
42             bool1 = active
43         }, {
44             "App Op: $int1 for $str1($int2), active=$bool1"
45         })
46     }
47 
logUpdatedItemFromMediaProjectionnull48     fun logUpdatedItemFromMediaProjection(uid: Int, packageName: String, active: Boolean) {
49         log(LogLevel.INFO, {
50             int1 = uid
51             str1 = packageName
52             bool1 = active
53         }, {
54             "MediaProjection: $str1($int1), active=$bool1"
55         })
56     }
57 
logRetrievedPrivacyItemsListnull58     fun logRetrievedPrivacyItemsList(list: List<PrivacyItem>) {
59         log(LogLevel.INFO, {
60             str1 = listToString(list)
61         }, {
62             "Retrieved list to process: $str1"
63         })
64     }
65 
logPrivacyItemsToHoldnull66     fun logPrivacyItemsToHold(list: List<PrivacyItem>) {
67         log(LogLevel.DEBUG, {
68             str1 = listToString(list)
69         }, {
70             "Holding items: $str1"
71         })
72     }
73 
logPrivacyItemsUpdateSchedulednull74     fun logPrivacyItemsUpdateScheduled(delay: Long) {
75         log(LogLevel.INFO, {
76             val scheduledFor = System.currentTimeMillis() + delay
77             val formattedTimestamp = DATE_FORMAT.format(scheduledFor)
78             str1 = formattedTimestamp
79         }, {
80             "Updating items scheduled for $str1"
81         })
82     }
83 
logCurrentProfilesChangednull84     fun logCurrentProfilesChanged(profiles: List<Int>) {
85         log(LogLevel.INFO, {
86             str1 = profiles.toString()
87         }, {
88             "Profiles changed: $str1"
89         })
90     }
91 
logChipVisiblenull92     fun logChipVisible(visible: Boolean) {
93         log(LogLevel.INFO, {
94             bool1 = visible
95         }, {
96             "Chip visible: $bool1"
97         })
98     }
99 
logStatusBarIconsVisiblenull100     fun logStatusBarIconsVisible(
101         showCamera: Boolean,
102         showMicrophone: Boolean,
103         showLocation: Boolean
104     ) {
105         log(LogLevel.INFO, {
106             bool1 = showCamera
107             bool2 = showMicrophone
108             bool3 = showLocation
109         }, {
110             "Status bar icons visible: camera=$bool1, microphone=$bool2, location=$bool3"
111         })
112     }
113 
logUnfilteredPermGroupUsagenull114     fun logUnfilteredPermGroupUsage(contents: List<PermissionGroupUsage>) {
115         log(LogLevel.DEBUG, {
116             str1 = contents.toString()
117         }, {
118             "Perm group usage: $str1"
119         })
120     }
121 
logShowDialogContentsnull122     fun logShowDialogContents(contents: List<PrivacyDialog.PrivacyElement>) {
123         log(LogLevel.INFO, {
124             str1 = contents.toString()
125         }, {
126             "Privacy dialog shown. Contents: $str1"
127         })
128     }
129 
logShowDialogV2Contentsnull130     fun logShowDialogV2Contents(contents: List<PrivacyDialogV2.PrivacyElement>) {
131         log(LogLevel.INFO, {
132             str1 = contents.toString()
133         }, {
134             "Privacy dialog shown. Contents: $str1"
135         })
136     }
137 
logEmptyDialognull138     fun logEmptyDialog() {
139         log(LogLevel.WARNING, {}, {
140             "Trying to show an empty dialog"
141         })
142     }
143 
logPrivacyDialogDismissednull144     fun logPrivacyDialogDismissed() {
145         log(LogLevel.INFO, {}, {
146             "Privacy dialog dismissed"
147         })
148     }
149 
logStartSettingsActivityFromDialognull150     fun logStartSettingsActivityFromDialog(packageName: String, userId: Int) {
151         log(LogLevel.INFO, {
152             str1 = packageName
153             int1 = userId
154         }, {
155             "Start settings activity from dialog for packageName=$str1, userId=$int1 "
156         })
157     }
158 
logCloseAppFromDialognull159     fun logCloseAppFromDialog(packageName: String, userId: Int) {
160         log(LogLevel.INFO, {
161             str1 = packageName
162             int1 = userId
163         }, {
164             "Close app from dialog for packageName=$str1, userId=$int1"
165         })
166     }
167 
logStartPrivacyDashboardFromDialognull168     fun logStartPrivacyDashboardFromDialog() {
169         log(LogLevel.INFO, {}, { "Start privacy dashboard from dialog" })
170     }
171 
logLabelNotFoundnull172     fun logLabelNotFound(packageName: String) {
173         log(LogLevel.WARNING, { str1 = packageName }, { "Label not found for: $str1" })
174     }
175 
listToStringnull176     private fun listToString(list: List<PrivacyItem>): String {
177         return list.joinToString(separator = ", ", transform = PrivacyItem::log)
178     }
179 
lognull180     private inline fun log(
181         logLevel: LogLevel,
182         initializer: LogMessage.() -> Unit,
183         noinline printer: LogMessage.() -> String
184     ) {
185         buffer.log(TAG, logLevel, initializer, printer)
186     }
187 }
188