Loading packages/SystemUI/res/values/config.xml +1 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,7 @@ <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> <string name="quick_settings_tiles_stock" translatable="false"> wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle,controls wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle,controls,alarm </string> <!-- The tiles to display in QuickSettings --> Loading packages/SystemUI/res/values/flags.xml +2 −0 Original line number Diff line number Diff line Loading @@ -46,4 +46,6 @@ <bool name="flag_navigation_bar_overlay">false</bool> <bool name="flag_pm_lite">false</bool> <bool name="flag_alarm_tile">false</bool> </resources> packages/SystemUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2861,4 +2861,7 @@ <string name="qs_remove_labels" translatable="false"></string> <string name="qs_tile_label_fontFamily" translatable="false">@*android:string/config_headlineFontFamily</string> <!-- Secondary label for alarm tile when there is no next alarm information [CHAR LIMIT=20] --> <string name="qs_alarm_tile_no_alarm">No alarm set</string> </resources> packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +7 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.plugins.qs.QSTileView; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.tiles.AirplaneModeTile; import com.android.systemui.qs.tiles.AlarmTile; import com.android.systemui.qs.tiles.BatterySaverTile; import com.android.systemui.qs.tiles.BluetoothTile; import com.android.systemui.qs.tiles.CameraToggleTile; Loading Loading @@ -91,6 +92,7 @@ public class QSFactoryImpl implements QSFactory { private final Provider<CameraToggleTile> mCameraToggleTileProvider; private final Provider<MicrophoneToggleTile> mMicrophoneToggleTileProvider; private final Provider<DeviceControlsTile> mDeviceControlsTileProvider; private final Provider<AlarmTile> mAlarmTileProvider; private final Lazy<QSHost> mQsHostLazy; private final Provider<CustomTile.Builder> mCustomTileBuilderProvider; Loading Loading @@ -126,7 +128,8 @@ public class QSFactoryImpl implements QSFactory { Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider, Provider<CameraToggleTile> cameraToggleTileProvider, Provider<MicrophoneToggleTile> microphoneToggleTileProvider, Provider<DeviceControlsTile> deviceControlsTileProvider) { Provider<DeviceControlsTile> deviceControlsTileProvider, Provider<AlarmTile> alarmTileProvider) { mQsHostLazy = qsHostLazy; mCustomTileBuilderProvider = customTileBuilderProvider; Loading Loading @@ -157,6 +160,7 @@ public class QSFactoryImpl implements QSFactory { mCameraToggleTileProvider = cameraToggleTileProvider; mMicrophoneToggleTileProvider = microphoneToggleTileProvider; mDeviceControlsTileProvider = deviceControlsTileProvider; mAlarmTileProvider = alarmTileProvider; } public QSTile createTile(String tileSpec) { Loading Loading @@ -218,6 +222,8 @@ public class QSFactoryImpl implements QSFactory { return mMicrophoneToggleTileProvider.get(); case "controls": return mDeviceControlsTileProvider.get(); case "alarm": return mAlarmTileProvider.get(); } // Custom tiles Loading packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt 0 → 100644 +117 −0 Original line number Diff line number Diff line package com.android.systemui.qs.tiles import android.app.AlarmManager import android.app.AlarmManager.AlarmClockInfo import android.content.Intent import android.os.Handler import android.os.Looper import android.provider.AlarmClock import android.service.quicksettings.Tile import android.text.TextUtils import android.text.format.DateFormat import androidx.annotation.VisibleForTesting import com.android.internal.logging.MetricsLogger import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.policy.NextAlarmController import java.util.Locale import javax.inject.Inject class AlarmTile @Inject constructor( host: QSHost, @Background backgroundLooper: Looper, @Main mainHandler: Handler, metricsLogger: MetricsLogger, statusBarStateController: StatusBarStateController, activityStarter: ActivityStarter, qsLogger: QSLogger, private val featureFlags: FeatureFlags, private val userTracker: UserTracker, nextAlarmController: NextAlarmController ) : QSTileImpl<QSTile.State>( host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, activityStarter, qsLogger ) { private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null private val icon = ResourceIcon.get(R.drawable.ic_alarm) @VisibleForTesting internal val defaultIntent = Intent(AlarmClock.ACTION_SET_ALARM) private val callback = NextAlarmController.NextAlarmChangeCallback { nextAlarm -> lastAlarmInfo = nextAlarm refreshState() } init { nextAlarmController.observe(this, callback) } override fun isAvailable(): Boolean { return featureFlags.isAlarmTileAvailable } override fun newTileState(): QSTile.State { return QSTile.State().apply { handlesLongClick = false } } private fun startDefaultSetAlarm() { mActivityStarter.postStartActivityDismissingKeyguard(defaultIntent, 0) } override fun handleClick() { lastAlarmInfo?.showIntent?.let { mActivityStarter.postStartActivityDismissingKeyguard(it) } ?: startDefaultSetAlarm() } override fun handleUpdateState(state: QSTile.State, arg: Any?) { state.icon = icon state.label = tileLabel lastAlarmInfo?.let { state.secondaryLabel = formatNextAlarm(it) state.state = Tile.STATE_ACTIVE } ?: run { state.secondaryLabel = mContext.getString(R.string.qs_alarm_tile_no_alarm) state.state = Tile.STATE_INACTIVE } state.contentDescription = TextUtils.concat(state.label, ", ", state.secondaryLabel) } override fun getTileLabel(): CharSequence { return mContext.getString(R.string.status_bar_alarm) } private fun formatNextAlarm(info: AlarmClockInfo): String { val skeleton = if (use24HourFormat()) "EHm" else "Ehma" val pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton) return DateFormat.format(pattern, info.triggerTime).toString() } private fun use24HourFormat(): Boolean { return DateFormat.is24HourFormat(mContext, userTracker.userId) } override fun getMetricsCategory(): Int { return 0 } override fun getLongClickIntent(): Intent? { return null } } No newline at end of file Loading
packages/SystemUI/res/values/config.xml +1 −1 Original line number Diff line number Diff line Loading @@ -107,7 +107,7 @@ <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> <string name="quick_settings_tiles_stock" translatable="false"> wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle,controls wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,dark,work,cast,night,screenrecord,reverse,reduce_brightness,cameratoggle,mictoggle,controls,alarm </string> <!-- The tiles to display in QuickSettings --> Loading
packages/SystemUI/res/values/flags.xml +2 −0 Original line number Diff line number Diff line Loading @@ -46,4 +46,6 @@ <bool name="flag_navigation_bar_overlay">false</bool> <bool name="flag_pm_lite">false</bool> <bool name="flag_alarm_tile">false</bool> </resources>
packages/SystemUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2861,4 +2861,7 @@ <string name="qs_remove_labels" translatable="false"></string> <string name="qs_tile_label_fontFamily" translatable="false">@*android:string/config_headlineFontFamily</string> <!-- Secondary label for alarm tile when there is no next alarm information [CHAR LIMIT=20] --> <string name="qs_alarm_tile_no_alarm">No alarm set</string> </resources>
packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java +7 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.plugins.qs.QSTileView; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.external.CustomTile; import com.android.systemui.qs.tiles.AirplaneModeTile; import com.android.systemui.qs.tiles.AlarmTile; import com.android.systemui.qs.tiles.BatterySaverTile; import com.android.systemui.qs.tiles.BluetoothTile; import com.android.systemui.qs.tiles.CameraToggleTile; Loading Loading @@ -91,6 +92,7 @@ public class QSFactoryImpl implements QSFactory { private final Provider<CameraToggleTile> mCameraToggleTileProvider; private final Provider<MicrophoneToggleTile> mMicrophoneToggleTileProvider; private final Provider<DeviceControlsTile> mDeviceControlsTileProvider; private final Provider<AlarmTile> mAlarmTileProvider; private final Lazy<QSHost> mQsHostLazy; private final Provider<CustomTile.Builder> mCustomTileBuilderProvider; Loading Loading @@ -126,7 +128,8 @@ public class QSFactoryImpl implements QSFactory { Provider<ReduceBrightColorsTile> reduceBrightColorsTileProvider, Provider<CameraToggleTile> cameraToggleTileProvider, Provider<MicrophoneToggleTile> microphoneToggleTileProvider, Provider<DeviceControlsTile> deviceControlsTileProvider) { Provider<DeviceControlsTile> deviceControlsTileProvider, Provider<AlarmTile> alarmTileProvider) { mQsHostLazy = qsHostLazy; mCustomTileBuilderProvider = customTileBuilderProvider; Loading Loading @@ -157,6 +160,7 @@ public class QSFactoryImpl implements QSFactory { mCameraToggleTileProvider = cameraToggleTileProvider; mMicrophoneToggleTileProvider = microphoneToggleTileProvider; mDeviceControlsTileProvider = deviceControlsTileProvider; mAlarmTileProvider = alarmTileProvider; } public QSTile createTile(String tileSpec) { Loading Loading @@ -218,6 +222,8 @@ public class QSFactoryImpl implements QSFactory { return mMicrophoneToggleTileProvider.get(); case "controls": return mDeviceControlsTileProvider.get(); case "alarm": return mAlarmTileProvider.get(); } // Custom tiles Loading
packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt 0 → 100644 +117 −0 Original line number Diff line number Diff line package com.android.systemui.qs.tiles import android.app.AlarmManager import android.app.AlarmManager.AlarmClockInfo import android.content.Intent import android.os.Handler import android.os.Looper import android.provider.AlarmClock import android.service.quicksettings.Tile import android.text.TextUtils import android.text.format.DateFormat import androidx.annotation.VisibleForTesting import com.android.internal.logging.MetricsLogger import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.FeatureFlags import com.android.systemui.statusbar.policy.NextAlarmController import java.util.Locale import javax.inject.Inject class AlarmTile @Inject constructor( host: QSHost, @Background backgroundLooper: Looper, @Main mainHandler: Handler, metricsLogger: MetricsLogger, statusBarStateController: StatusBarStateController, activityStarter: ActivityStarter, qsLogger: QSLogger, private val featureFlags: FeatureFlags, private val userTracker: UserTracker, nextAlarmController: NextAlarmController ) : QSTileImpl<QSTile.State>( host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController, activityStarter, qsLogger ) { private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null private val icon = ResourceIcon.get(R.drawable.ic_alarm) @VisibleForTesting internal val defaultIntent = Intent(AlarmClock.ACTION_SET_ALARM) private val callback = NextAlarmController.NextAlarmChangeCallback { nextAlarm -> lastAlarmInfo = nextAlarm refreshState() } init { nextAlarmController.observe(this, callback) } override fun isAvailable(): Boolean { return featureFlags.isAlarmTileAvailable } override fun newTileState(): QSTile.State { return QSTile.State().apply { handlesLongClick = false } } private fun startDefaultSetAlarm() { mActivityStarter.postStartActivityDismissingKeyguard(defaultIntent, 0) } override fun handleClick() { lastAlarmInfo?.showIntent?.let { mActivityStarter.postStartActivityDismissingKeyguard(it) } ?: startDefaultSetAlarm() } override fun handleUpdateState(state: QSTile.State, arg: Any?) { state.icon = icon state.label = tileLabel lastAlarmInfo?.let { state.secondaryLabel = formatNextAlarm(it) state.state = Tile.STATE_ACTIVE } ?: run { state.secondaryLabel = mContext.getString(R.string.qs_alarm_tile_no_alarm) state.state = Tile.STATE_INACTIVE } state.contentDescription = TextUtils.concat(state.label, ", ", state.secondaryLabel) } override fun getTileLabel(): CharSequence { return mContext.getString(R.string.status_bar_alarm) } private fun formatNextAlarm(info: AlarmClockInfo): String { val skeleton = if (use24HourFormat()) "EHm" else "Ehma" val pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton) return DateFormat.format(pattern, info.triggerTime).toString() } private fun use24HourFormat(): Boolean { return DateFormat.is24HourFormat(mContext, userTracker.userId) } override fun getMetricsCategory(): Int { return 0 } override fun getLongClickIntent(): Intent? { return null } } No newline at end of file