I am working on a security requirement for our product which states that the camera cannot be active while using our library. All of the possible solutions I investigated lack uniformity and coverage of all potential edge cases because with the most recent Android API levels users privacy is getting enhanced and for example, ActivityManager.getRunningTasks(int maxInt) and ActivityManager.getRunningAppProcesses() are deprecated and limited based on Android Docs, which could potentially give a solution.
Some other potential ways(based on Android Docs) of finding out if the camera is active:
UsageStatsManager.queryEvents Logs:
1: W UsageStatsManager TEST :: UsageStats event: me.jagar.xscamera2 8 secodns ago
2: W UsageStatsManager TEST :: UsageStats event: me.jagar.xscamera2 8 secodns ago
3: W UsageStatsManager TEST :: UsageStats event: com.google.android.apps.nexuslauncher 8 secodns ago
4: W UsageStatsManager TEST :: UsageStats event: android 8 secodns ago
5: W UsageStatsManager TEST :: UsageStats event: me.jagar.xscamera2 7 secodns ago
6: W UsageStatsManager TEST :: UsageStats event: com.google.android.apps.nexuslauncher 1 secodns ago
In line 4 that's where android hardware(camera) service is being activated by me.jagar.xscamera2. Complication: cannot rely on just android package name(says nothing about "camera service")
In addition, UsageStatsManager provides types of the events captured. Logs:
1: W UsageStatsManager TEST :: UsageStats event PKG NAME: me.jagar.xscamera2 :: 29 secodns ago :: TYPE: 19 -- HERE I STARTED THE RECORDING
2: W UsageStatsManager TEST :: UsageStats event PKG NAME: me.jagar.xscamera2 :: 29 secodns ago :: TYPE: 2
3: W UsageStatsManager TEST :: UsageStats event PKG NAME: com.google.android.apps.nexuslauncher :: 29 secodns ago :: TYPE: 1
4: W UsageStatsManager TEST :: UsageStats event PKG NAME: android :: 29 secodns ago :: TYPE: 12
5: W UsageStatsManager TEST :: UsageStats event PKG NAME: me.jagar.xscamera2 :: 29 secodns ago :: TYPE: 23
6: W UsageStatsManager TEST :: UsageStats event PKG NAME: com.google.android.apps.nexuslauncher :: 22 secodns ago :: TYPE: 2
7: W UsageStatsManager TEST :: UsageStats event PKG NAME: com.google.android.apps.nexuslauncher :: 21 secodns ago :: TYPE: 23
8: W UsageStatsManager TEST :: UsageStats event PKG NAME: me.jagar.xscamera2 :: 19 secodns ago :: TYPE: 12
9: W UsageStatsManager TEST :: UsageStats event PKG NAME: me.jagar.xscamera2 :: 11 secodns ago :: TYPE: 1
10: W UsageStatsManager TEST :: UsageStats event PKG NAME: me.jagar.xscamera2 :: 8 secodns ago :: TYPE: 20 -- HERE I STOPED THE RECORDING
Where:
UsageEvents.NOTIFICATION_INTERRUPTION = 12
UsageEvents.FOREGROUND_SERVICE_START = 19
UsageEvents.FOREGROUND_SERVICE_STOP = 20
me.jagar.xscamera2 is an arbitrary app what starts a foreground service for a preview and uses camera device to record in background.
Complication: Nothing tells me about camera device specifically. However, we can restrict any foreground service, which potentially gains preference to acquire the camera device, but on the other hand how do I make sure that I capture a long enough events list to see if the foreground service was started let's say a week ago, but never stopped? A year ago?
This answer has something useful: https://stackoverflow.com/a/39936381/23303897 . But I am not completely sure what do they mean.
Any other thoughts and solutions? What am I missing?
So, the answer is to use CameraManager.AvailabilityCallback
In my initial question I said that AvailabilityCallback could be used to detect if a camera is unavailable(meaning someone started using it), but what if the camera was active before launching our library?!
I missed/misinterpreted one sentence from docs which states:
The first time a callback is registered, it is immediately called with the availability status of all currently known camera devices.
If you have the same issue make sure to implement CameraManager.AvailabilityCallback and registerAvailabilityCallback(...). Implement your logic inside the callback covering the initial case when you roll call statuses of all currently known camera devices and then listen for the new states of the camera devices and do what you gotta do... Make sure to unregister the same instance of CameraManager.AvailabilityCallback!