feat(bedtime): add an opt-in bedtime mode under Settings

Clockula can now turn on a Do Not Disturb mode of its own at bedtime and
off at the wake-up time, on the nights the user picks, with an optional
reminder before it starts. Digital Wellbeing's Bedtime mode can't be
driven by a third-party app, so this is a separate rule: a typed mode
with grayscale, dimmed wallpaper, dark theme and hidden always-on display
on Android 15+, and a plain DND schedule rule on Android 10-14.

The rule's policy always allows alarms (and media). BedtimeEngine owns one
AlarmManager slot of its own, on its own receiver and request code, and
every bedtime call on the boot, time-change and launch paths runs after
the alarm and timer passes, guarded. The rule id is never stored: the
platform lists an app's own rules, so restores and reinstalls find or
recreate it. Turning bedtime off removes the rule. The screen walks the
user through granting DND access and explains the Wellbeing overlap.
Settings are part of the JSON backup; older files restore bedtime as off.

Refs #1
This commit is contained in:
makiolaj committed 2026-10-22 11:19:38 +02:00
1 parent 3f431a7f32
commit 69b436cffd
46 files changed
+2132 -16

No files matched your search

+17
View File
@@ -50,6 +50,12 @@
<!-- The alarm vibrates, and vibrates on its own when no audio source opens. -->
<uses-permission android:name="android.permission.VIBRATE" />
<!-- The opt-in bedtime mode (issue #1): lists Clockula under Settings ›
Special app access › Do Not Disturb, where the user grants it by hand.
Without that grant nothing changes; with it, Clockula adds one Do Not
Disturb rule of its own, which always lets alarms through. -->
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
<!-- "Choose from a music app…": package visibility for the apps that share
a library through Android's standard MediaBrowserService, and for
nothing else. A visibility declaration, not a permission — and no
@@ -273,6 +279,17 @@
</intent-filter>
</receiver>
<!-- The bedtime slot arriving, and Do Not Disturb access changing. The
second is a system broadcast addressed to this package, so the
receiver stays unexported (issue #1). -->
<receiver
android:name=".bedtime.receiver.BedtimeReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED" />
</intent-filter>
</receiver>
<!-- Persists the per-app language on API < 33, where the platform
per-app-languages API is unavailable. On 33+ this is a no-op. -->
<service