Godot: Automatic Godot Camera access (iOS) causes crash and App rejection

Created on 26 Nov 2019  Â·  10Comments  Â·  Source: godotengine/godot

Godot version:
3.2 Alpha, 3.2 Beta1, 3.2 Beta2

OS/device including version:
Tested on iOS 12/13

Issue description:

Godot automatically asks for camera access at startup wich causes the app to crash on certain devices and leads to the app rejection when you try to publish it.

I could reproduce the issue on an iPhone 5S using iOS12 (works fine on iPhone X and iPad Pro and iOS13). The App does not crash when you delete the "Privacy - Camera Usage Description" but Godot still tries to get permission and the App can not be uploaded to the App store.

I am trying to release a game for children and, apart from being unable to publish it, Godot asking for Camera access on startup is quite problematic.

My code does not contain any references to the camera, microphone or arkit. Everything is deselected and I have tried to exclude them using the entitlement description.

I have tried Godot 3.1, Godot 3.2 Alpha and both Betas. I have also tried to revert to 3.1.2RC1 but it does not recognize the .tscn files after they have been opened in 3.2

At the moment it is not possible for me to release the app due to this issue.

Steps to reproduce:
Upload any project to iOS App store

Minimal reproduction project:

bug high priority ios porting

Most helpful comment

A bit more advanced mock-up - https://github.com/bruvzg/godot/tree/ios_modular_build:

  • [x] All camera access implementations are moved to the camera module.
  • [x] iOS build - export template have all modules as separate libgodot_{module_name}_module.iphone.{release/debug}.{arch}.a static libs.
  • [x] iOS exporter - get available module list from the export template.
  • [x] iOS exporter - generate register_module_types.gen.cpp for selected modules on demand.
  • [x] iOS exporter - add selected static libs to the Xcode project.

All 10 comments

Yes, this is really problematic, confirmed. A similar issue has been raised pre-beta2 related to the packaging of ArKit and has been addressed by @bruvzg and @BastiaanOlij in [this PR] (https://github.com/godotengine/godot/pull/33759) but more needs to be done to resolve this properly and unfortunately I am not very up to speed with iOS and the build chain. I can help with testing though.

Also happening here on 3.2 beta 2.

Godot should not request camera access when "Camera usage description" is empty or missing: https://github.com/godotengine/godot/blob/master/platform/iphone/camera_ios.mm#L401-L410 (added in #30374), so it must be requested by some other code.

If the "Camera Privacy" entry is not set (delete the key or leave the "value" field empty) the Xcode Debugger output reads: "No NSCameraUsageDescription key in pList, no access to cameras." Apple will not to accept the build and send an email with the following statement:

"ITMS-90683: Missing Purpose String in Info.plist - Your app's code references one or more APIs that access sensitive user data. The app's Info.plist file should contain a NSCameraUsageDescription key with a user-facing purpose string explaining clearly and completely why your app needs the data. Starting Spring 2019, all apps submitted to the App Store that access user data are required to include a purpose string. If you're using external libraries or SDKs, they may reference APIs that require a purpose string. While your app might not use these APIs, a purpose string is still required. You can contact the developer of the library or SDK and request they release a version of their code that doesn't contain the APIs."

No NSCameraUsageDescription key in pList, no access to cameras

Yep, this is message from the Godot itself indicating camera init is skipped.

ITMS-90683: Missing Purpose String in Info.plist

Well, looks like just having camera code is enough to trigger this.

If this is the case we'll probably need to ship multiple versions of the export templates compiled with and without camera (and most likely microphone) support.

Or somehow split all sensitive the code into multiple static libs and load it dynamically.

Or somehow split all sensitive the code into multiple static libs and load it dynamically.

Here's basic mock-up:

AFAIK iOS dlsym doesn't work on RTLD_SELF and apps with .dylibs are not accepted to the App Store, so loading camera server code at the runtime is not an option.


1. Compile camera server code to the separate static lib (additionally make empty/stub lib version).

diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 85ba56165b..0c492f4553 100644
--- a/platform/iphone/SCsub
+++ b/platform/iphone/SCsub
@@ -14,12 +14,25 @@ iphone_lib = [
     'in_app_store.mm',
     'icloud.mm',
     'ios.mm',
+]
+
+iphone_camera_lib_real = [
     'camera_ios.mm',
 ]

+iphone_camera_lib_stub = [
+    'camera_ios_stub.mm',
+]
+
 env_ios = env.Clone()
 ios_lib = env_ios.add_library('iphone', iphone_lib)

+env_ios_camera_real = env.Clone()
+ios_lib_camera_real = env_ios_camera_real.add_library('iphone_camera_real', iphone_camera_lib_real)
+
+env_ios_camera_stub = env.Clone()
+ios_lib_camera_stub = env_ios_camera_stub.add_library('iphone_camera_stub', iphone_camera_lib_stub)
+
 def combine_libs(target=None, source=None, env=None):
     lib_path = target[0].srcnode().abspath
     if "osxcross" in env:
diff --git a/platform/iphone/camera_ios_stub.mm b/platform/iphone/camera_ios_stub.mm
new file mode 100644
index 0000000000..f724171df3
--- /dev/null
+++ b/platform/iphone/camera_ios_stub.mm
@@ -0,0 +1,12 @@
+/*************************************************************************/
+/*  camera_ios_stub.mm                                                   */
+/*************************************************************************/
+
+#include "camera_ios.h"
+#include "servers/camera/camera_feed.h"
+
+void CameraIOS::update_feeds() { /*NOP*/ }
+
+CameraIOS::CameraIOS() { /*NOP*/ }
+
+CameraIOS::~CameraIOS() { /*NOP*/ }

  1. On export include either real camera lib or stub (or generate stub code in place) to the Xcode project.

Been a bit preoccupied lately, sorry for jumping in late.

This is pretty horrible from Apple, it really makes it hard for generic
engines to operate. There are other features that fall under this type of
protection, having separate builds for each possible combination sounds
whack.

Seeing we do the final compile in xcode, would there be a way to
restructure this so we isolate the bits of logic in modules but instead of
compiling in the modules we add them as separate lib files? So we have a
dummy version and implemented version compiled and deployed in the template.
Then on export we decide which libraries to link in?

On Thu, 28 Nov 2019 at 11:51 pm, bruvzg notifications@github.com wrote:

Or somehow split all sensitive the code into multiple static libs and load
it dynamically.

Here's basic mock-up:

AFAIK iOS dlsym doesn't work on RTLD_SELF and apps with .dylibs are not
accepted to the App Store, so loading camera server code at the runtime is
not an option.

  1. Compile camera server code to the separate static lib (additionally
    make empty/stub lib version).

diff --git a/platform/iphone/SCsub b/platform/iphone/SCsub
index 85ba56165b..0c492f4553 100644--- a/platform/iphone/SCsub+++ b/platform/iphone/SCsub@@ -14,12 +14,25 @@ iphone_lib = [
'in_app_store.mm',
'icloud.mm',
'ios.mm',+]++iphone_camera_lib_real = [
'camera_ios.mm',
]
+iphone_camera_lib_stub = [+ 'camera_ios_stub.mm',+]+
env_ios = env.Clone()
ios_lib = env_ios.add_library('iphone', iphone_lib)
+env_ios_camera_real = env.Clone()+ios_lib_camera_real = env_ios_camera_real.add_library('iphone_camera_real', iphone_camera_lib_real)++env_ios_camera_stub = env.Clone()+ios_lib_camera_stub = env_ios_camera_stub.add_library('iphone_camera_stub', iphone_camera_lib_stub)+
def combine_libs(target=None, source=None, env=None):
lib_path = target[0].srcnode().abspath
if "osxcross" in env:diff --git a/platform/iphone/camera_ios_stub.mm b/platform/iphone/camera_ios_stub.mm
new file mode 100644
index 0000000000..f724171df3--- /dev/null+++ b/platform/iphone/camera_ios_stub.mm@@ -0,0 +1,12 @@+/***********************/+/* camera_ios_stub.mm /+/***********************/++#include "camera_ios.h"+#include "servers/camera/camera_feed.h"++void CameraIOS::update_feeds() { /NOP/ }++CameraIOS::CameraIOS() { /NOP/ }++CameraIOS::~CameraIOS() { /NOP*/ }

  1. On export include either real camera lib or stub (or generate stub code
    in place) to the Xcode project.

—
You are receiving this because you were assigned.

Reply to this email directly, view it on GitHub
https://github.com/godotengine/godot/issues/33918?email_source=notifications&email_token=AAO262LSEZ4MJOGY7ZFND3TQV65FXA5CNFSM4JR2QPW2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFMQSBI#issuecomment-559483141,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AAO262M4TX7EIFFVV6ALBR3QV65FXANCNFSM4JR2QPWQ
.

>

Kindest regards,

Bastiaan Olij

https://www.facebook.com/bastiaan.olij
https://twitter.com/mux213
https://www.youtube.com/BastiaanOlij
https://www.youtube.com/channel/UCrbLJYzJjDf2p-vJC011lYw
https://github.com/BastiaanOlij

A bit more advanced mock-up - https://github.com/bruvzg/godot/tree/ios_modular_build:

  • [x] All camera access implementations are moved to the camera module.
  • [x] iOS build - export template have all modules as separate libgodot_{module_name}_module.iphone.{release/debug}.{arch}.a static libs.
  • [x] iOS exporter - get available module list from the export template.
  • [x] iOS exporter - generate register_module_types.gen.cpp for selected modules on demand.
  • [x] iOS exporter - add selected static libs to the Xcode project.

@bruvzg you're a god dude :) I have to find time to play around with this.

@bruvzg Looks good and a sensible thing to do. Go for it.

Was this page helpful?
0 / 5 - 0 ratings