Overview of a quick “Test Camera Functionality - FPCamera (as system app)”:
Normal Mode
(scoop crash log attached at the end of this post - basically: “unable to retrieve camera characteristics”)
Pro Mode
Switch lenses (to wide angle lense)
Panorama
HiRes - 48MP Mode
(accessible + possible to take pictures, but really 48MP? My test shot had 2.8MP ^^)
Video
Time Lapse (speed?)
SloMo (speed?; crashes after some sec)
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)
click to show ...
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.
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…
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 …
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
Full stack trace
--------- 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
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 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.
Welcome @maxmitti and nothing to add to @hirnsushi first reply to you. → Great job!
I didn’t had the time yet to work on this any further. Still miss some build tools to create my own APKs out of modified code (as most of us here I’m not a developer). Let’s see when I have time to play around with this again. I will try your module for now - so thanks again.