How does Device File Explorer on Android Studio works

Problem Statement

How does Device File Explorer on Android Studio works

Problem Statement

When I tried to upload file to the package’s data dir, I tried to use adb push command to push the file on /sdcard directory, then use run-as command copy file to the app’s directory, but when I use run-as command, it can’t access the /sdcard directory, but when I tried to use Device File Explorer on the Android Studio, it can upload file, it was amazing, so I tried to find out why the Device File Explorer can upload files to the application’s data dir, I want to find the source code for Device File Explorer, but I didn’t find it. Then I think about the logs of the Android Studio, I mentioned the log directory for Android Studio on my previous article.

Solved: The emulator process for AVD has terminated
Today I encounter the problem when start an emulator on Android Studio, when start emulator, it report the following…

The log folder for Android Studio is ~/Library/Logs/Google/AndroidStudio<version> , when I monitor the logs on the idea.log and find that the Device File Explorer print the commands it used when operating, this article is what I found when I operate with it for both Emulator and Physical Device.

What can Device File Explorer do

When we open the Device File Explorer, we can choose the devices that was connected to the computer, both Simulator and Physical Devices. When we select a device, it will list the directory on the device as a directory tree, and we can navigate on the directory tree. We can also upload and download files from the device to local machine.

How does Device File Explorer do?

From the log we can see that the Device File Explorer run the different commands for Emulator and Physical Device, so I will explain both of them, from the log, we can see that the Device File Explorer use the adb command-line tool to list, upload and download files.

For emulators, because when we connect with adb, we can switch to super user, so on the emulator, it will use the super user to do the job, but for physical devices, because we can’t switch to super user, so it will use run-as command to do the jobs.

List devices

To list the devices, we can use adb devices -l , but on the log, I didn’t see that the Device File Explorer use this command, but on the Android Studio, it can list all the connected devices, so I think it just use the devices that Android Studio has got.

Run command with adb

From idea.log we can see some logs that Device File Explorer printed like below:su 0 sh -c 'id' || echo ERR-ERR-ERR-ERR

To execute the command above, we can run with adb shell like following:adb -s <$ANDROID_SERIAL> shell "su 0 sh -c 'id' || echo ERR-ERR-ERR-ERR"Example:
$ adb -s emulator-5554 shell "su 0 sh -c 'id' || echo ERR-ERR-ERR-ERR"
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:su:s0

List packages

The applications data dir is under /data/data/<package> , the Device File Explorer will list the package list when we navigate to /data/data dir, to list packages under /data/data dir, it’s different for emulator and physical device

Emulator

For emulator, it just use root user to list the content under /data/data folder.

Physical Device

For physical device, it just show three folders under /data dir, which are: app , data and local . When we open folders under /data dir, it will run the following commands:# List /data/data dir
pm list packages || echo ERR-ERR-ERR-ERR# List /data/app dir
pm list packages -f || echo ERR-ERR-ERR-ERR# List /data/local dir, just show a dir named tmp

List content of a package

Emulator

For emulator, it still use root user to list the content under the package’s data dir.

Physical Device

For physical device, it will use run-as command to list the content of a package’s data dir, the command below is to show the content of the package named com.swanwish.logviewer.run-as com.swanwish.logviewer sh -c 'ls -al /data/data/com.swanwish.logviewer/' || echo ERR-ERR-ERR-ERR

We can test this command with adb shell like below:$ adb -s adb-816d824e-2lp6Pe._adb-tls-connect._tcp. shell "run-as com.swanwish.logviewer sh -c 'ls -al /data/data/com.swanwish.logviewer/' || echo ERR-ERR-ERR-ERR"
total 52
drwx------   5 u0_a499 u0_a499        3488 2022-06-15 22:28 .
drwxrwx--x 473 system  system        53248 2022-06-17 15:00 ..
drwxrws--x   2 u0_a499 u0_a499_cache  3488 2022-06-15 22:28 cache
drwxrws--x   5 u0_a499 u0_a499_cache  3488 2022-06-15 23:13 code_cache
drwxrwx--x   2 u0_a499 u0_a499        3488 2022-06-15 22:28 files

Upload file

Because we can’t upload file directly to the data dir of a package, but the Device File Explorer can upload file, it’s so amazing, and I find the answer from the log file, it’s a little different between emulator and physical device.

The following command is I upload a file named crash.gif to my test app which has package name com.swanwish.logviewer .

Emulator

For emulator, it will crate a temp file under /data/local/tmp folder, and push file to that temp file, and copy file to the package’s data fir, and delete the temp file at last, the following is part of the commands that Device File Explorer used.# Create a temp file
su 0 sh -c 'touch /data/local/tmp/temp37c98352-e6c3-4d5d-8ff9-302cc22060ff' || echo ERR-ERR-ERR-ERR# Push file to the temp file
Push file took 24.45 ms to execute: "/Users/Stephen/Downloads/crash.gif" -> "/data/local/tmp/temp37c98352-e6c3-4d5d-8ff9-302cc22060ff"# copy file from temp file to dest file
su 0 sh -c 'cp /data/local/tmp/temp37c98352-e6c3-4d5d-8ff9-302cc22060ff /data/data/com.swanwish.logviewer/crash.gif' || echo ERR-ERR-ERR-ERR# Delete the temp file
su 0 sh -c 'rm -f /data/local/tmp/temp37c98352-e6c3-4d5d-8ff9-302cc22060ff' || echo ERR-ERR-ERR-ERR

Physical Device

For physical device, it will use run-as to finish the job, the following is some of the commands it used.# Create a temp file
touch /data/local/tmp/temp5e011b37-0ef8-4643-9272-2fb9d07774f6 || echo ERR-ERR-ERR-ERR# Upload file the temp file
Push file took 393.0 ms to execute: "/Users/Stephen/Downloads/crash.gif" -> "/data/local/tmp/temp5e011b37-0ef8-4643-9272-2fb9d07774f6"# Copy temp file to dest file
run-as com.swanwish.logviewer sh -c 'cp /data/local/tmp/temp5e011b37-0ef8-4643-9272-2fb9d07774f6 /data/data/com.swanwish.logviewer/crash.gif' || echo ERR-ERR-ERR-ERR# Delete the temp file
rm -f /data/local/tmp/temp5e011b37-0ef8-4643-9272-2fb9d07774f6 || echo ERR-ERR-ERR-ERR

Download file

Download file is similar with upload file, it just copy from package’s data dir to a temp file under /data/local/tmp folder, then download file from /data/local/tmp to local directory.

Delete file

Delete file also different between Emulator and Physical Devices, for Emulator, it will use the root user to delete the file, and for Physical Device, it will use the run-as command to do the job.

Emulatorsu 0 sh -c 'rm -f /data/data/com.swanwish.logviewer/crash.gif' || echo ERR-ERR-ERR-ERR

Physical Devicerun-as com.swanwish.logviewer sh -c 'rm -f /data/data/com.swanwish.logviewer/crash.gif' || echo ERR-ERR-ERR-ERR

Conclusion

From Device File Explorer , I learned that the /data/local/tmp directory is a magic dir, we can use it to upload and download files from package’s data dir. I hope if you also want to do that like me.

Thanks for your reading!