# The foreground-service video The Play Console's foreground-service declaration for `FOREGROUND_SERVICE_DATA_SYNC` requires a video of the user *triggering* the local import/export, not just a description. This is that video, and the record of how it was made. The All files access declaration has its own video and page: [PERMISSION_VIDEO](PERMISSION_VIDEO.md). ## The file | file | length | what it is | |---|---|---| | `store-assets/video/fgs-import-export.mp4` | **16.1 s** | The submission copy: 1080×2400, H.264, **no audio**, English captions burned in | | `store-assets/video/fgs-import-export-uncaptioned.mp4` | 18.8 s | The same cut without captions, for a voice-over | | `store-assets/video/fgs-import-export.srt` | — | The five captions and their timings | **The file is not a link.** Upload it to YouTube **Unlisted**, or Drive shared with "anyone with the link", and paste that URL into the foreground-service declaration. A private upload cannot be reviewed. ## What it shows | time | on screen | what it proves | |---|---|---| | 0:00 | `AADemo`, with `Source` selected and **Copy to…** in the action bar | The user starts a local import/export | | 0:02 | The **Copy to…** picker: `Internal storage`, then `AADemo` | The destination is chosen locally, without leaving the source | | 0:06 | The picker on `Target`, then **Copy here** | The user triggers the local copy | | 0:10 | The notification shade: **Copying files** with a moving progress bar | The `dataSync` foreground service is doing the work and reporting it | | 0:14 | `AADemo` with the snackbar **Copied 121 items to Target** and **Show** | The operation completed at the chosen destination | The captions, in order: 1. *Copy a 1.8 GB folder with Copy to…* 2. *Pick Internal storage, then AADemo* 3. *Choose Target, then Copy here* 4. *The foreground service reports progress* 5. *Done: Copied 121 items to Target* ## What was cut, and why The raw take was **41.0 s**; the published copy is three pieces of it: | kept | what it is | |---|---| | 0–9.5 s | Select `Source`, **Copy to…**, pick `Internal storage → AADemo → Target`, **Copy here** | | 21–25.5 s | The shade with **Copying files** and its progress bar | | 26–31 s | The completed folder and the **Copied 121 items to Target** snackbar | The two gaps are elapsed time, not evidence: the wait between **Copy here** and the notification appearing, and the wait between the shade closing and the listing refreshing. **The app's target listing stays empty until the copy finishes and then refreshes itself**, so the empty frames are the operation in progress, not a failure. The notification and the result are from the same take. Nothing else is edited. No home screen, launcher or library view appears — the recording starts inside `AADemo`. The shade was cleared of the phone's weather and Play cards before the take; what remains besides the app's notification is Android's generic USB debugging/transfer pair. The quick-settings panel shows only icons, battery and data totals; the Wi-Fi name exists in the accessibility tree but is not drawn on screen. Every filename is synthetic: the source is `AADemo/Source/file001.bin` … `file120.bin`, made from `/dev/zero`, and the destination is `AADemo/Target`. ## Re-shooting it Create the fixture first — 120 files of 16 MB, so the copy lasts long enough to read the notification: ```bash adb shell 'rm -rf /sdcard/AADemo/Target; mkdir -p /sdcard/AADemo/Source /sdcard/AADemo/Target for i in $(seq -w 1 120); do dd if=/dev/zero of=/sdcard/AADemo/Source/file$i.bin bs=1M count=16 2>/dev/null done' ``` Clear the notification shade before recording: open it, tap **Clear all**, and check with `adb shell cmd notification list`. The phone's own weather, Play and messaging cards must not appear in a video that will be published; USB debugging/transfer cards are generic and may stay. Open the app on **Internal storage → AADemo**, long-press `Source`, and verify the bar says **1 item** with **Copy to…** before recording. Then: ```bash adb shell rm -f /sdcard/fgs.mp4 adb shell screenrecord --size 1080x2400 --bit-rate 8000000 --time-limit 55 /sdcard/fgs.mp4 & sleep 1.5 adb shell input tap 231 2155 # Copy to… in the selection bar sleep 2 adb shell input tap 540 1148 # Internal storage in the picker sleep 2 adb shell input tap 540 994 # AADemo sleep 2 adb shell input tap 540 1302 # Target sleep 2 adb shell input tap 740 1396 # Copy here # The notification exists only after Copy here. Wait for it, or the shade shows only USB cards. for i in $(seq 1 16); do adb shell cmd notification list | grep -q 'de.softwareapp_hb.filemanager' && break sleep 0.5 done adb shell cmd statusbar expand-notifications sleep 6 # the card can rank below the USB pair for the first second adb shell cmd statusbar collapse sleep 18 # the copy must finish and the listing refresh adb shell pkill -INT screenrecord adb pull /sdcard/fgs.mp4 ``` Cut the two waits, keeping the trigger, the notification and the result. Use `-ss`/`-t` per segment rather than a filter graph: the phone records variable-frame video, and a `trim` concat came out 6 s short on this take. ```bash ffmpeg -y -ss 0 -t 9.5 -i fgs.mp4 -an -c:v libx264 -crf 20 -pix_fmt yuv420p seg-a.mp4 ffmpeg -y -ss 21 -t 4.5 -i fgs.mp4 -an -c:v libx264 -crf 20 -pix_fmt yuv420p seg-b.mp4 ffmpeg -y -ss 26 -t 5 -i fgs.mp4 -an -c:v libx264 -crf 20 -pix_fmt yuv420p seg-c.mp4 printf "file 'seg-a.mp4'\nfile 'seg-b.mp4'\nfile 'seg-c.mp4'\n" > segments.txt ffmpeg -y -f concat -safe 0 -i segments.txt -c copy fgs-cut.mp4 ``` The times are this take's; check the frames before reusing them. The published file is 16.1 s after the caption pass, because the last segment is shorter than its nominal five seconds. Three traps cost takes here: - **The picker recentres as the trail grows.** Its rows and its **Copy here** button move with each level, so map each screen with `adb shell uiautomator dump`; the coordinates above are this phone's 1080×2400 layout, not a scale factor. - **Never run `assembleRelease` and `adb install` in one parallel batch.** That race installed the previous APK, and the bar still said **Copy / Move** even though the new strings were in the built APK. Install sequentially, then check the phone: `aapt2 dump resources | grep browser_action_cut_to`. - **Open the shade only once the notification exists, and hold it.** Opening it straight after **Copy here** can show only Android's USB cards, and even when the app's card exists it can rank below them for the first second. The `cmd notification list` loop plus the 6 s hold is what made **Copying files** readable. Also expect the target listing to stay **empty** until the copy completes and the ViewModel reloads it. That is the operation still running, not a missed **Copy here**; `du -sh /sdcard/AADemo/Target` is the independent check. The captions are five PNG overlays at **y = 1900**, not the 2130 used by the all-files video: the selection bar sits at 2133–2177 on this phone, and a caption there hides the **Copy to…** button — the very action the video exists to show. ## Uploading it Upload `store-assets/video/fgs-import-export.mp4` to YouTube **Unlisted** or Drive with link sharing, and paste the URL into the **foreground-service** declaration. This is a different field from the All files access video: the permission video shows browsing a whole volume, this one shows the local copy that the `dataSync` service keeps alive.