<?xml version="1.0" encoding="utf-8"?>
<!--
  Authoritative AndroidManifest for JellyTau.

  NOTE: this is NOT a manifest-merger fragment. Gradle only ever reads
  gen/android/app/src/main/AndroidManifest.xml, and `tauri android init`
  regenerates that file from tauri.conf.json - dropping everything below.
  scripts/sync-android-sources.sh copies this file over the generated one,
  so this is the full manifest and the single source of truth.

  (An earlier version of this file was a partial <application> fragment on the
  assumption that Tauri merged it. It did not: the hardwareAccelerated flag it
  declared never reached any built APK. It is folded in properly below.)

  ${appLabel} / ${activityLabel} are manifestPlaceholders set in
  app/build.gradle.kts: they resolve to @string/app_name and
  @string/main_activity_title for release, and to "JellyTau Debug" for the
  debug build type (which also carries applicationIdSuffix ".debug" so it
  installs alongside a release build).
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET" />
    <!-- Required to read NetworkCapabilities for the WiFi-only download gate (UR-053) -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
    <!--
      Declared, and deliberately NEVER requested at runtime. That is not an
      oversight, and an audit has flagged it once already — please read before
      "fixing" it in either direction.

      Nothing the app posts today needs it. The only notification it produces is
      the playback service's, which is a MediaStyle notification carrying a valid
      MediaSession token, and "Notifications related to media sessions are exempt
      from this behavior change". Verified on device (HONOR ROD2-W09, Android 16
      / SDK 36): appops `POST_NOTIFICATION: ignore`, granted=false, and the
      transport notification simultaneously live with all three actions and
      working lockscreen controls. So there is no permission dialog, because a
      prompt the app does not need is a prompt that can be permanently denied for
      nothing. Media3 does not require the declaration either — media3-session's
      own manifest declares no permissions, and the MediaSessionService guide
      asks only for the two FOREGROUND_SERVICE permissions above.

      It stays declared because the exemption is narrow: it is a property of the
      NOTIFICATION (MediaStyle *and* a non-null session token), not of the
      foreground service, and it covers media and self-managed-call notifications
      only. A download-completion notice (UR-011) would be an ordinary
      notification and would be silently dropped. Adding one means requesting
      this permission at runtime — AndroidX ActivityResultContracts.
      RequestPermission from MainActivity, at the point the feature is used — and
      handling refusal; keeping the declaration is what makes that a one-file
      change. See JellyTauPlaybackService.warnIfNotificationWillBeDropped.

      TRACES: UR-006 | DR-198
    -->
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <!--
      Android TV is deliberately NOT declared here.

      A LEANBACK_LAUNCHER category and an android.software.leanback uses-feature
      used to sit in this manifest, but nothing behind them: no D-pad focus
      model, no TV-sized layouts, and neither of the two declarations Play's TV
      validation also requires (android.hardware.touchscreen required="false"
      and an android:banner). That combination is the worst of both - it offers
      the app to TV launchers while failing TV review and shipping a UI that
      cannot be driven without a touchscreen.

      Re-declare all four together (leanback feature, LEANBACK_LAUNCHER,
      touchscreen required="false", banner) once a focus pass has actually been
      done, not before.
    -->

    <!--
      android:allowBackup / android:dataExtractionRules below:
      no cloud backup, no device-to-device transfer (UR-012).

      Credentials are encrypted under an Android Keystore key, and Keystore keys
      are NEVER backed up. A restored install would therefore get the
      jellytau_secure_prefs ciphertext with no key to open it - the app would
      look signed in and silently fail every request, which is worse than a
      login screen. Everything else in the data dir (the SQLite catalogue:
      library metadata, watch history, download bookkeeping) is a rebuildable
      mirror of the Jellyfin server, so backing it up buys nothing and exports
      the user's library and viewing history to their Google account.

      allowBackup covers API 24-30 completely, and kills *cloud* backup on API
      31+. It does NOT stop device-to-device transfer there, so
      @xml/data_extraction_rules (API 31+) excludes both channels explicitly. No
      android:fullBackupContent is needed: over the API 23-30 range where it
      would govern, allowBackup="false" has already turned backup off entirely.
    -->
    <application
        android:icon="@mipmap/ic_launcher"
        android:label="${appLabel}"
        android:theme="@style/Theme.jellytau"
        android:hardwareAccelerated="true"
        android:networkSecurityConfig="@xml/network_security_config"
        android:usesCleartextTraffic="${usesCleartextTraffic}"
        android:allowBackup="false"
        android:dataExtractionRules="@xml/data_extraction_rules">
        <activity
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|density"
            android:launchMode="singleTask"
            android:label="${activityLabel}"
            android:name=".MainActivity"
            android:exported="true"
            android:supportsPictureInPicture="true"
            android:resizeableActivity="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
                <!-- No LEANBACK_LAUNCHER: see the Android TV note above. -->
            </intent-filter>
        </activity>

        <provider
          android:name="androidx.core.content.FileProvider"
          android:authorities="${applicationId}.fileprovider"
          android:exported="false"
          android:grantUriPermissions="true">
          <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
        </provider>

        <!-- Media playback service for lockscreen controls -->
        <service
            android:name="com.dtourolle.jellytau.player.JellyTauPlaybackService"
            android:foregroundServiceType="mediaPlayback"
            android:exported="true">
            <intent-filter>
                <action android:name="androidx.media3.session.MediaSessionService" />
            </intent-filter>
        </service>
    </application>
</manifest>
