Skip to content

Commit 574f917

Browse files
committed
Merge pull request #77686 from m4gr3d/fix_editor_audio_stream_microphone_crash_main
Fix issue causing the Android editor to crash when creating a new AudioStreamMicrophone
2 parents d998323 + 8ca1418 commit 574f917

File tree

6 files changed

+87
-17
lines changed

6 files changed

+87
-17
lines changed

platform/android/audio_driver_opensl.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ Error AudioDriverOpenSL::input_start() {
272272
return init_input_device();
273273
}
274274

275-
return OK;
275+
WARN_PRINT("Unable to start audio capture - No RECORD_AUDIO permission");
276+
return ERR_UNAUTHORIZED;
276277
}
277278

278279
Error AudioDriverOpenSL::input_stop() {

platform/android/java/editor/src/main/AndroidManifest.xml

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
2222
android:maxSdkVersion="29"/>
2323
<uses-permission android:name="android.permission.INTERNET" />
24+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
25+
<uses-permission android:name="android.permission.VIBRATE" />
2426

2527
<application
2628
android:allowBackup="false"

platform/android/java/editor/src/main/java/org/godotengine/editor/GodotEditor.kt

+16-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ open class GodotEditor : FullScreenGodotApp() {
8181
private val commandLineParams = ArrayList<String>()
8282

8383
override fun onCreate(savedInstanceState: Bundle?) {
84-
PermissionsUtil.requestManifestPermissions(this)
84+
// We exclude certain permissions from the set we request at startup, as they'll be
85+
// requested on demand based on use-cases.
86+
PermissionsUtil.requestManifestPermissions(this, setOf(Manifest.permission.RECORD_AUDIO))
8587

8688
val params = intent.getStringArrayExtra(COMMAND_LINE_PARAMS)
8789
updateCommandLineParams(params)
@@ -98,6 +100,8 @@ open class GodotEditor : FullScreenGodotApp() {
98100
val longPressEnabled = enableLongPressGestures()
99101
val panScaleEnabled = enablePanAndScaleGestures()
100102

103+
checkForProjectPermissionsToEnable()
104+
101105
runOnUiThread {
102106
// Enable long press, panning and scaling gestures
103107
godotFragment?.renderView?.inputHandler?.apply {
@@ -107,6 +111,17 @@ open class GodotEditor : FullScreenGodotApp() {
107111
}
108112
}
109113

114+
/**
115+
* Check for project permissions to enable
116+
*/
117+
protected open fun checkForProjectPermissionsToEnable() {
118+
// Check for RECORD_AUDIO permission
119+
val audioInputEnabled = java.lang.Boolean.parseBoolean(GodotLib.getGlobal("audio/driver/enable_input"));
120+
if (audioInputEnabled) {
121+
PermissionsUtil.requestPermission(Manifest.permission.RECORD_AUDIO, this)
122+
}
123+
}
124+
110125
private fun updateCommandLineParams(args: Array<String>?) {
111126
// Update the list of command line params with the new args
112127
commandLineParams.clear()

platform/android/java/editor/src/main/java/org/godotengine/editor/GodotGame.kt

+5
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,9 @@ class GodotGame : GodotEditor() {
3939
override fun enableLongPressGestures() = false
4040

4141
override fun enablePanAndScaleGestures() = false
42+
43+
override fun checkForProjectPermissionsToEnable() {
44+
// Nothing to do.. by the time we get here, the project permissions will have already
45+
// been requested by the Editor window.
46+
}
4247
}

platform/android/java/editor/src/main/java/org/godotengine/editor/GodotProjectManager.kt

+6-1
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,9 @@ package org.godotengine.editor
3737
* Upon selection of a project, this activity (via its parent logic) starts the
3838
* [GodotEditor] activity.
3939
*/
40-
class GodotProjectManager : GodotEditor()
40+
class GodotProjectManager : GodotEditor() {
41+
override fun checkForProjectPermissionsToEnable() {
42+
// Nothing to do here.. we have yet to select a project to load.
43+
}
44+
}
45+

platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java

+56-14
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,12 @@
4242
import android.provider.Settings;
4343
import android.util.Log;
4444

45+
import androidx.annotation.Nullable;
4546
import androidx.core.content.ContextCompat;
4647

4748
import java.util.ArrayList;
4849
import java.util.List;
50+
import java.util.Set;
4951

5052
/**
5153
* This class includes utility functions for Android permissions related operations.
@@ -58,38 +60,65 @@ public final class PermissionsUtil {
5860
static final int REQUEST_CAMERA_PERMISSION = 2;
5961
static final int REQUEST_VIBRATE_PERMISSION = 3;
6062
public static final int REQUEST_ALL_PERMISSION_REQ_CODE = 1001;
63+
public static final int REQUEST_SINGLE_PERMISSION_REQ_CODE = 1002;
6164
public static final int REQUEST_MANAGE_EXTERNAL_STORAGE_REQ_CODE = 2002;
6265

6366
private PermissionsUtil() {
6467
}
6568

6669
/**
6770
* Request a dangerous permission. name must be specified in <a href="https://github.com/aosp-mirror/platform_frameworks_base/blob/master/core/res/AndroidManifest.xml">this</a>
68-
* @param name the name of the requested permission.
71+
* @param permissionName the name of the requested permission.
6972
* @param activity the caller activity for this method.
7073
* @return true/false. "true" if permission was granted otherwise returns "false".
7174
*/
72-
public static boolean requestPermission(String name, Activity activity) {
75+
public static boolean requestPermission(String permissionName, Activity activity) {
7376
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
7477
// Not necessary, asked on install already
7578
return true;
7679
}
7780

78-
if (name.equals("RECORD_AUDIO") && ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
79-
activity.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, REQUEST_RECORD_AUDIO_PERMISSION);
80-
return false;
81-
}
81+
switch (permissionName) {
82+
case "RECORD_AUDIO":
83+
case Manifest.permission.RECORD_AUDIO:
84+
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
85+
activity.requestPermissions(new String[] { Manifest.permission.RECORD_AUDIO }, REQUEST_RECORD_AUDIO_PERMISSION);
86+
return false;
87+
}
88+
return true;
8289

83-
if (name.equals("CAMERA") && ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
84-
activity.requestPermissions(new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA_PERMISSION);
85-
return false;
86-
}
90+
case "CAMERA":
91+
case Manifest.permission.CAMERA:
92+
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
93+
activity.requestPermissions(new String[] { Manifest.permission.CAMERA }, REQUEST_CAMERA_PERMISSION);
94+
return false;
95+
}
96+
return true;
8797

88-
if (name.equals("VIBRATE") && ContextCompat.checkSelfPermission(activity, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) {
89-
activity.requestPermissions(new String[] { Manifest.permission.VIBRATE }, REQUEST_VIBRATE_PERMISSION);
90-
return false;
98+
case "VIBRATE":
99+
case Manifest.permission.VIBRATE:
100+
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.VIBRATE) != PackageManager.PERMISSION_GRANTED) {
101+
activity.requestPermissions(new String[] { Manifest.permission.VIBRATE }, REQUEST_VIBRATE_PERMISSION);
102+
return false;
103+
}
104+
return true;
105+
106+
default:
107+
// Check if the given permission is a dangerous permission
108+
try {
109+
PermissionInfo permissionInfo = getPermissionInfo(activity, permissionName);
110+
int protectionLevel = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ? permissionInfo.getProtection() : permissionInfo.protectionLevel;
111+
if (protectionLevel == PermissionInfo.PROTECTION_DANGEROUS && ContextCompat.checkSelfPermission(activity, permissionName) != PackageManager.PERMISSION_GRANTED) {
112+
activity.requestPermissions(new String[] { permissionName }, REQUEST_SINGLE_PERMISSION_REQ_CODE);
113+
return false;
114+
}
115+
} catch (PackageManager.NameNotFoundException e) {
116+
// Unknown permission - return false as it can't be granted.
117+
Log.w(TAG, "Unable to identify permission " + permissionName, e);
118+
return false;
119+
}
120+
return true;
91121
}
92-
return true;
93122
}
94123

95124
/**
@@ -98,6 +127,16 @@ public static boolean requestPermission(String name, Activity activity) {
98127
* @return true/false. "true" if all permissions were granted otherwise returns "false".
99128
*/
100129
public static boolean requestManifestPermissions(Activity activity) {
130+
return requestManifestPermissions(activity, null);
131+
}
132+
133+
/**
134+
* Request dangerous permissions which are defined in the Android manifest file from the user.
135+
* @param activity the caller activity for this method.
136+
* @param excludes Set of permissions to exclude from the request
137+
* @return true/false. "true" if all permissions were granted otherwise returns "false".
138+
*/
139+
public static boolean requestManifestPermissions(Activity activity, @Nullable Set<String> excludes) {
101140
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
102141
return true;
103142
}
@@ -115,6 +154,9 @@ public static boolean requestManifestPermissions(Activity activity) {
115154

116155
List<String> requestedPermissions = new ArrayList<>();
117156
for (String manifestPermission : manifestPermissions) {
157+
if (excludes != null && excludes.contains(manifestPermission)) {
158+
continue;
159+
}
118160
try {
119161
if (manifestPermission.equals(Manifest.permission.MANAGE_EXTERNAL_STORAGE)) {
120162
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {

0 commit comments

Comments
 (0)