xref: /aosp_15_r20/frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)

<lambda>null1 package com.android.systemui.qs.tiles
2 
3 import android.app.AlarmManager
4 import android.app.AlarmManager.AlarmClockInfo
5 import android.content.Intent
6 import android.os.Handler
7 import android.os.Looper
8 import android.provider.AlarmClock
9 import android.service.quicksettings.Tile
10 import android.text.TextUtils
11 import android.text.format.DateFormat
12 import android.widget.Button
13 import androidx.annotation.VisibleForTesting
14 import com.android.internal.jank.InteractionJankMonitor
15 import com.android.internal.logging.MetricsLogger
16 import com.android.systemui.animation.Expandable
17 import com.android.systemui.dagger.qualifiers.Background
18 import com.android.systemui.dagger.qualifiers.Main
19 import com.android.systemui.plugins.ActivityStarter
20 import com.android.systemui.plugins.FalsingManager
21 import com.android.systemui.plugins.qs.QSTile
22 import com.android.systemui.plugins.statusbar.StatusBarStateController
23 import com.android.systemui.qs.QSHost
24 import com.android.systemui.qs.QsEventLogger
25 import com.android.systemui.qs.logging.QSLogger
26 import com.android.systemui.qs.tileimpl.QSTileImpl
27 import com.android.systemui.res.R
28 import com.android.systemui.settings.UserTracker
29 import com.android.systemui.statusbar.policy.NextAlarmController
30 import java.util.Locale
31 import javax.inject.Inject
32 
33 class AlarmTile
34 @Inject
35 constructor(
36     host: QSHost,
37     uiEventLogger: QsEventLogger,
38     @Background backgroundLooper: Looper,
39     @Main mainHandler: Handler,
40     falsingManager: FalsingManager,
41     metricsLogger: MetricsLogger,
42     statusBarStateController: StatusBarStateController,
43     activityStarter: ActivityStarter,
44     qsLogger: QSLogger,
45     private val userTracker: UserTracker,
46     nextAlarmController: NextAlarmController,
47 ) :
48     QSTileImpl<QSTile.State>(
49         host,
50         uiEventLogger,
51         backgroundLooper,
52         mainHandler,
53         falsingManager,
54         metricsLogger,
55         statusBarStateController,
56         activityStarter,
57         qsLogger,
58     ) {
59 
60     private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null
61     private var icon: QSTile.Icon? = null
62     @VisibleForTesting internal val defaultIntent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
63     private val callback =
64         NextAlarmController.NextAlarmChangeCallback { nextAlarm ->
65             lastAlarmInfo = nextAlarm
66             refreshState()
67         }
68 
69     init {
70         nextAlarmController.observe(this, callback)
71     }
72 
73     override fun newTileState(): QSTile.State {
74         return QSTile.State().apply {
75             handlesLongClick = false
76             expandedAccessibilityClassName = Button::class.java.name
77         }
78     }
79 
80     override fun handleClick(expandable: Expandable?) {
81         val animationController =
82             expandable?.activityTransitionController(
83                 InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE
84             )
85         val pendingIntent = lastAlarmInfo?.showIntent
86         if (pendingIntent != null) {
87             mActivityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController)
88         } else {
89             mActivityStarter.postStartActivityDismissingKeyguard(
90                 defaultIntent,
91                 0,
92                 animationController,
93             )
94         }
95     }
96 
97     override fun handleUpdateState(state: QSTile.State, arg: Any?) {
98         if (icon == null) {
99             icon = maybeLoadResourceIcon(R.drawable.ic_alarm)
100         }
101         state.icon = icon
102         state.label = tileLabel
103         lastAlarmInfo?.let {
104             state.secondaryLabel = formatNextAlarm(it)
105             state.state = Tile.STATE_ACTIVE
106         }
107             ?: run {
108                 state.secondaryLabel = mContext.getString(R.string.qs_alarm_tile_no_alarm)
109                 state.state = Tile.STATE_INACTIVE
110             }
111         state.contentDescription = TextUtils.concat(state.label, ", ", state.secondaryLabel)
112     }
113 
114     override fun getTileLabel(): CharSequence {
115         return mContext.getString(R.string.status_bar_alarm)
116     }
117 
118     private fun formatNextAlarm(info: AlarmClockInfo): String {
119         val skeleton = if (use24HourFormat()) "EHm" else "Ehma"
120         val pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton)
121         return DateFormat.format(pattern, info.triggerTime).toString()
122     }
123 
124     private fun use24HourFormat(): Boolean {
125         return DateFormat.is24HourFormat(mContext, userTracker.userId)
126     }
127 
128     override fun getMetricsCategory(): Int {
129         return 0
130     }
131 
132     override fun getLongClickIntent(): Intent? {
133         return null
134     }
135 
136     companion object {
137         const val TILE_SPEC = "alarm"
138     }
139 }
140