/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.privacy.logging import android.app.ActivityManager import android.content.Context import android.icu.text.SimpleDateFormat import android.permission.PermissionGroupUsage import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.log.core.LogMessage import com.android.systemui.log.dagger.PrivacyLog import com.android.systemui.privacy.PrivacyDialog import com.android.systemui.privacy.PrivacyDialogV2 import com.android.systemui.privacy.PrivacyItem import java.util.Locale import javax.inject.Inject private const val TAG = "PrivacyLog" private val DATE_FORMAT = SimpleDateFormat("MM-dd HH:mm:ss.SSS", Locale.US) class PrivacyLogger @Inject constructor( @PrivacyLog private val buffer: LogBuffer ) { fun logUpdatedItemFromAppOps(code: Int, uid: Int, packageName: String, active: Boolean) { log(LogLevel.INFO, { int1 = code int2 = uid str1 = packageName bool1 = active }, { "App Op: $int1 for $str1($int2), active=$bool1" }) } fun logLocationAppOps( uid: Int, packageName: String, importance: Int, isForeground: Boolean, isSystemApp: Boolean ) { log( LogLevel.INFO, { int1 = uid int2 = importance str1 = packageName bool1 = isForeground bool2 = isSystemApp }, { "Location Op: $str1($int1) importance=$int2 isFg=$bool1 isSystem=$bool2" }) } fun logUpdatedItemFromMediaProjection(uid: Int, packageName: String, active: Boolean) { log(LogLevel.INFO, { int1 = uid str1 = packageName bool1 = active }, { "MediaProjection: $str1($int1), active=$bool1" }) } fun logRetrievedPrivacyItemsList(list: List) { log(LogLevel.INFO, { str1 = listToString(list) }, { "Retrieved list to process: $str1" }) } fun logPrivacyItemsToHold(list: List) { log(LogLevel.DEBUG, { str1 = listToString(list) }, { "Holding items: $str1" }) } fun logPrivacyItemsUpdateScheduled(delay: Long) { log(LogLevel.INFO, { val scheduledFor = System.currentTimeMillis() + delay val formattedTimestamp = DATE_FORMAT.format(scheduledFor) str1 = formattedTimestamp }, { "Updating items scheduled for $str1" }) } fun logCurrentProfilesChanged(profiles: List) { log(LogLevel.INFO, { str1 = profiles.toString() }, { "Profiles changed: $str1" }) } fun logChipVisible(visible: Boolean) { log(LogLevel.INFO, { bool1 = visible }, { "Chip visible: $bool1" }) } fun logStatusBarIconsVisible( showCamera: Boolean, showMicrophone: Boolean, showLocation: Boolean ) { log(LogLevel.INFO, { bool1 = showCamera bool2 = showMicrophone bool3 = showLocation }, { "Status bar icons visible: camera=$bool1, microphone=$bool2, location=$bool3" }) } fun logUnfilteredPermGroupUsage(contents: List) { log(LogLevel.DEBUG, { str1 = contents.toString() }, { "Perm group usage: $str1" }) } fun logShowDialogContents(contents: List) { log(LogLevel.INFO, { str1 = contents.toString() }, { "Privacy dialog shown. Contents: $str1" }) } fun logShowDialogV2Contents(contents: List) { log(LogLevel.INFO, { str1 = contents.toString() }, { "Privacy dialog shown. Contents: $str1" }) } fun logEmptyDialog() { log(LogLevel.WARNING, {}, { "Trying to show an empty dialog" }) } fun logPrivacyDialogDismissed() { log(LogLevel.INFO, {}, { "Privacy dialog dismissed" }) } fun logStartSettingsActivityFromDialog(packageName: String, userId: Int) { log(LogLevel.INFO, { str1 = packageName int1 = userId }, { "Start settings activity from dialog for packageName=$str1, userId=$int1 " }) } fun logCloseAppFromDialog(packageName: String, userId: Int) { log(LogLevel.INFO, { str1 = packageName int1 = userId }, { "Close app from dialog for packageName=$str1, userId=$int1" }) } fun logStartPrivacyDashboardFromDialog() { log(LogLevel.INFO, {}, { "Start privacy dashboard from dialog" }) } fun logLabelNotFound(packageName: String) { log(LogLevel.WARNING, { str1 = packageName }, { "Label not found for: $str1" }) } private fun listToString(list: List): String { return list.joinToString(separator = ", ", transform = PrivacyItem::log) } private inline fun log( logLevel: LogLevel, initializer: LogMessage.() -> Unit, noinline printer: LogMessage.() -> String ) { buffer.log(TAG, logLevel, initializer, printer) } }