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.assist 18 19 import android.content.ComponentName 20 import android.content.Context 21 import android.content.pm.PackageManager 22 import android.util.Log 23 import com.android.internal.app.AssistUtils 24 import com.android.internal.logging.InstanceId 25 import com.android.internal.logging.InstanceIdSequence 26 import com.android.internal.logging.UiEventLogger 27 import com.android.internal.util.FrameworkStatsLog 28 import com.android.systemui.assist.AssistantInvocationEvent.Companion.deviceStateFromLegacyDeviceState 29 import com.android.systemui.assist.AssistantInvocationEvent.Companion.eventFromLegacyInvocationType 30 import com.android.systemui.dagger.SysUISingleton 31 import com.android.systemui.settings.UserTracker 32 import javax.inject.Inject 33 34 /** Class for reporting events related to Assistant sessions. */ 35 @SysUISingleton 36 open class AssistLogger @Inject constructor( 37 protected val context: Context, 38 protected val uiEventLogger: UiEventLogger, 39 private val assistUtils: AssistUtils, 40 private val phoneStateMonitor: PhoneStateMonitor, 41 private val userTracker: UserTracker, 42 ) { 43 44 private val instanceIdSequence = InstanceIdSequence(INSTANCE_ID_MAX) 45 46 private var currentInstanceId: InstanceId? = null 47 reportAssistantInvocationEventFromLegacynull48 fun reportAssistantInvocationEventFromLegacy( 49 legacyInvocationType: Int, 50 isInvocationComplete: Boolean, 51 assistantComponent: ComponentName? = null, 52 legacyDeviceState: Int? = null 53 ) { 54 val deviceState = if (legacyDeviceState == null) { 55 null 56 } else { 57 deviceStateFromLegacyDeviceState(legacyDeviceState) 58 } 59 reportAssistantInvocationEvent( 60 eventFromLegacyInvocationType(legacyInvocationType, isInvocationComplete), 61 assistantComponent, 62 deviceState) 63 } 64 reportAssistantInvocationEventnull65 fun reportAssistantInvocationEvent( 66 invocationEvent: UiEventLogger.UiEventEnum, 67 assistantComponent: ComponentName? = null, 68 deviceState: Int? = null 69 ) { 70 71 val assistComponentFinal = assistantComponent ?: getAssistantComponentForCurrentUser() 72 73 val assistantUid = getAssistantUid(assistComponentFinal) 74 75 val deviceStateFinal = deviceState 76 ?: deviceStateFromLegacyDeviceState(phoneStateMonitor.phoneState) 77 78 FrameworkStatsLog.write( 79 FrameworkStatsLog.ASSISTANT_INVOCATION_REPORTED, 80 invocationEvent.id, 81 assistantUid, 82 assistComponentFinal?.flattenToString() ?: "", 83 getOrCreateInstanceId().id, 84 deviceStateFinal, 85 false) 86 reportAssistantInvocationExtraData() 87 } 88 reportAssistantSessionEventnull89 fun reportAssistantSessionEvent(sessionEvent: UiEventLogger.UiEventEnum) { 90 val assistantComponent = getAssistantComponentForCurrentUser() 91 val assistantUid = getAssistantUid(assistantComponent) 92 uiEventLogger.logWithInstanceId( 93 sessionEvent, 94 assistantUid, 95 assistantComponent?.flattenToString(), 96 getOrCreateInstanceId()) 97 98 if (SESSION_END_EVENTS.contains(sessionEvent)) { 99 clearInstanceId() 100 } 101 } 102 reportAssistantInvocationExtraDatanull103 protected open fun reportAssistantInvocationExtraData() { 104 } 105 getOrCreateInstanceIdnull106 protected fun getOrCreateInstanceId(): InstanceId { 107 val instanceId = currentInstanceId ?: instanceIdSequence.newInstanceId() 108 currentInstanceId = instanceId 109 return instanceId 110 } 111 clearInstanceIdnull112 protected fun clearInstanceId() { 113 currentInstanceId = null 114 } 115 getAssistantComponentForCurrentUsernull116 protected fun getAssistantComponentForCurrentUser(): ComponentName? { 117 return assistUtils.getAssistComponentForUser(userTracker.userId) 118 } 119 getAssistantUidnull120 protected fun getAssistantUid(assistantComponent: ComponentName?): Int { 121 if (assistantComponent == null) { 122 return 0 123 } 124 125 var assistantUid = 0 126 try { 127 assistantUid = context.packageManager.getApplicationInfo( 128 assistantComponent.packageName, /* flags = */ 129 0).uid 130 } catch (e: PackageManager.NameNotFoundException) { 131 Log.e(TAG, "Unable to find Assistant UID", e) 132 } 133 return assistantUid 134 } 135 136 companion object { 137 protected const val TAG = "AssistLogger" 138 139 private const val INSTANCE_ID_MAX = 1 shl 20 140 141 private val SESSION_END_EVENTS = 142 setOf( 143 AssistantSessionEvent.ASSISTANT_SESSION_INVOCATION_CANCELLED, 144 AssistantSessionEvent.ASSISTANT_SESSION_CLOSE) 145 } 146 } 147