Loading packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt +75 −47 Original line number Diff line number Diff line Loading @@ -22,15 +22,18 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.os.UserManager import android.util.Log import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import androidx.annotation.VisibleForTesting import com.android.systemui.dagger.SysUISingleton import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity import com.android.systemui.util.kotlin.getOrNull import com.android.wm.shell.bubbles.Bubble import com.android.wm.shell.bubbles.Bubbles import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener import java.util.Optional import java.util.concurrent.atomic.AtomicReference import javax.inject.Inject /** Loading @@ -41,18 +44,40 @@ import javax.inject.Inject * Currently, we only support a single task per time. */ @SysUISingleton internal class NoteTaskController class NoteTaskController @Inject constructor( private val context: Context, private val resolver: NoteTaskInfoResolver, private val eventLogger: NoteTaskEventLogger, private val optionalBubbles: Optional<Bubbles>, private val optionalKeyguardManager: Optional<KeyguardManager>, private val optionalUserManager: Optional<UserManager>, private val optionalKeyguardManager: Optional<KeyguardManager>, @NoteTaskEnabledKey private val isEnabled: Boolean, private val uiEventLogger: UiEventLogger, ) { @VisibleForTesting val infoReference = AtomicReference<NoteTaskInfo?>() /** @see BubbleExpandListener */ fun onBubbleExpandChanged(isExpanding: Boolean, key: String?) { if (!isEnabled) return if (key != Bubble.KEY_APP_BUBBLE) return val info = infoReference.getAndSet(null) // Safe guard mechanism, this callback should only be called for app bubbles. if (info?.launchMode != NoteTaskLaunchMode.AppBubble) return if (isExpanding) { logDebug { "onBubbleExpandChanged - expanding: $info" } eventLogger.logNoteTaskOpened(info) } else { logDebug { "onBubbleExpandChanged - collapsing: $info" } eventLogger.logNoteTaskClosed(info) } } /** * Shows a note task. How the task is shown will depend on when the method is invoked. * Loading @@ -69,32 +94,50 @@ constructor( * That will let users open other apps in full screen, and take contextual notes. */ @JvmOverloads fun showNoteTask(isInMultiWindowMode: Boolean = false, uiEvent: ShowNoteTaskUiEvent? = null) { fun showNoteTask( entryPoint: NoteTaskEntryPoint, isInMultiWindowMode: Boolean = false, ) { if (!isEnabled) return val bubbles = optionalBubbles.getOrNull() ?: return val keyguardManager = optionalKeyguardManager.getOrNull() ?: return val userManager = optionalUserManager.getOrNull() ?: return val keyguardManager = optionalKeyguardManager.getOrNull() ?: return // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing. if (!userManager.isUserUnlocked) return val noteTaskInfo = resolver.resolveInfo() ?: return val info = resolver.resolveInfo( entryPoint = entryPoint, isInMultiWindowMode = isInMultiWindowMode, isKeyguardLocked = keyguardManager.isKeyguardLocked, ) ?: return uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) } infoReference.set(info) // TODO(b/266686199): We should handle when app not available. For now, we log. val intent = noteTaskInfo.toCreateNoteIntent() val intent = createNoteIntent(info) try { if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) { context.startActivity(intent) } else { logDebug { "onShowNoteTask - start: $info" } when (info.launchMode) { is NoteTaskLaunchMode.AppBubble -> { bubbles.showOrHideAppBubble(intent) // App bubble logging happens on `onBubbleExpandChanged`. logDebug { "onShowNoteTask - opened as app bubble: $info" } } is NoteTaskLaunchMode.Activity -> { context.startActivity(intent) eventLogger.logNoteTaskOpened(info) logDebug { "onShowNoteTask - opened as activity: $info" } } } logDebug { "onShowNoteTask - success: $info" } } catch (e: ActivityNotFoundException) { Log.e(TAG, "Activity not found for action: $ACTION_CREATE_NOTE.", e) logDebug { "onShowNoteTask - failed: $info" } } logDebug { "onShowNoteTask - compoleted: $info" } } /** Loading @@ -119,41 +162,12 @@ constructor( enabledState, PackageManager.DONT_KILL_APP, ) } /** IDs of UI events accepted by [showNoteTask]. */ enum class ShowNoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.") NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294), /* ktlint-disable max-line-length */ @UiEvent( doc = "User opened a note by pressing the stylus tail button while the screen was unlocked." ) NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295), @UiEvent( doc = "User opened a note by pressing the stylus tail button while the screen was locked." ) NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296), @UiEvent(doc = "User opened a note by tapping on an app shortcut.") NOTE_OPENED_VIA_SHORTCUT(1297); override fun getId() = _id logDebug { "setNoteTaskShortcutEnabled - completed: $isEnabled" } } companion object { private val TAG = NoteTaskController::class.simpleName.orEmpty() private fun NoteTaskInfoResolver.NoteTaskInfo.toCreateNoteIntent(): Intent { return Intent(ACTION_CREATE_NOTE) .setPackage(packageName) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint // was used to start it. .putExtra(INTENT_EXTRA_USE_STYLUS_MODE, true) } val TAG = NoteTaskController::class.simpleName.orEmpty() // TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead. const val NOTE_TASK_KEY_EVENT = 311 Loading @@ -165,3 +179,17 @@ constructor( const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE" } } private fun createNoteIntent(info: NoteTaskInfo): Intent = Intent(NoteTaskController.ACTION_CREATE_NOTE) .setPackage(info.packageName) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint // was used to start it. .putExtra(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true) private inline fun logDebug(message: () -> String) { if (Build.IS_DEBUGGABLE) { Log.d(NoteTaskController.TAG, message()) } } packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt +1 −1 Original line number Diff line number Diff line Loading @@ -19,4 +19,4 @@ package com.android.systemui.notetask import javax.inject.Qualifier /** Key associated with a [Boolean] flag that enables or disables the note task feature. */ @Qualifier internal annotation class NoteTaskEnabledKey @Qualifier annotation class NoteTaskEnabledKey packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.notetask import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity import com.android.systemui.screenshot.AppClipsTrampolineActivity /** * Supported entry points for [NoteTaskController.showNoteTask]. * * An entry point represents where the note task has ben called from. In rare cases, it may * represent a "re-entry" (i.e., [APP_CLIPS]). */ enum class NoteTaskEntryPoint { /** @see [LaunchNoteTaskActivity] */ WIDGET_PICKER_SHORTCUT, /** @see [NoteTaskQuickAffordanceConfig] */ QUICK_AFFORDANCE, /** @see [NoteTaskInitializer.callbacks] */ TAIL_BUTTON, /** @see [AppClipsTrampolineActivity] */ APP_CLIPS, } packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.notetask import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import com.android.systemui.notetask.NoteTaskEntryPoint.APP_CLIPS import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED import javax.inject.Inject /** * A wrapper around [UiEventLogger] specialized in the note taking UI events. * * if the accepted [NoteTaskInfo] contains a [NoteTaskInfo.entryPoint], it will be logged as the * correct [NoteTaskUiEvent]. If null, it will be ignored. * * @see NoteTaskController for usage examples. */ class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) { /** Logs a [NoteTaskInfo] as an **open** [NoteTaskUiEvent], including package name and uid. */ fun logNoteTaskOpened(info: NoteTaskInfo) { val event = when (info.entryPoint) { TAIL_BUTTON -> { if (info.isKeyguardLocked) { NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED } else { NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON } } WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE APP_CLIPS -> return null -> return } uiEventLogger.log(event, info.uid, info.packageName) } /** Logs a [NoteTaskInfo] as a **closed** [NoteTaskUiEvent], including package name and uid. */ fun logNoteTaskClosed(info: NoteTaskInfo) { val event = when (info.entryPoint) { TAIL_BUTTON -> { if (info.isKeyguardLocked) { NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED } else { NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON } } WIDGET_PICKER_SHORTCUT -> return QUICK_AFFORDANCE -> return APP_CLIPS -> return null -> return } uiEventLogger.log(event, info.uid, info.packageName) } /** IDs of UI events accepted by [NoteTaskController]. */ enum class NoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.") NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294), @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was unlocked.") // ktlint-disable max-line-length NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295), @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was locked.") // ktlint-disable max-line-length NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296), @UiEvent(doc = "User opened a note by tapping on an app shortcut.") NOTE_OPENED_VIA_SHORTCUT(1297), @UiEvent(doc = "Note closed via a tail button while device is unlocked") NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON(1311), @UiEvent(doc = "Note closed via a tail button while device is locked") NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1312); override fun getId() = _id } } packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.notetask /** Contextual information required to launch a Note Task by [NoteTaskController]. */ data class NoteTaskInfo( val packageName: String, val uid: Int, val entryPoint: NoteTaskEntryPoint? = null, val isInMultiWindowMode: Boolean = false, val isKeyguardLocked: Boolean = false, ) { val launchMode: NoteTaskLaunchMode = if (isInMultiWindowMode || isKeyguardLocked) { NoteTaskLaunchMode.Activity } else { NoteTaskLaunchMode.AppBubble } } Loading
packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt +75 −47 Original line number Diff line number Diff line Loading @@ -22,15 +22,18 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.os.Build import android.os.UserManager import android.util.Log import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import androidx.annotation.VisibleForTesting import com.android.systemui.dagger.SysUISingleton import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity import com.android.systemui.util.kotlin.getOrNull import com.android.wm.shell.bubbles.Bubble import com.android.wm.shell.bubbles.Bubbles import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener import java.util.Optional import java.util.concurrent.atomic.AtomicReference import javax.inject.Inject /** Loading @@ -41,18 +44,40 @@ import javax.inject.Inject * Currently, we only support a single task per time. */ @SysUISingleton internal class NoteTaskController class NoteTaskController @Inject constructor( private val context: Context, private val resolver: NoteTaskInfoResolver, private val eventLogger: NoteTaskEventLogger, private val optionalBubbles: Optional<Bubbles>, private val optionalKeyguardManager: Optional<KeyguardManager>, private val optionalUserManager: Optional<UserManager>, private val optionalKeyguardManager: Optional<KeyguardManager>, @NoteTaskEnabledKey private val isEnabled: Boolean, private val uiEventLogger: UiEventLogger, ) { @VisibleForTesting val infoReference = AtomicReference<NoteTaskInfo?>() /** @see BubbleExpandListener */ fun onBubbleExpandChanged(isExpanding: Boolean, key: String?) { if (!isEnabled) return if (key != Bubble.KEY_APP_BUBBLE) return val info = infoReference.getAndSet(null) // Safe guard mechanism, this callback should only be called for app bubbles. if (info?.launchMode != NoteTaskLaunchMode.AppBubble) return if (isExpanding) { logDebug { "onBubbleExpandChanged - expanding: $info" } eventLogger.logNoteTaskOpened(info) } else { logDebug { "onBubbleExpandChanged - collapsing: $info" } eventLogger.logNoteTaskClosed(info) } } /** * Shows a note task. How the task is shown will depend on when the method is invoked. * Loading @@ -69,32 +94,50 @@ constructor( * That will let users open other apps in full screen, and take contextual notes. */ @JvmOverloads fun showNoteTask(isInMultiWindowMode: Boolean = false, uiEvent: ShowNoteTaskUiEvent? = null) { fun showNoteTask( entryPoint: NoteTaskEntryPoint, isInMultiWindowMode: Boolean = false, ) { if (!isEnabled) return val bubbles = optionalBubbles.getOrNull() ?: return val keyguardManager = optionalKeyguardManager.getOrNull() ?: return val userManager = optionalUserManager.getOrNull() ?: return val keyguardManager = optionalKeyguardManager.getOrNull() ?: return // TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing. if (!userManager.isUserUnlocked) return val noteTaskInfo = resolver.resolveInfo() ?: return val info = resolver.resolveInfo( entryPoint = entryPoint, isInMultiWindowMode = isInMultiWindowMode, isKeyguardLocked = keyguardManager.isKeyguardLocked, ) ?: return uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) } infoReference.set(info) // TODO(b/266686199): We should handle when app not available. For now, we log. val intent = noteTaskInfo.toCreateNoteIntent() val intent = createNoteIntent(info) try { if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) { context.startActivity(intent) } else { logDebug { "onShowNoteTask - start: $info" } when (info.launchMode) { is NoteTaskLaunchMode.AppBubble -> { bubbles.showOrHideAppBubble(intent) // App bubble logging happens on `onBubbleExpandChanged`. logDebug { "onShowNoteTask - opened as app bubble: $info" } } is NoteTaskLaunchMode.Activity -> { context.startActivity(intent) eventLogger.logNoteTaskOpened(info) logDebug { "onShowNoteTask - opened as activity: $info" } } } logDebug { "onShowNoteTask - success: $info" } } catch (e: ActivityNotFoundException) { Log.e(TAG, "Activity not found for action: $ACTION_CREATE_NOTE.", e) logDebug { "onShowNoteTask - failed: $info" } } logDebug { "onShowNoteTask - compoleted: $info" } } /** Loading @@ -119,41 +162,12 @@ constructor( enabledState, PackageManager.DONT_KILL_APP, ) } /** IDs of UI events accepted by [showNoteTask]. */ enum class ShowNoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.") NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294), /* ktlint-disable max-line-length */ @UiEvent( doc = "User opened a note by pressing the stylus tail button while the screen was unlocked." ) NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295), @UiEvent( doc = "User opened a note by pressing the stylus tail button while the screen was locked." ) NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296), @UiEvent(doc = "User opened a note by tapping on an app shortcut.") NOTE_OPENED_VIA_SHORTCUT(1297); override fun getId() = _id logDebug { "setNoteTaskShortcutEnabled - completed: $isEnabled" } } companion object { private val TAG = NoteTaskController::class.simpleName.orEmpty() private fun NoteTaskInfoResolver.NoteTaskInfo.toCreateNoteIntent(): Intent { return Intent(ACTION_CREATE_NOTE) .setPackage(packageName) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint // was used to start it. .putExtra(INTENT_EXTRA_USE_STYLUS_MODE, true) } val TAG = NoteTaskController::class.simpleName.orEmpty() // TODO(b/254604589): Use final KeyEvent.KEYCODE_* instead. const val NOTE_TASK_KEY_EVENT = 311 Loading @@ -165,3 +179,17 @@ constructor( const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE" } } private fun createNoteIntent(info: NoteTaskInfo): Intent = Intent(NoteTaskController.ACTION_CREATE_NOTE) .setPackage(info.packageName) .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // EXTRA_USE_STYLUS_MODE does not mean a stylus is in-use, but a stylus entrypoint // was used to start it. .putExtra(NoteTaskController.INTENT_EXTRA_USE_STYLUS_MODE, true) private inline fun logDebug(message: () -> String) { if (Build.IS_DEBUGGABLE) { Log.d(NoteTaskController.TAG, message()) } }
packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEnabledKey.kt +1 −1 Original line number Diff line number Diff line Loading @@ -19,4 +19,4 @@ package com.android.systemui.notetask import javax.inject.Qualifier /** Key associated with a [Boolean] flag that enables or disables the note task feature. */ @Qualifier internal annotation class NoteTaskEnabledKey @Qualifier annotation class NoteTaskEnabledKey
packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEntryPoint.kt 0 → 100644 +41 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.notetask import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity import com.android.systemui.screenshot.AppClipsTrampolineActivity /** * Supported entry points for [NoteTaskController.showNoteTask]. * * An entry point represents where the note task has ben called from. In rare cases, it may * represent a "re-entry" (i.e., [APP_CLIPS]). */ enum class NoteTaskEntryPoint { /** @see [LaunchNoteTaskActivity] */ WIDGET_PICKER_SHORTCUT, /** @see [NoteTaskQuickAffordanceConfig] */ QUICK_AFFORDANCE, /** @see [NoteTaskInitializer.callbacks] */ TAIL_BUTTON, /** @see [AppClipsTrampolineActivity] */ APP_CLIPS, }
packages/SystemUI/src/com/android/systemui/notetask/NoteTaskEventLogger.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.notetask import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import com.android.systemui.notetask.NoteTaskEntryPoint.APP_CLIPS import com.android.systemui.notetask.NoteTaskEntryPoint.QUICK_AFFORDANCE import com.android.systemui.notetask.NoteTaskEntryPoint.TAIL_BUTTON import com.android.systemui.notetask.NoteTaskEntryPoint.WIDGET_PICKER_SHORTCUT import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_SHORTCUT import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON import com.android.systemui.notetask.NoteTaskEventLogger.NoteTaskUiEvent.NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED import javax.inject.Inject /** * A wrapper around [UiEventLogger] specialized in the note taking UI events. * * if the accepted [NoteTaskInfo] contains a [NoteTaskInfo.entryPoint], it will be logged as the * correct [NoteTaskUiEvent]. If null, it will be ignored. * * @see NoteTaskController for usage examples. */ class NoteTaskEventLogger @Inject constructor(private val uiEventLogger: UiEventLogger) { /** Logs a [NoteTaskInfo] as an **open** [NoteTaskUiEvent], including package name and uid. */ fun logNoteTaskOpened(info: NoteTaskInfo) { val event = when (info.entryPoint) { TAIL_BUTTON -> { if (info.isKeyguardLocked) { NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED } else { NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON } } WIDGET_PICKER_SHORTCUT -> NOTE_OPENED_VIA_SHORTCUT QUICK_AFFORDANCE -> NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE APP_CLIPS -> return null -> return } uiEventLogger.log(event, info.uid, info.packageName) } /** Logs a [NoteTaskInfo] as a **closed** [NoteTaskUiEvent], including package name and uid. */ fun logNoteTaskClosed(info: NoteTaskInfo) { val event = when (info.entryPoint) { TAIL_BUTTON -> { if (info.isKeyguardLocked) { NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED } else { NoteTaskUiEvent.NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON } } WIDGET_PICKER_SHORTCUT -> return QUICK_AFFORDANCE -> return APP_CLIPS -> return null -> return } uiEventLogger.log(event, info.uid, info.packageName) } /** IDs of UI events accepted by [NoteTaskController]. */ enum class NoteTaskUiEvent(private val _id: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "User opened a note by tapping on the lockscreen shortcut.") NOTE_OPENED_VIA_KEYGUARD_QUICK_AFFORDANCE(1294), @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was unlocked.") // ktlint-disable max-line-length NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON(1295), @UiEvent(doc = "User opened a note by pressing the stylus tail button while the screen was locked.") // ktlint-disable max-line-length NOTE_OPENED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1296), @UiEvent(doc = "User opened a note by tapping on an app shortcut.") NOTE_OPENED_VIA_SHORTCUT(1297), @UiEvent(doc = "Note closed via a tail button while device is unlocked") NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON(1311), @UiEvent(doc = "Note closed via a tail button while device is locked") NOTE_CLOSED_VIA_STYLUS_TAIL_BUTTON_LOCKED(1312); override fun getId() = _id } }
packages/SystemUI/src/com/android/systemui/notetask/NoteTaskInfo.kt 0 → 100644 +33 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.notetask /** Contextual information required to launch a Note Task by [NoteTaskController]. */ data class NoteTaskInfo( val packageName: String, val uid: Int, val entryPoint: NoteTaskEntryPoint? = null, val isInMultiWindowMode: Boolean = false, val isKeyguardLocked: Boolean = false, ) { val launchMode: NoteTaskLaunchMode = if (isInMultiWindowMode || isKeyguardLocked) { NoteTaskLaunchMode.Activity } else { NoteTaskLaunchMode.AppBubble } }