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