1 /*
<lambda>null2  * Copyright (C) 2024 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.inputdevice.tutorial.ui.view
18 
19 import android.os.Bundle
20 import android.view.WindowManager
21 import androidx.activity.ComponentActivity
22 import androidx.activity.compose.setContent
23 import androidx.activity.enableEdgeToEdge
24 import androidx.activity.viewModels
25 import androidx.compose.runtime.Composable
26 import androidx.compose.runtime.getValue
27 import androidx.lifecycle.Lifecycle.State.STARTED
28 import androidx.lifecycle.compose.collectAsStateWithLifecycle
29 import androidx.lifecycle.lifecycleScope
30 import com.android.app.tracing.coroutines.launchTraced as launch
31 import com.android.compose.theme.PlatformTheme
32 import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger
33 import com.android.systemui.inputdevice.tutorial.InputDeviceTutorialLogger.TutorialContext
34 import com.android.systemui.inputdevice.tutorial.KeyboardTouchpadTutorialMetricsLogger
35 import com.android.systemui.inputdevice.tutorial.TouchpadTutorialScreensProvider
36 import com.android.systemui.inputdevice.tutorial.ui.composable.ActionKeyTutorialScreen
37 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel
38 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.KeyboardTouchpadTutorialViewModel.Factory.ViewModelFactoryAssistedProvider
39 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.ACTION_KEY
40 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.BACK_GESTURE
41 import com.android.systemui.inputdevice.tutorial.ui.viewmodel.Screen.HOME_GESTURE
42 import java.util.Optional
43 import javax.inject.Inject
44 
45 /**
46  * Activity for out of the box experience for keyboard and touchpad. Note that it's possible that
47  * either of them are actually not connected when this is launched
48  */
49 class KeyboardTouchpadTutorialActivity
50 @Inject
51 constructor(
52     private val viewModelFactoryAssistedProvider: ViewModelFactoryAssistedProvider,
53     private val touchpadTutorialScreensProvider: Optional<TouchpadTutorialScreensProvider>,
54     private val logger: InputDeviceTutorialLogger,
55     private val metricsLogger: KeyboardTouchpadTutorialMetricsLogger,
56 ) : ComponentActivity() {
57 
58     companion object {
59         const val INTENT_TUTORIAL_SCOPE_KEY = "tutorial_scope"
60         const val INTENT_TUTORIAL_SCOPE_TOUCHPAD = "touchpad"
61         const val INTENT_TUTORIAL_SCOPE_TOUCHPAD_BACK = "touchpad_back"
62         const val INTENT_TUTORIAL_SCOPE_TOUCHPAD_HOME = "touchpad_home"
63         const val INTENT_TUTORIAL_SCOPE_KEYBOARD = "keyboard"
64         const val INTENT_TUTORIAL_SCOPE_ALL = "all"
65 
66         const val INTENT_TUTORIAL_ENTRY_POINT_KEY = "entry_point"
67         const val INTENT_TUTORIAL_ENTRY_POINT_SCHEDULER = "scheduler"
68         const val INTENT_TUTORIAL_ENTRY_POINT_CONTEXTUAL_EDU = "contextual_edu"
69     }
70 
71     private val vm by
72         viewModels<KeyboardTouchpadTutorialViewModel>(
73             factoryProducer = {
74                 viewModelFactoryAssistedProvider.create(touchpadTutorialScreensProvider.isPresent)
75             }
76         )
77 
78     override fun onCreate(savedInstanceState: Bundle?) {
79         super.onCreate(savedInstanceState)
80         enableEdgeToEdge()
81         // required to handle 3+ fingers on touchpad
82         window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
83         window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS)
84         lifecycle.addObserver(vm)
85         lifecycleScope.launch {
86             vm.closeActivity.collect { finish ->
87                 if (finish) {
88                     logger.logCloseTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL)
89                     finish()
90                 }
91             }
92         }
93         setContent {
94             PlatformTheme { KeyboardTouchpadTutorialContainer(vm, touchpadTutorialScreensProvider) }
95         }
96         // TODO(b/376692701): Update launchTime when the activity is launched by Companion App
97         if (savedInstanceState == null) {
98             metricsLogger.logPeripheralTutorialLaunched(
99                 intent.getStringExtra(INTENT_TUTORIAL_ENTRY_POINT_KEY),
100                 intent.getStringExtra(INTENT_TUTORIAL_SCOPE_KEY),
101             )
102             logger.logOpenTutorial(TutorialContext.KEYBOARD_TOUCHPAD_TUTORIAL)
103         }
104     }
105 }
106 
107 @Composable
KeyboardTouchpadTutorialContainernull108 fun KeyboardTouchpadTutorialContainer(
109     vm: KeyboardTouchpadTutorialViewModel,
110     touchpadScreens: Optional<TouchpadTutorialScreensProvider>,
111 ) {
112     val activeScreen by vm.screen.collectAsStateWithLifecycle(STARTED)
113     when (activeScreen) {
114         BACK_GESTURE ->
115             touchpadScreens
116                 .get()
117                 .BackGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack)
118         HOME_GESTURE ->
119             touchpadScreens
120                 .get()
121                 .HomeGesture(onDoneButtonClicked = vm::onDoneButtonClicked, onBack = vm::onBack)
122         ACTION_KEY ->
123             ActionKeyTutorialScreen(
124                 onDoneButtonClicked = vm::onDoneButtonClicked,
125                 onBack = vm::onBack,
126             )
127     }
128 }
129