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

Commit 60cf8199 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[SB][RON] Add demo commands for showing example RON chips.

This CL:
1) Adds a new `DemoRonCommand` that lets users show a RON chip for a
   specific package using adb.
2) Hooks up those demo adb commands to the rest of the chip
   architecture.

Bug: 361346412
Flag: com.android.systemui.status_bar_ron_chips
Test: `adb shell cmd statusbar demo-ron -p com.android.systemui` ->
verify status bar chip shows with SysUI icon
Test: verify call chips and screen share chips still work as expected
Test: atest DemoRonChipViewModelTest OngoingActivityChipsViewModelTest

Change-Id: I0f391d1d557edc78057a999e6b3b6d07ca463b49
parent ed48a531
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -390,6 +390,13 @@ flag {
    }
    }
}
}


flag {
    name: "status_bar_ron_chips"
    namespace: "systemui"
    description: "Show rich ongoing notifications as chips in the status bar"
    bug: "361346412"
}

flag {
flag {
    name: "compose_bouncer"
    name: "compose_bouncer"
    namespace: "systemui"
    namespace: "systemui"
+10 −0
Original line number Original line Diff line number Diff line
@@ -16,14 +16,24 @@


package com.android.systemui.statusbar.chips
package com.android.systemui.statusbar.chips


import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.statusbar.chips.ron.demo.ui.viewmodel.DemoRonChipViewModel
import dagger.Binds
import dagger.Module
import dagger.Module
import dagger.Provides
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap


@Module
@Module
abstract class StatusBarChipsModule {
abstract class StatusBarChipsModule {
    @Binds
    @IntoMap
    @ClassKey(DemoRonChipViewModel::class)
    abstract fun binds(impl: DemoRonChipViewModel): CoreStartable

    companion object {
    companion object {
        @Provides
        @Provides
        @SysUISingleton
        @SysUISingleton
+1 −1
Original line number Original line Diff line number Diff line
@@ -69,7 +69,7 @@ constructor(
                                    state.notificationIconView
                                    state.notificationIconView
                                )
                                )
                            } else {
                            } else {
                                OngoingActivityChipModel.ChipIcon.Basic(phoneIcon)
                                OngoingActivityChipModel.ChipIcon.SingleColorIcon(phoneIcon)
                            }
                            }


                        // This block mimics OngoingCallController#updateChip.
                        // This block mimics OngoingCallController#updateChip.
+2 −2
Original line number Original line Diff line number Diff line
@@ -190,7 +190,7 @@ constructor(
    ): OngoingActivityChipModel.Shown {
    ): OngoingActivityChipModel.Shown {
        return OngoingActivityChipModel.Shown.Timer(
        return OngoingActivityChipModel.Shown.Timer(
            icon =
            icon =
                OngoingActivityChipModel.ChipIcon.Basic(
                OngoingActivityChipModel.ChipIcon.SingleColorIcon(
                    Icon.Resource(
                    Icon.Resource(
                        CAST_TO_OTHER_DEVICE_ICON,
                        CAST_TO_OTHER_DEVICE_ICON,
                        // This string is "Casting screen"
                        // This string is "Casting screen"
@@ -215,7 +215,7 @@ constructor(
    private fun createIconOnlyCastChip(deviceName: String?): OngoingActivityChipModel.Shown {
    private fun createIconOnlyCastChip(deviceName: String?): OngoingActivityChipModel.Shown {
        return OngoingActivityChipModel.Shown.IconOnly(
        return OngoingActivityChipModel.Shown.IconOnly(
            icon =
            icon =
                OngoingActivityChipModel.ChipIcon.Basic(
                OngoingActivityChipModel.ChipIcon.SingleColorIcon(
                    Icon.Resource(
                    Icon.Resource(
                        CAST_TO_OTHER_DEVICE_ICON,
                        CAST_TO_OTHER_DEVICE_ICON,
                        // This string is just "Casting"
                        // This string is just "Casting"
+125 −0
Original line number Original line 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.statusbar.chips.ron.demo.ui.viewmodel

import android.content.pm.PackageManager
import android.content.pm.PackageManager.NameNotFoundException
import android.graphics.drawable.Drawable
import com.android.systemui.CoreStartable
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.chips.ron.shared.StatusBarRonChips
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipViewModel
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.commandline.ParseableCommand
import com.android.systemui.statusbar.commandline.Type
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

/**
 * A view model that will emit demo RON chips (rich ongoing notification chips) from [chip] based on
 * adb commands sent by the user.
 *
 * Example adb commands:
 * - To show a chip with the SysUI icon: adb shell cmd statusbar demo-ron -p com.android.systemui
 * - To hide the chip: adb shell cmd statusbar demo-ron --hide
 *
 * See [DemoRonCommand] for more information on the adb command spec.
 */
@SysUISingleton
class DemoRonChipViewModel
@Inject
constructor(
    private val commandRegistry: CommandRegistry,
    private val packageManager: PackageManager,
    private val systemClock: SystemClock,
) : OngoingActivityChipViewModel, CoreStartable {
    override fun start() {
        commandRegistry.registerCommand("demo-ron") { DemoRonCommand() }
    }

    private val _chip =
        MutableStateFlow<OngoingActivityChipModel>(OngoingActivityChipModel.Hidden())
    override val chip: StateFlow<OngoingActivityChipModel> = _chip.asStateFlow()

    private inner class DemoRonCommand : ParseableCommand("demo-ron") {
        private val packageName: String? by
            param(
                longName = "packageName",
                shortName = "p",
                description = "The package name for the demo RON app",
                valueParser = Type.String,
            )

        private val hide by
            flag(
                longName = "hide",
                description = "Hides any existing demo RON chip",
            )

        override fun execute(pw: PrintWriter) {
            if (!StatusBarRonChips.isEnabled) {
                pw.println(
                    "Error: com.android.systemui.status_bar_ron_chips must be enabled " +
                        "before using this demo feature"
                )
                return
            }

            if (hide) {
                _chip.value = OngoingActivityChipModel.Hidden()
                return
            }

            val currentPackageName = packageName
            if (currentPackageName == null) {
                pw.println("--packageName (or -p) must be included")
                return
            }

            lateinit var iconDrawable: Drawable
            try {
                // Note: For the real implementation, we should check if applicationInfo exists
                // before fetching the icon, so that we either don't show the chip or show a good
                // backup icon in case the app info can't be found for some reason.
                iconDrawable = packageManager.getApplicationIcon(currentPackageName)
            } catch (e: NameNotFoundException) {
                pw.println("Package $currentPackageName could not be found")
                return
            }

            _chip.value =
                // TODO(b/361346412): Include a demo for text like "10min".
                OngoingActivityChipModel.Shown.Timer(
                    icon =
                        OngoingActivityChipModel.ChipIcon.FullColorAppIcon(
                            Icon.Loaded(drawable = iconDrawable, contentDescription = null),
                        ),
                    // TODO(b/361346412): Include a demo with a custom color theme.
                    colors = ColorsModel.Themed,
                    startTimeMs = systemClock.elapsedRealtime(),
                    onClickListener = null,
                )
        }
    }
}
Loading