Yeah, I noticed that as well.
There’s probably a reason com.android.shell
has access to all the things, including SYSTEM_CAMERA
.
I would guess debugging
Yeah, I noticed that as well.
There’s probably a reason com.android.shell
has access to all the things, including SYSTEM_CAMERA
.
I would guess debugging
Output (saved log) of the Magisk Module installation:
- Copying zip to temp directory
- Installing CamAsSystemApp.zip
- Current boot slot: _a
- Device is system-as-root
Archive: /data/user/0/com.topjohnwu.magisk/cache/flash/install.zip
inflating: module.prop
*************************
Cam as system app (FP4)
by Smojo
*************************
Archive: /data/user/0/com.topjohnwu.magisk/cache/flash/install.zip
inflating: customize.sh
*******************
Powered by Magisk
*******************
- Extracting module files
Archive: /data/user/0/com.topjohnwu.magisk/cache/flash/install.zip
creating: system/
creating: system/priv-app/
creating: system/priv-app/FPCamera/
inflating: system/priv-app/FPCamera/FPCamera.apk
creating: system/priv-app/FPCamera/oat/
creating: system/priv-app/FPCamera/oat/arm64/
inflating: system/priv-app/FPCamera/oat/arm64/FPCamera.odex
inflating: system/priv-app/FPCamera/oat/arm64/FPCamera.vdex
creating: system/etc/
creating: system/etc/permissions/
inflating: system/etc/permissions/privapp-permissions-com.fp.camera.xml
inflating: customize.sh
inflating: module.prop
Setting permissions of installed file(s)
Done
- Done
Looks okayish. I tend to reboot now. Any objections? ^^
Nope, looks good
Let’s see if everything worked
First thing you should check is dumpsys package com.fp.camera
.
The main activity will crash, but if you open the app via long press shortcut and choose Pro for example, you should be able to switch lenses.
Yes it worked.
Overview of a quick “Test Camera Functionality - FPCamera (as system app)”:
What is the issue with the normal mode? (how did you even discover that the Pro mode works? At that point I would have stopped and put it aside saying:“Hm doesn’t work.” )
Scoop App - Crash capture of FPCamera (normal mode)
FATAL EXCEPTION: ControlHandler
Process: com.fp.camera, PID: 23315
java.lang.IllegalArgumentException: getCameraCharacteristics:754: Unable to retrieve camera characteristics for unknown device : No such file or directory (-2)
at android.hardware.camera2.CameraManager.throwAsPublicException(CameraManager.java:1263)
at android.hardware.camera2.CameraManager.getCameraCharacteristics(CameraManager.java:591)
at android.hardware.camera2.CameraManager.getPhysicalIdToCharsMap(CameraManager.java:630)
at android.hardware.camera2.CameraManager.openCameraDeviceUserAsync(CameraManager.java:665)
at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:958)
at android.hardware.camera2.CameraManager.openCameraForUid(CameraManager.java:979)
at android.hardware.camera2.CameraManager.openCamera(CameraManager.java:817)
at com.android.camera.device.OneCameraImpl.doOpenCamera(OneCameraImpl.java:357)
at com.android.camera.device.OneCameraImpl$CameraHandler.handleMessage(OneCameraImpl.java:214)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: android.os.ServiceSpecificException: getCameraCharacteristics:754: Unable to retrieve camera characteristics for unknown device : No such file or directory (-2) (code 3)
at android.os.Parcel.createExceptionOrNull(Parcel.java:2440)
at android.os.Parcel.createException(Parcel.java:2410)
at android.os.Parcel.readException(Parcel.java:2393)
at android.os.Parcel.readException(Parcel.java:2335)
at android.hardware.ICameraService$Stub$Proxy.getCameraCharacteristics(ICameraService.java:812)
at android.hardware.camera2.CameraManager.getCameraCharacteristics(CameraManager.java:570)
... 11 more
Anything special you look for in dumpsys package com.fp.camera
?
For those who would like to try (and don’t start from scratch) or extend it or just play around, I put the module dummy to git: Git - CamAsSystemApp dummy
(It is just a dummy and does not include the APK/Folder and Files of FPCamera → it’s too big for git)
I debugged that issue. Problem is that for one of the cameras the HAL for the camera returns an “invalid” value (CameraCharacteristics.LOGICAL_MULTI_CAMERA_PHYSICAL_IDS) . That then causes an exception when opening that Camera via Camera2 Java APIs and makes the App crash :-/
Prior to Android 12 that value wasn’t accessed when opening the camera.
It’s a one line fix in android_frameworks_base/core/java/android/hardware/camera2/impl/CameraMetadataNative.java at lineage-19.1 · LineageOS/android_frameworks_base · GitHub to prevent it.
Awesome, I’m happy everything worked for you
Somebody on the forum discovered it some time ago. There are answers for all the problems on this forum, I’m pretty sure we’ll find the answer to life, the universe and everything at some point in the future
There are certainly some libraries missing, you would have on a stock install. The normal mode also lets you select several filters, my guess is that those might be crashing it, but I haven’t had the time to look at it really. Edit: Well, that happens if you take ages to write an answer, someone will provide the actual one
Mainly if everything worked fine with the permissions.xml
and the SYSTEM_CAMERA
permission was not only requested…
FP4:/ $ dumpsys package com.fp.camera | grep SYSTEM_CAMERA
android.permission.SYSTEM_CAMERA
android.permission.SYSTEM_CAMERA: granted=true
…but also actually granted.
Am I understanding you correctly that this workaround wouldn’t be necessary if the camera app was actually meant for A12, since it can’t handle that behaviour, or is there something else going on I’m not getting?
Should this be fixed in the FP Camera app once the FP4 officially moves over to 12?
I believe it’s not the fault of the App in this case. The app tries to open Camera ID 3 (BACK_SAT) when in normal photo mode. Camera with id “3” apparently is a logical camera - not sure what the actual purpose of this it all.
Logical cameras are supposed to have physical sub cameras. Now with updated framework code when opening the camera it tries to load the characteristics of the physcial subcameras. But the list of subcameras which is provided via the HAL is not well-formed. That’s supposed to be a byte array where the camera ID strings are separated by ‘\0’ bytes. But here for Fairphone it’s [‘\0’, ‘\0’, ‘0’, \0’].
That is then split into list of physical cameras [ “”, “”, “0” ]. Loading characteristics of unidentified Camera “” of course fails and throws the exception. That is all framework-internal.
We also see this in the log pasted above by @Smojo:
java.lang.IllegalArgumentException: getCameraCharacteristics:754: Unable to retrieve camera characteristics for unknown device : No such file or directory (-2)
So we can fix it to handle that data gracefully. For C++ Native Camera APIs that is actually filtered, but not on Java API side. The actual fix would be to provide a well-formed list of subcameras. That would probably be somewhere in closed source vendor camera blobs …
Can you implement that fix or is it already worked on by the LineageOS devs and could we bring that into CalyxOS?
So we need to have some Fairphone developers take a look at the findings in this thread. Great work guys!
So next step (or more a possibility) here would be testing Open Camera. I’m still not sure if I have the knowledge/skills to patch an APK … (even it sounds simple ^^)
→
but if I would just use the /e/OS Camera (which is a port of OpenCamera) the simple Magisk module approach, I used for the FPCamera (extract from factory zip etc. …), should work as well, or am I wrong?
I haven’t tried it, but that would have been my suggestion as well.
Why patch it if you can get one that should work already
Update: Well, crashes on start with the following error:
08-27 17:34:57.861 8307 8307 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{foundation.e.camera/net.sourceforge.opencamera.MainActivity}: android.view.InflateException: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Error inflating class android.widget.Button
So line #285 in this file, just a button, no idea what this means
No time to debug this further at the moment, but if it isn’t an easy fix, building OpenCamera with the proper permissions might be the easier route after all
--------- beginning of crash
08-27 18:08:29.801 16852 16852 E AndroidRuntime: FATAL EXCEPTION: main
08-27 18:08:29.801 16852 16852 E AndroidRuntime: Process: foundation.e.camera, PID: 16852
08-27 18:08:29.801 16852 16852 E AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{foundation.e.camera/net.sourceforge.opencamera.MainActivity}: android.view.InflateException: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Error inflating class android.widget.Button
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3707)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3864)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2253)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:201)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.os.Looper.loop(Looper.java:288)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7870)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: Caused by: android.view.InflateException: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Error inflating class android.widget.Button
08-27 18:08:29.801 16852 16852 E AndroidRuntime: Caused by: android.view.InflateException: Binary XML file line #285 in foundation.e.camera:layout/activity_main: Error inflating class android.widget.Button
08-27 18:08:29.801 16852 16852 E AndroidRuntime: Caused by: java.lang.reflect.InvocationTargetException
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at java.lang.reflect.Constructor.newInstance0(Native Method)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.createView(LayoutInflater.java:858)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.createView(LayoutInflater.java:780)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at com.android.internal.policy.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:58)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.onCreateView(LayoutInflater.java:934)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.onCreateView(LayoutInflater.java:954)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1008)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:965)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.rInflate(LayoutInflater.java:1127)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1088)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.inflate(LayoutInflater.java:686)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.inflate(LayoutInflater.java:538)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.view.LayoutInflater.inflate(LayoutInflater.java:485)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:461)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.Activity.setContentView(Activity.java:3526)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at net.sourceforge.opencamera.MainActivity.onCreate(MainActivity.java:224)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8057)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.Activity.performCreate(Activity.java:8037)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1345)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3688)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3864)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2253)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:201)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.os.Looper.loop(Looper.java:288)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7870)
08-27 18:08:29.801 16852 16852 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: Caused by: java.lang.UnsupportedOperationException: Failed to resolve attribute at index 6: TypedValue{t=0x2/d=0x101009b a=1}
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at android.content.res.TypedArray.getColorStateList(TypedArray.java:598)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at android.widget.TextView.readTextAppearance(TextView.java:4062)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at android.widget.TextView.<init>(TextView.java:1088)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at android.widget.Button.<init>(Button.java:166)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at android.widget.Button.<init>(Button.java:141)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: at android.widget.Button.<init>(Button.java:117)
08-27 18:08:29.802 16852 16852 E AndroidRuntime: ... 33 more
Hm :-/ if I start patching APKs it might be an option to try to remove this line.
I will start reading a bit about building an APK from it’s code (how I get the tools I need etc. …).
I first started to use nix-env
, which might not be the very best way to use it.
Short video why: Select a Invidious Instance - video: " Is nix-env bad?"
Great little article about nix and nix shell
: Working with nix-shell - SmartJava
As I will probably only use this from time to time I think something like setting up a
nix-shell android-tools.nix
is the better way and out in all the packages I need for the things discussed here (e.g. also gradle
can be added).
I’ve been reading along with great interest since the beginning and wanted to ask if you’ve made any progress.
I’ve had absolutely no time to experiment further in the last two weeks, not sure about the others…
I was able to build my own OpenCamera with SYSTEM_CAMERA
permission according to @xblax’s instructions.
I also successfully created a Magisk module using @Smojo’s dummy.
After installing, dumpsys
reports that SYSTEM_CAMERA
permission has been granted.
Unfortunately it doesn’t seem to pick up any additional cameras.
However, I am using the stock Fairphone OS, so that could be an issue, I guess.
Here is the Magisk module, in case anyone wants to try it on a different OS.
Did you switch OpenCamera to the Camera2 API (Settings → Camera API, restart the app)?
I’ve tried your module on CalyxOS and the wide-angle lens works fine
Great job
Oh, and welcome to the community BTW
Could we use our WeAreFairphone-Git for getting this to the masses :)?
Did you switch OpenCamera to the Camera2 API (Settings → Camera API, restart the app)?
Yes, otherwise there is nothing to change, right?
OpenCamera’s About in Settings also reports MultiCamera?: false
.
I’ve tried your module on CalyxOS and the wide-angle lens works fine
I’m glad it works for you
Oh, and welcome to the community BTW
Thank you very much.
Could we use our WeAreFairphone-Git for getting this to the masses :)?
Feel free to publish it wherever you want, at least from my side.
I am not sure if it would violate any of OpenCamera’s licenses, though.