Skip to content

Commit 4a5febf

Browse files
authored
Merge pull request #470 from DevKor-github/codexd/442-audit-android-manifest-permissions
docs: audit Android manifest permissions
2 parents a3c8638 + d173240 commit 4a5febf

3 files changed

Lines changed: 119 additions & 0 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Android Manifest Permission Audit
2+
3+
This audit records the Android manifest permission review for release issue
4+
#442 under parent track #465.
5+
6+
## Source Manifests Reviewed
7+
8+
- `android/app/src/main/AndroidManifest.xml`
9+
- `android/app/src/debug/AndroidManifest.xml`
10+
- `android/app/src/profile/AndroidManifest.xml`
11+
12+
The main manifest is the app-owned release source of truth. Debug and profile
13+
manifests only add `android.permission.INTERNET` for Flutter tooling and hot
14+
reload.
15+
16+
## Release Permission Inventory
17+
18+
| Permission | Status | Justification |
19+
| --- | --- | --- |
20+
| `android.permission.POST_NOTIFICATIONS` | Keep | Required on Android 13+ for OnTime reminder, preparation-step, and alarm notifications. Native alarm fallback also checks this permission before posting the full-screen alarm notification. |
21+
| `android.permission.SCHEDULE_EXACT_ALARM` | Keep | Required on Android 12+ for user-scheduled schedule alarms that must fire at the selected time. Native alarm scheduling checks `AlarmManager.canScheduleExactAlarms()` before using `setAlarmClock`. |
22+
| `android.permission.USE_FULL_SCREEN_INTENT` | Keep | Required for the user-scheduled alarm ringing notification to present `AlarmRingingActivity` as a full-screen alarm experience. Usage is tied to alarm-category notifications, not generic or promotional notifications. |
23+
| `android.permission.RECEIVE_BOOT_COMPLETED` | Keep | Required for `NativeAlarmBootReceiver` to restore persisted future native alarms after device restart. The receiver is not exported. |
24+
| `android.permission.VIBRATE` | Keep | Required so alarm and notification channels can use vibration behavior for time-sensitive reminders and alarms. |
25+
26+
No unused app-owned release permission was found during the audit.
27+
28+
## Manifest Merge Notes
29+
30+
Release manifest merge was verified with:
31+
32+
```sh
33+
ANDROID_KEYSTORE_PATH=$HOME/.android/debug.keystore \
34+
ANDROID_KEYSTORE_PASSWORD=android \
35+
ANDROID_KEY_ALIAS=androiddebugkey \
36+
ANDROID_KEY_PASSWORD=android \
37+
gradle :app:processReleaseMainManifest -x :app:compileFlutterBuildRelease
38+
```
39+
40+
The command used ignored local placeholder release config only to allow manifest
41+
merge without production Firebase and signing secrets.
42+
43+
The merged release manifest contains the app-owned permissions above plus these
44+
dependency-owned permissions:
45+
46+
| Permission | Source | Justification |
47+
| --- | --- | --- |
48+
| `android.permission.INTERNET` | Google Sign-In, Firebase Messaging, AppAuth, and related network dependencies | Required for sign-in, Firebase initialization/messaging, and app network access. |
49+
| `android.permission.WAKE_LOCK` | `firebase_messaging` / Firebase Messaging | Required by Firebase Messaging background delivery while processing incoming messages. |
50+
| `android.permission.ACCESS_NETWORK_STATE` | Firebase Messaging / Firebase Installations / Google transport dependencies | Required by Firebase and transport dependencies to check network availability for messaging and token/installation work. |
51+
| `com.google.android.c2dm.permission.RECEIVE` | Firebase Messaging | Required for receiving FCM push messages. |
52+
| `android.permission.USE_BIOMETRIC` | AndroidX biometric via Google credential dependencies | Added by AndroidX credential/biometric dependencies used by Google sign-in support. |
53+
| `android.permission.USE_FINGERPRINT` | AndroidX biometric via Google credential dependencies | Legacy counterpart to `USE_BIOMETRIC` from the same dependency chain. |
54+
| `club.devkor.ontime.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION` | AndroidX core | Signature-level internal permission used by AndroidX for non-exported dynamic receiver protection. |
55+
56+
The merge did not add location, contacts, camera, microphone, phone, SMS,
57+
storage, calendar, nearby-device, or Bluetooth permissions.
58+
59+
Debug and profile merged manifests may additionally contain their variant-owned
60+
`android.permission.INTERNET` declaration for Flutter tooling.
61+
62+
## Related Android Components
63+
64+
- `MainActivity` checks exact alarm and notification permission state before
65+
scheduling native alarms.
66+
- `NativeAlarmReceiver` posts alarm-category full-screen notifications and
67+
skips posting when notification permission is denied.
68+
- `NativeAlarmBootReceiver` handles boot completion and exact-alarm permission
69+
state changes to restore persisted native alarms.
70+
- `AlarmRingingActivity` is the full-screen alarm UI launched only from the
71+
alarm notification path.

docs/Release-Checklist.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ OnTime.
3434
- Confirm the application ID is `club.devkor.ontime`.
3535
- Confirm the app label is `OnTime`.
3636
- Review launcher icons in `android/app/src/main/res/mipmap-*`.
37+
- Review `docs/Android-Manifest-Permissions.md` and confirm app-owned release
38+
manifest permissions are still limited to user-facing notification, exact
39+
alarm, full-screen alarm, boot restore, and vibration behavior.
3740
- Provide release signing through one of the following secret-free paths:
3841
- `android/key.properties` with `storeFile`, `storePassword`, `keyAlias`, and
3942
`keyPassword`.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Issue 442 Android Manifest Permission Audit Plan
2+
3+
## Scope
4+
5+
Audit Android manifest permissions for release readiness under parent track #465.
6+
This issue covers only manifest permission inventory, permission justification,
7+
and merged-manifest verification for Android.
8+
9+
## Files Likely Touched
10+
11+
- `docs/Android-Manifest-Permissions.md`
12+
- `docs/Release-Checklist.md`
13+
14+
No Android manifest permission removal is planned unless the audit finds an
15+
unused release permission.
16+
17+
## Implementation Approach
18+
19+
1. Review `android/app/src/main/AndroidManifest.xml` for release permissions.
20+
2. Review `android/app/src/debug/AndroidManifest.xml` and
21+
`android/app/src/profile/AndroidManifest.xml` for variant-only permissions.
22+
3. Trace each release permission to current native or Flutter behavior.
23+
4. Document the release permission inventory and justification.
24+
5. Link the audit from the release checklist.
25+
6. Run manifest-merge verification and confirm no unexpected sensitive
26+
permission is introduced by plugins or manifest merge.
27+
28+
## Verification
29+
30+
- `flutter pub get`
31+
- Android merged manifest task, then inspect merged permissions.
32+
- `git diff --check`
33+
34+
## Blockers
35+
36+
None for this issue. A full signed release build may require Firebase and
37+
signing secrets, but manifest merge can be verified without changing release
38+
behavior.
39+
40+
## Explicitly Left Out
41+
42+
- Notification permission UX changes for #443.
43+
- Exact alarm permission UX changes for #444.
44+
- Play Console full-screen intent declaration submission for #445.
45+
- Device alarm and notification QA for #457.

0 commit comments

Comments
 (0)