1 /*
2  * Copyright (C) 2019 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 package com.android.customization.module.logging
17 
18 import android.app.WallpaperManager
19 import android.content.Intent
20 import android.stats.style.StyleEnums.APP_LAUNCHED
21 import android.stats.style.StyleEnums.CLOCK_APPLIED
22 import android.stats.style.StyleEnums.CLOCK_COLOR_APPLIED
23 import android.stats.style.StyleEnums.CLOCK_SIZE_APPLIED
24 import android.stats.style.StyleEnums.DARK_THEME_APPLIED
25 import android.stats.style.StyleEnums.GRID_APPLIED
26 import android.stats.style.StyleEnums.LAUNCHED_CROP_AND_SET_ACTION
27 import android.stats.style.StyleEnums.LAUNCHED_DEEP_LINK
28 import android.stats.style.StyleEnums.LAUNCHED_KEYGUARD
29 import android.stats.style.StyleEnums.LAUNCHED_LAUNCHER
30 import android.stats.style.StyleEnums.LAUNCHED_LAUNCH_ICON
31 import android.stats.style.StyleEnums.LAUNCHED_PREFERENCE_UNSPECIFIED
32 import android.stats.style.StyleEnums.LAUNCHED_SETTINGS
33 import android.stats.style.StyleEnums.LAUNCHED_SETTINGS_SEARCH
34 import android.stats.style.StyleEnums.LAUNCHED_SUW
35 import android.stats.style.StyleEnums.LAUNCHED_TIPS
36 import android.stats.style.StyleEnums.LOCK_SCREEN_NOTIFICATION_APPLIED
37 import android.stats.style.StyleEnums.RESET_APPLIED
38 import android.stats.style.StyleEnums.SHORTCUT_APPLIED
39 import android.stats.style.StyleEnums.SNAPSHOT
40 import android.stats.style.StyleEnums.THEMED_ICON_APPLIED
41 import android.stats.style.StyleEnums.THEME_COLOR_APPLIED
42 import android.stats.style.StyleEnums.WALLPAPER_APPLIED
43 import android.stats.style.StyleEnums.WALLPAPER_DESTINATION_HOME_AND_LOCK_SCREEN
44 import android.stats.style.StyleEnums.WALLPAPER_DESTINATION_HOME_SCREEN
45 import android.stats.style.StyleEnums.WALLPAPER_DESTINATION_LOCK_SCREEN
46 import android.stats.style.StyleEnums.WALLPAPER_EFFECT_APPLIED
47 import android.stats.style.StyleEnums.WALLPAPER_EFFECT_FG_DOWNLOAD
48 import android.stats.style.StyleEnums.WALLPAPER_EFFECT_PROBE
49 import android.stats.style.StyleEnums.WALLPAPER_EXPLORE
50 import android.text.TextUtils
51 import com.android.customization.model.color.ColorCustomizationManager
52 import com.android.customization.model.grid.GridOption
53 import com.android.customization.module.logging.ThemesUserEventLogger.ClockSize
54 import com.android.customization.module.logging.ThemesUserEventLogger.ColorSource
55 import com.android.wallpaper.module.WallpaperPreferences
56 import com.android.wallpaper.module.logging.UserEventLogger.EffectStatus
57 import com.android.wallpaper.module.logging.UserEventLogger.SetWallpaperEntryPoint
58 import com.android.wallpaper.module.logging.UserEventLogger.WallpaperDestination
59 import com.android.wallpaper.util.LaunchSourceUtils
60 import javax.inject.Inject
61 import javax.inject.Singleton
62 
63 /** StatsLog-backed implementation of [ThemesUserEventLogger]. */
64 @Singleton
65 class ThemesUserEventLoggerImpl
66 @Inject
67 constructor(
68     private val preferences: WallpaperPreferences,
69     private val colorManager: ColorCustomizationManager,
70     private val appSessionId: AppSessionId,
71 ) : ThemesUserEventLogger {
72 
logSnapshotnull73     override fun logSnapshot() {
74         SysUiStatsLogger(SNAPSHOT)
75             .setWallpaperCategoryHash(preferences.getHomeCategoryHash())
76             .setWallpaperIdHash(preferences.getHomeWallpaperIdHash())
77             .setEffectIdHash(preferences.getHomeWallpaperEffectsIdHash())
78             .setLockWallpaperCategoryHash(preferences.getLockCategoryHash())
79             .setLockWallpaperIdHash(preferences.getLockWallpaperIdHash())
80             .setLockEffectIdHash(preferences.getLockWallpaperEffectsIdHash())
81             .setColorSource(colorManager.currentColorSourceForLogging)
82             .setColorVariant(colorManager.currentStyleForLogging)
83             .setSeedColor(colorManager.currentSeedColorForLogging)
84             .log()
85     }
86 
logAppLaunchednull87     override fun logAppLaunched(launchSource: Intent) {
88         SysUiStatsLogger(APP_LAUNCHED)
89             .setAppSessionId(appSessionId.createNewId().getId())
90             .setLaunchedPreference(launchSource.getAppLaunchSource())
91             .log()
92     }
93 
logWallpaperAppliednull94     override fun logWallpaperApplied(
95         collectionId: String?,
96         wallpaperId: String?,
97         effects: String?,
98         @SetWallpaperEntryPoint setWallpaperEntryPoint: Int,
99         @WallpaperDestination destination: Int,
100     ) {
101         val categoryHash = getIdHashCode(collectionId)
102         val wallpaperIdHash = getIdHashCode(wallpaperId)
103         val isHomeWallpaperSet =
104             destination == WALLPAPER_DESTINATION_HOME_SCREEN ||
105                 destination == WALLPAPER_DESTINATION_HOME_AND_LOCK_SCREEN
106         val isLockWallpaperSet =
107             destination == WALLPAPER_DESTINATION_LOCK_SCREEN ||
108                 destination == WALLPAPER_DESTINATION_HOME_AND_LOCK_SCREEN
109         SysUiStatsLogger(WALLPAPER_APPLIED)
110             .setAppSessionId(appSessionId.getId())
111             .setWallpaperCategoryHash(if (isHomeWallpaperSet) categoryHash else 0)
112             .setWallpaperIdHash(if (isHomeWallpaperSet) wallpaperIdHash else 0)
113             .setEffectIdHash(if (isHomeWallpaperSet) getIdHashCode(effects) else 0)
114             .setLockWallpaperCategoryHash(if (isLockWallpaperSet) categoryHash else 0)
115             .setLockWallpaperIdHash(if (isLockWallpaperSet) wallpaperIdHash else 0)
116             .setLockEffectIdHash(if (isLockWallpaperSet) getIdHashCode(effects) else 0)
117             .setSetWallpaperEntryPoint(setWallpaperEntryPoint)
118             .setWallpaperDestination(destination)
119             .log()
120     }
121 
logEffectApplynull122     override fun logEffectApply(
123         effect: String,
124         @EffectStatus status: Int,
125         timeElapsedMillis: Long,
126         resultCode: Int,
127     ) {
128         SysUiStatsLogger(WALLPAPER_EFFECT_APPLIED)
129             .setAppSessionId(appSessionId.getId())
130             .setEffectPreference(status)
131             .setEffectIdHash(getIdHashCode(effect))
132             .setTimeElapsed(timeElapsedMillis)
133             .setEffectResultCode(resultCode)
134             .log()
135     }
136 
logEffectProbenull137     override fun logEffectProbe(effect: String, @EffectStatus status: Int) {
138         SysUiStatsLogger(WALLPAPER_EFFECT_PROBE)
139             .setAppSessionId(appSessionId.getId())
140             .setEffectPreference(status)
141             .setEffectIdHash(getIdHashCode(effect))
142             .log()
143     }
144 
logEffectForegroundDownloadnull145     override fun logEffectForegroundDownload(
146         effect: String,
147         @EffectStatus status: Int,
148         timeElapsedMillis: Long,
149     ) {
150         SysUiStatsLogger(WALLPAPER_EFFECT_FG_DOWNLOAD)
151             .setAppSessionId(appSessionId.getId())
152             .setEffectPreference(status)
153             .setEffectIdHash(getIdHashCode(effect))
154             .setTimeElapsed(timeElapsedMillis)
155             .log()
156     }
157 
logResetAppliednull158     override fun logResetApplied() {
159         SysUiStatsLogger(RESET_APPLIED).setAppSessionId(appSessionId.getId()).log()
160     }
161 
logWallpaperExploreButtonClickednull162     override fun logWallpaperExploreButtonClicked() {
163         SysUiStatsLogger(WALLPAPER_EXPLORE).setAppSessionId(appSessionId.getId()).log()
164     }
165 
logThemeColorAppliednull166     override fun logThemeColorApplied(@ColorSource source: Int, style: Int, seedColor: Int) {
167         SysUiStatsLogger(THEME_COLOR_APPLIED)
168             .setAppSessionId(appSessionId.getId())
169             .setColorSource(source)
170             .setColorVariant(style)
171             .setSeedColor(seedColor)
172             .log()
173     }
174 
logGridAppliednull175     override fun logGridApplied(grid: GridOption) {
176         SysUiStatsLogger(GRID_APPLIED)
177             .setAppSessionId(appSessionId.getId())
178             .setLauncherGrid(grid.getLauncherGridInt())
179             .log()
180     }
181 
logClockAppliednull182     override fun logClockApplied(clockId: String) {
183         SysUiStatsLogger(CLOCK_APPLIED)
184             .setAppSessionId(appSessionId.getId())
185             .setClockPackageHash(getIdHashCode(clockId))
186             .log()
187     }
188 
logClockColorAppliednull189     override fun logClockColorApplied(seedColor: Int) {
190         SysUiStatsLogger(CLOCK_COLOR_APPLIED)
191             .setAppSessionId(appSessionId.getId())
192             .setSeedColor(seedColor)
193             .log()
194     }
195 
logClockSizeAppliednull196     override fun logClockSizeApplied(@ClockSize clockSize: Int) {
197         SysUiStatsLogger(CLOCK_SIZE_APPLIED)
198             .setAppSessionId(appSessionId.getId())
199             .setClockSize(clockSize)
200             .log()
201     }
202 
logThemedIconAppliednull203     override fun logThemedIconApplied(useThemeIcon: Boolean) {
204         SysUiStatsLogger(THEMED_ICON_APPLIED)
205             .setAppSessionId(appSessionId.getId())
206             .setToggleOn(useThemeIcon)
207             .log()
208     }
209 
logLockScreenNotificationAppliednull210     override fun logLockScreenNotificationApplied(showLockScreenNotifications: Boolean) {
211         SysUiStatsLogger(LOCK_SCREEN_NOTIFICATION_APPLIED)
212             .setAppSessionId(appSessionId.getId())
213             .setToggleOn(showLockScreenNotifications)
214             .log()
215     }
216 
logShortcutAppliednull217     override fun logShortcutApplied(shortcut: String, shortcutSlotId: String) {
218         SysUiStatsLogger(SHORTCUT_APPLIED)
219             .setAppSessionId(appSessionId.getId())
220             .setShortcut(shortcut)
221             .setShortcutSlotId(shortcutSlotId)
222             .log()
223     }
224 
logDarkThemeAppliednull225     override fun logDarkThemeApplied(useDarkTheme: Boolean) {
226         SysUiStatsLogger(DARK_THEME_APPLIED)
227             .setAppSessionId(appSessionId.getId())
228             .setToggleOn(useDarkTheme)
229             .log()
230     }
231 
232     /**
233      * The grid integer depends on the column and row numbers. For example: 4x5 is 405 13x37 is 1337
234      * The upper limit for the column / row count is 99.
235      */
GridOptionnull236     private fun GridOption.getLauncherGridInt(): Int {
237         return cols * 100 + rows
238     }
239 
getAppLaunchSourcenull240     private fun Intent.getAppLaunchSource(): Int {
241         return if (hasExtra(LaunchSourceUtils.WALLPAPER_LAUNCH_SOURCE)) {
242             when (getStringExtra(LaunchSourceUtils.WALLPAPER_LAUNCH_SOURCE)) {
243                 LaunchSourceUtils.LAUNCH_SOURCE_LAUNCHER -> LAUNCHED_LAUNCHER
244                 LaunchSourceUtils.LAUNCH_SOURCE_SETTINGS -> LAUNCHED_SETTINGS
245                 LaunchSourceUtils.LAUNCH_SOURCE_SUW -> LAUNCHED_SUW
246                 LaunchSourceUtils.LAUNCH_SOURCE_TIPS -> LAUNCHED_TIPS
247                 LaunchSourceUtils.LAUNCH_SOURCE_DEEP_LINK -> LAUNCHED_DEEP_LINK
248                 LaunchSourceUtils.LAUNCH_SOURCE_KEYGUARD -> LAUNCHED_KEYGUARD
249                 LaunchSourceUtils.LAUNCH_SOURCE_SETTINGS_SEARCH -> LAUNCHED_SETTINGS_SEARCH
250                 else -> LAUNCHED_PREFERENCE_UNSPECIFIED
251             }
252         } else if (action != null && action == WallpaperManager.ACTION_CROP_AND_SET_WALLPAPER) {
253             LAUNCHED_CROP_AND_SET_ACTION
254         } else if (categories != null && categories.contains(Intent.CATEGORY_LAUNCHER)) {
255             LAUNCHED_LAUNCH_ICON
256         } else {
257             LAUNCHED_PREFERENCE_UNSPECIFIED
258         }
259     }
260 
261     /** If not set, the output hash is 0. */
WallpaperPreferencesnull262     private fun WallpaperPreferences.getHomeCategoryHash(): Int {
263         return getIdHashCode(getHomeWallpaperCollectionId())
264     }
265 
266     /** If not set, the output hash is 0. */
WallpaperPreferencesnull267     private fun WallpaperPreferences.getHomeWallpaperIdHash(): Int {
268         val remoteId = getHomeWallpaperRemoteId()
269         val wallpaperId =
270             if (!TextUtils.isEmpty(remoteId)) remoteId else getHomeWallpaperServiceName()
271         return getIdHashCode(wallpaperId)
272     }
273 
274     /** If not set, the output hash is 0. */
WallpaperPreferencesnull275     private fun WallpaperPreferences.getLockCategoryHash(): Int {
276         return getIdHashCode(getLockWallpaperCollectionId())
277     }
278 
279     /** If not set, the output hash is 0. */
WallpaperPreferencesnull280     private fun WallpaperPreferences.getLockWallpaperIdHash(): Int {
281         val remoteId = getLockWallpaperRemoteId()
282         val wallpaperId =
283             if (!TextUtils.isEmpty(remoteId)) remoteId else getLockWallpaperServiceName()
284         return getIdHashCode(wallpaperId)
285     }
286 
287     /** If not set, the output hash is 0. */
WallpaperPreferencesnull288     private fun WallpaperPreferences.getHomeWallpaperEffectsIdHash(): Int {
289         return getIdHashCode(getHomeWallpaperEffects())
290     }
291 
292     /** If not set, the output hash is 0. */
getLockWallpaperEffectsIdHashnull293     private fun WallpaperPreferences.getLockWallpaperEffectsIdHash(): Int {
294         return getIdHashCode(getLockWallpaperEffects())
295     }
296 
getIdHashCodenull297     private fun getIdHashCode(id: String?): Int {
298         return id?.hashCode() ?: 0
299     }
300 }
301