Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d6d6f5d authored by yyalan's avatar yyalan
Browse files

Schedule OOBE and handle disconnection

Bug: 344862874
Flag: com.android.systemui.shared.new_touchpad_gestures_tutorial
Test: manual
Change-Id: I20a646166b9542ec2023f75a2860be2dae39859c
parent fec792dd
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package com.android.systemui.inputdevice.oobe

import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.inputdevice.oobe.domain.interactor.OobeTutorialSchedulerInteractor
import com.android.systemui.inputdevice.oobe.domain.interactor.OobeSchedulerInteractor
import com.android.systemui.shared.Flags.newTouchpadGesturesTutorial
import dagger.Lazy
import javax.inject.Inject
@@ -27,11 +27,10 @@ import javax.inject.Inject
@SysUISingleton
class KeyboardTouchpadOobeTutorialCoreStartable
@Inject
constructor(private val oobeTutorialSchedulerInteractor: Lazy<OobeTutorialSchedulerInteractor>) :
    CoreStartable {
constructor(private val oobeSchedulerInteractor: Lazy<OobeSchedulerInteractor>) : CoreStartable {
    override fun start() {
        if (newTouchpadGesturesTutorial()) {
            oobeTutorialSchedulerInteractor.get().start()
            oobeSchedulerInteractor.get().start()
        }
    }
}
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.inputdevice.oobe.data.model

data class OobeSchedulerInfo(
    val keyboard: DeviceSchedulerInfo = DeviceSchedulerInfo(),
    val touchpad: DeviceSchedulerInfo = DeviceSchedulerInfo()
)

data class DeviceSchedulerInfo(var isLaunched: Boolean = false, var connectionTime: Long? = null) {
    val wasEverConnected: Boolean
        get() = connectionTime != null
}
+97 −0
Original line number Diff line number Diff line
@@ -20,39 +20,78 @@ import android.content.Context
import android.content.Intent
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.inputdevice.oobe.data.model.DeviceSchedulerInfo
import com.android.systemui.inputdevice.oobe.data.model.OobeSchedulerInfo
import com.android.systemui.keyboard.data.repository.KeyboardRepository
import com.android.systemui.touchpad.data.repository.TouchpadRepository
import java.time.Duration
import java.time.Instant
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch

/** When keyboards or touchpads are connected, schedule a tutorial after given time has elapsed */
/**
 * When the first time a keyboard or touchpad id connected, wait for [LAUNCH_DELAY], then launch the
 * tutorial as soon as there's a connected device
 */
@SysUISingleton
class OobeTutorialSchedulerInteractor
class OobeSchedulerInteractor
@Inject
constructor(
    @Application private val context: Context,
    @Application private val applicationScope: CoroutineScope,
    keyboardRepository: KeyboardRepository,
    touchpadRepository: TouchpadRepository
    private val keyboardRepository: KeyboardRepository,
    private val touchpadRepository: TouchpadRepository
) {
    private val isAnyKeyboardConnected = keyboardRepository.isAnyKeyboardConnected
    private val isAnyTouchpadConnected = touchpadRepository.isAnyTouchpadConnected
    private val info = OobeSchedulerInfo()

    fun start() {
        applicationScope.launch { isAnyKeyboardConnected.collect { startOobe() } }
        applicationScope.launch { isAnyTouchpadConnected.collect { startOobe() } }
        if (!info.keyboard.isLaunched) {
            applicationScope.launch {
                schedule(keyboardRepository.isAnyKeyboardConnected, info.keyboard)
            }
        }
        if (!info.touchpad.isLaunched) {
            applicationScope.launch {
                schedule(touchpadRepository.isAnyTouchpadConnected, info.touchpad)
            }
        }
    }

    private suspend fun schedule(isAnyDeviceConnected: Flow<Boolean>, info: DeviceSchedulerInfo) {
        if (!info.wasEverConnected) {
            waitForDeviceConnection(isAnyDeviceConnected)
            info.connectionTime = Instant.now().toEpochMilli()
        }
        delay(remainingTimeMillis(info.connectionTime!!))
        waitForDeviceConnection(isAnyDeviceConnected)
        info.isLaunched = true
        launchOobe()
    }

    private suspend fun waitForDeviceConnection(isAnyDeviceConnected: Flow<Boolean>): Boolean {
        return isAnyDeviceConnected.filter { it }.first()
    }

    private fun startOobe() {
    private fun launchOobe() {
        val intent = Intent(TUTORIAL_ACTION)
        intent.addCategory(Intent.CATEGORY_DEFAULT)
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    }

    private fun remainingTimeMillis(start: Long): Long {
        val elapsed = Instant.now().toEpochMilli() - start
        return LAUNCH_DELAY - elapsed
    }

    companion object {
        const val TAG = "OobeSchedulerInteractor"
        const val TUTORIAL_ACTION = "com.android.systemui.action.TOUCHPAD_TUTORIAL"
        private val LAUNCH_DELAY = Duration.ofHours(72).toMillis()
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.touchpad

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.touchpad.data.repository.TouchpadRepository
import com.android.systemui.touchpad.data.repository.TouchpadRepositoryImpl
import dagger.Binds
@@ -25,5 +26,6 @@ import dagger.Module
abstract class TouchpadModule {

    @Binds
    @SysUISingleton
    abstract fun bindTouchpadRepository(repository: TouchpadRepositoryImpl): TouchpadRepository
}