|
| 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. |
0 commit comments