[Scummvm-git-logs] scummvm master -> 250206bd00096617c3aa549ff740ea44562347de
antoniou79
a.antoniou79 at gmail.com
Sun Aug 1 13:11:35 UTC 2021
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
4ac31d5481 ANDROID: Use SAF if a directory is not writeable
250206bd00 ANDROID: Add a checkbox for a revoke SAF permissions button
Commit: 4ac31d5481f87fb02a1741f9db024aafefeb0f15
https://github.com/scummvm/scummvm/commit/4ac31d5481f87fb02a1741f9db024aafefeb0f15
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2021-08-01T16:10:54+03:00
Commit Message:
ANDROID: Use SAF if a directory is not writeable
Changed paths:
backends/fs/posix/posix-fs.cpp
backends/platform/android/jni-android.cpp
backends/platform/android/jni-android.h
backends/platform/android/org/scummvm/scummvm/ScummVM.java
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/fs/posix/posix-fs.cpp b/backends/fs/posix/posix-fs.cpp
index 9a97850820..c357fede00 100644
--- a/backends/fs/posix/posix-fs.cpp
+++ b/backends/fs/posix/posix-fs.cpp
@@ -68,7 +68,14 @@ bool POSIXFilesystemNode::isReadable() const {
}
bool POSIXFilesystemNode::isWritable() const {
- return access(_path.c_str(), W_OK) == 0;
+ bool retVal = access(_path.c_str(), W_OK) == 0;
+#if defined(ANDROID_PLAIN_PORT)
+ if (!retVal) {
+ // Update return value if going through Android's SAF grants the permission
+ retVal = JNI::isDirectoryWritableWithSAF(_path);
+ }
+#endif // ANDROID_PLAIN_PORT
+ return retVal;
}
void POSIXFilesystemNode::setFlags() {
diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp
index 1d0e42ec99..38e6d074ea 100644
--- a/backends/platform/android/jni-android.cpp
+++ b/backends/platform/android/jni-android.cpp
@@ -91,6 +91,7 @@ jmethodID JNI::_MID_deinitSurface = 0;
jmethodID JNI::_MID_createDirectoryWithSAF = 0;
jmethodID JNI::_MID_createFileWithSAF = 0;
jmethodID JNI::_MID_closeFileWithSAF = 0;
+jmethodID JNI::_MID_isDirectoryWritableWithSAF = 0;
jmethodID JNI::_MID_EGL10_eglSwapBuffers = 0;
@@ -561,6 +562,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
FIND_METHOD(, createDirectoryWithSAF, "(Ljava/lang/String;)Z");
FIND_METHOD(, createFileWithSAF, "(Ljava/lang/String;)Ljava/lang/String;");
FIND_METHOD(, closeFileWithSAF, "(Ljava/lang/String;)V");
+ FIND_METHOD(, isDirectoryWritableWithSAF, "(Ljava/lang/String;)Z");
_jobj_egl = env->NewGlobalRef(egl);
_jobj_egl_display = env->NewGlobalRef(egl_display);
@@ -814,7 +816,6 @@ Common::U32String JNI::createFileWithSAF(const Common::String &filePath) {
Common::U32String hackyFilenameStr = convertFromJString(env, hackyFilenameJSTR);
- //LOGD("JNI - _MID_createFileWithSAF returned %s", hackyFilenameStr.c_str());
env->DeleteLocalRef(hackyFilenameJSTR);
return hackyFilenameStr;
@@ -836,4 +837,22 @@ void JNI::closeFileWithSAF(const Common::String &hackyFilename) {
}
+bool JNI::isDirectoryWritableWithSAF(const Common::String &dirPath) {
+ JNIEnv *env = JNI::getEnv();
+ jstring javaDirPath = env->NewStringUTF(dirPath.c_str());
+
+ bool isWritable = env->CallBooleanMethod(_jobj, _MID_isDirectoryWritableWithSAF, javaDirPath);
+
+ if (env->ExceptionCheck()) {
+ LOGE("JNI - Failed to check if directory is writable SAF enhanced method");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ isWritable = false;
+ }
+
+ return isWritable;
+
+}
+
#endif
diff --git a/backends/platform/android/jni-android.h b/backends/platform/android/jni-android.h
index 17a62aefa1..51908899ed 100644
--- a/backends/platform/android/jni-android.h
+++ b/backends/platform/android/jni-android.h
@@ -87,6 +87,7 @@ public:
static bool createDirectoryWithSAF(const Common::String &dirPath);
static Common::U32String createFileWithSAF(const Common::String &filePath);
static void closeFileWithSAF(const Common::String &hackyFilename);
+ static bool isDirectoryWritableWithSAF(const Common::String &dirPath);
private:
static JavaVM *_vm;
@@ -119,6 +120,7 @@ private:
static jmethodID _MID_createDirectoryWithSAF;
static jmethodID _MID_createFileWithSAF;
static jmethodID _MID_closeFileWithSAF;
+ static jmethodID _MID_isDirectoryWritableWithSAF;
static jmethodID _MID_EGL10_eglSwapBuffers;
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index 0852ddeb88..d23e1ee673 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
@@ -74,6 +74,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
abstract protected boolean createDirectoryWithSAF(String dirPath);
abstract protected String createFileWithSAF(String filePath);
abstract protected void closeFileWithSAF(String hackyFilename);
+ abstract protected boolean isDirectoryWritableWithSAF(String dirPath);
public ScummVM(AssetManager asset_manager, SurfaceHolder holder, final MyScummVMDestroyedCallback scummVMDestroyedCallback) {
_asset_manager = asset_manager;
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 776e134dc1..688381898d 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -417,19 +417,19 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// TODO - "Swipe" behavior does not seem to work currently. Should we support it?
public void swipeLeft() {
- //Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeLeft");
+// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeLeft");
}
public void swipeRight() {
- //Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeRight" );
+// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeRight" );
}
public void swipeDown() {
- //Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeDown" );
+// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeDown" );
}
public void swipeUp() {
- //Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeUp ");
+// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - swipeUp ");
}
public void onKey(int key, int[] keysAround) {
// Log.d(ScummVM.LOG_TAG, "SHOW KEYBOARD - 001 - onKey key: " + key );
@@ -583,7 +583,6 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
};
-
private class MyScummVM extends ScummVM {
public MyScummVM(SurfaceHolder holder, final MyScummVMDestroyedCallback destroyedCallback) {
@@ -793,6 +792,36 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return retRes[0];
}
+
+ // This is a simplified version of createDirectoryWithSAF
+ // TODO Maybe we could merge isDirectoryWritableWithSAF() with createDirectoryWithSAF() using an extra argument parameter
+ @Override
+ protected boolean isDirectoryWritableWithSAF(String dirPath) {
+ final boolean[] retRes = {false};
+
+ Log.d(ScummVM.LOG_TAG, "Check if folder writable: " + dirPath);
+ File folderToCheck = new File (dirPath);
+ if (folderToCheck.canWrite()) {
+ Log.d(ScummVM.LOG_TAG, "This path has write permission!" + dirPath);
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Trying to get write access with SAF");
+ if (getStorageAccessFrameworkTreeUri() == null) {
+ requestStorageAccessFramework(dirPath);
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Already requested Storage Access (Storage Access Framework) in the past (share prefs saved)!");
+ }
+ }
+
+ if (canWriteFile(folderToCheck, true)) {
+ Log.d(ScummVM.LOG_TAG, "(post SAF request) Writing is possible for this directory node");
+ retRes[0] = true;
+ } else {
+ Log.d(ScummVM.LOG_TAG, "(post SAF request) Error - writing is still not possible for this directory node");
+ }
+
+ return retRes[0];
+ }
+
@Override
protected String createFileWithSAF(String filePath) {
final String[] retResStr = {""};
@@ -2158,6 +2187,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
_scummvm.displayMessageOnOSD(getString(R.string.saf_request_prompt) + dirPathSample);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+ // Directory picker
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION
@@ -2298,14 +2328,20 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
} catch (Exception ignored) {
originalDirectory = true;
}
+
Uri treeUri;
if ((treeUri = getStorageAccessFrameworkTreeUri()) == null) {
return null;
}
+
DocumentFile dof = DocumentFile.fromTreeUri(getApplicationContext(), treeUri);
if (originalDirectory) {
return dof;
}
+
+ // Important note: We cannot assume that anything sent here is a relative path on top of the *ONLY* SAF "root" path
+ // since the the user could select another SD Card (from multiple inserted or replaces the current one and inserts another)
+ // TODO Can we translate our path string "/storage/XXXX-XXXXX/folder/doc.ext' a content URI? or a document URI?
String[] parts = relPath.split("\\/");
for (int i = 0; i < parts.length; i++) {
DocumentFile nextDof = dof.findFile(parts[i]);
Commit: 250206bd00096617c3aa549ff740ea44562347de
https://github.com/scummvm/scummvm/commit/250206bd00096617c3aa549ff740ea44562347de
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2021-08-01T16:10:54+03:00
Commit Message:
ANDROID: Add a checkbox for a revoke SAF permissions button
Themes were updated to version SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.48"
Changed paths:
A dists/android/res/drawable/ic_lock_icon.xml
backends/platform/android/jni-android.cpp
backends/platform/android/jni-android.h
backends/platform/android/options.cpp
backends/platform/android/org/scummvm/scummvm/ScummVM.java
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
common/system.h
dists/android/res/values/strings.xml
gui/ThemeEngine.h
gui/options.cpp
gui/options.h
gui/themes/default.inc
gui/themes/residualvm.zip
gui/themes/residualvm/THEMERC
gui/themes/residualvm/residualvm_layout.stx
gui/themes/residualvm/residualvm_layout_lowres.stx
gui/themes/scummclassic.zip
gui/themes/scummclassic/THEMERC
gui/themes/scummmodern.zip
gui/themes/scummmodern/THEMERC
gui/themes/scummmodern/scummmodern_layout.stx
gui/themes/scummmodern/scummmodern_layout_lowres.stx
gui/themes/scummremastered.zip
gui/themes/scummremastered/THEMERC
gui/themes/scummremastered/remastered_layout.stx
gui/themes/scummremastered/remastered_layout_lowres.stx
diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp
index 38e6d074ea..7baa3683dd 100644
--- a/backends/platform/android/jni-android.cpp
+++ b/backends/platform/android/jni-android.cpp
@@ -84,6 +84,7 @@ jmethodID JNI::_MID_isConnectionLimited = 0;
jmethodID JNI::_MID_setWindowCaption = 0;
jmethodID JNI::_MID_showVirtualKeyboard = 0;
jmethodID JNI::_MID_showKeyboardControl = 0;
+jmethodID JNI::_MID_showSAFRevokePermsControl = 0;
jmethodID JNI::_MID_getSysArchives = 0;
jmethodID JNI::_MID_getAllStorageLocations = 0;
jmethodID JNI::_MID_initSurface = 0;
@@ -385,6 +386,19 @@ void JNI::showKeyboardControl(bool enable) {
}
}
+void JNI::showSAFRevokePermsControl(bool enable) {
+ JNIEnv *env = JNI::getEnv();
+
+ env->CallVoidMethod(_jobj, _MID_showSAFRevokePermsControl, enable);
+
+ if (env->ExceptionCheck()) {
+ LOGE("Error trying to show the revoke SAF permissions button");
+
+ env->ExceptionDescribe();
+ env->ExceptionClear();
+ }
+}
+
// The following adds assets folder to search set.
// However searching and retrieving from "assets" on Android this is slow
// so we also make sure to add the "path" directory, with a higher priority
@@ -555,6 +569,7 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
FIND_METHOD(, isConnectionLimited, "()Z");
FIND_METHOD(, showVirtualKeyboard, "(Z)V");
FIND_METHOD(, showKeyboardControl, "(Z)V");
+ FIND_METHOD(, showSAFRevokePermsControl, "(Z)V");
FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
FIND_METHOD(, getAllStorageLocations, "()[Ljava/lang/String;");
FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
@@ -856,3 +871,4 @@ bool JNI::isDirectoryWritableWithSAF(const Common::String &dirPath) {
}
#endif
+
diff --git a/backends/platform/android/jni-android.h b/backends/platform/android/jni-android.h
index 51908899ed..81af274976 100644
--- a/backends/platform/android/jni-android.h
+++ b/backends/platform/android/jni-android.h
@@ -68,6 +68,7 @@ public:
static bool isConnectionLimited();
static void showVirtualKeyboard(bool enable);
static void showKeyboardControl(bool enable);
+ static void showSAFRevokePermsControl(bool enable);
static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
static inline bool haveSurface();
@@ -113,6 +114,7 @@ private:
static jmethodID _MID_setWindowCaption;
static jmethodID _MID_showVirtualKeyboard;
static jmethodID _MID_showKeyboardControl;
+ static jmethodID _MID_showSAFRevokePermsControl;
static jmethodID _MID_getSysArchives;
static jmethodID _MID_getAllStorageLocations;
static jmethodID _MID_initSurface;
diff --git a/backends/platform/android/options.cpp b/backends/platform/android/options.cpp
index 2ed2225feb..1839517506 100644
--- a/backends/platform/android/options.cpp
+++ b/backends/platform/android/options.cpp
@@ -62,6 +62,7 @@ private:
GUI::CheckboxWidget *_onscreenCheckbox;
GUI::CheckboxWidget *_touchpadCheckbox;
+ GUI::CheckboxWidget *_onscreenSAFRevokeCheckbox;
bool _enabled;
};
@@ -71,6 +72,7 @@ AndroidOptionsWidget::AndroidOptionsWidget(GuiObject *boss, const Common::String
_onscreenCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "AndroidOptionsDialog.OnScreenControl", _("Show On-screen control"));
_touchpadCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "AndroidOptionsDialog.TouchpadMode", _("Touchpad mouse mode"));
+ _onscreenSAFRevokeCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "AndroidOptionsDialog.SAFRevokePermsControl", _("Show SAF revoke permissions overlay button"));
}
AndroidOptionsWidget::~AndroidOptionsWidget() {
@@ -82,6 +84,7 @@ void AndroidOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::S
.addPadding(0, 0, 0, 0)
.addWidget("OnScreenControl", "Checkbox")
.addWidget("TouchpadMode", "Checkbox")
+ .addWidget("SAFRevokePermsControl", "Checkbox")
.closeLayout()
.closeDialog();
}
@@ -89,15 +92,18 @@ void AndroidOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::S
void AndroidOptionsWidget::load() {
_onscreenCheckbox->setState(ConfMan.getBool("onscreen_control", _domain));
_touchpadCheckbox->setState(ConfMan.getBool("touchpad_mouse_mode", _domain));
+ _onscreenSAFRevokeCheckbox->setState(ConfMan.getBool("onscreen_saf_revoke_btn", _domain));
}
bool AndroidOptionsWidget::save() {
if (_enabled) {
ConfMan.setBool("onscreen_control", _onscreenCheckbox->getState(), _domain);
ConfMan.setBool("touchpad_mouse_mode", _touchpadCheckbox->getState(), _domain);
+ ConfMan.setBool("onscreen_saf_revoke_btn", _onscreenSAFRevokeCheckbox->getState(), _domain);
} else {
ConfMan.removeKey("onscreen_control", _domain);
ConfMan.removeKey("touchpad_mouse_mode", _domain);
+ ConfMan.removeKey("onscreen_saf_revoke_btn", _domain);
}
return true;
@@ -105,7 +111,8 @@ bool AndroidOptionsWidget::save() {
bool AndroidOptionsWidget::hasKeys() {
return ConfMan.hasKey("onscreen_control", _domain) ||
- ConfMan.hasKey("touchpad_mouse_mode", _domain);
+ ConfMan.hasKey("touchpad_mouse_mode", _domain) ||
+ ConfMan.hasKey("onscreen_saf_revoke_btn", _domain);
}
void AndroidOptionsWidget::setEnabled(bool e) {
@@ -113,6 +120,7 @@ void AndroidOptionsWidget::setEnabled(bool e) {
_onscreenCheckbox->setEnabled(e);
_touchpadCheckbox->setEnabled(e);
+ _onscreenSAFRevokeCheckbox->setEnabled(e);
}
@@ -123,9 +131,11 @@ GUI::OptionsContainerWidget *OSystem_Android::buildBackendOptionsWidget(GUI::Gui
void OSystem_Android::registerDefaultSettings(const Common::String &target) const {
ConfMan.registerDefault("onscreen_control", true);
ConfMan.registerDefault("touchpad_mouse_mode", true);
+ ConfMan.registerDefault("onscreen_saf_revoke_btn", false);
}
void OSystem_Android::applyBackendSettings() {
JNI::showKeyboardControl(ConfMan.getBool("onscreen_control"));
+ JNI::showSAFRevokePermsControl(ConfMan.getBool("onscreen_saf_revoke_btn"));
_touchpad_mode = ConfMan.getBool("touchpad_mouse_mode");
}
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index d23e1ee673..73f6f5e439 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
@@ -68,6 +68,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
abstract protected void setWindowCaption(String caption);
abstract protected void showVirtualKeyboard(boolean enable);
abstract protected void showKeyboardControl(boolean enable);
+ abstract protected void showSAFRevokePermsControl(boolean enable);
abstract protected String[] getSysArchives();
abstract protected String[] getAllStorageLocations();
abstract protected String[] getAllStorageLocationsNoPermissionRequest();
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 688381898d..b472540ac8 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -117,6 +117,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private EditableSurfaceView _main_surface = null;
private ImageView _toggleKeyboardBtnIcon = null;
private ImageView _openMenuBtnIcon = null;
+ private ImageView _revokeSafPermissionsBtnIcon = null;
public View _screenKeyboard = null;
static boolean keyboardWithoutTextInputShown = false;
@@ -571,7 +572,6 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
};
-
public final View.OnClickListener menuBtnOnClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -583,6 +583,18 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
};
+ public final View.OnClickListener revokeSafPermissionsBtnOnClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ clearStorageAccessFrameworkTreeUri();
+ _scummvm.displayMessageOnOSD(getString(R.string.saf_revoke_done));
+ }
+ });
+ }
+ };
+
private class MyScummVM extends ScummVM {
public MyScummVM(SurfaceHolder holder, final MyScummVMDestroyedCallback destroyedCallback) {
@@ -687,6 +699,15 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
});
}
+ @Override
+ protected void showSAFRevokePermsControl(final boolean enable) {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ showSAFRevokePermissionsBtnIcon(enable);
+ }
+ });
+ }
+
@Override
protected String[] getSysArchives() {
Log.d(ScummVM.LOG_TAG, "Adding to Search Archive: " + _actualScummVMDataDir.getPath());
@@ -941,6 +962,11 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
buttonLayout.addView(_openMenuBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
buttonLayout.bringChildToFront(_openMenuBtnIcon);
+ _revokeSafPermissionsBtnIcon = new ImageView(this);
+ _revokeSafPermissionsBtnIcon.setImageResource(R.drawable.ic_lock_icon);
+ buttonLayout.addView(_revokeSafPermissionsBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
+ buttonLayout.bringChildToFront(_revokeSafPermissionsBtnIcon);
+
_main_surface.setFocusable(true);
_main_surface.setFocusableInTouchMode(true);
_main_surface.requestFocus();
@@ -1030,6 +1056,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
//findViewById(R.id.show_keyboard).setOnClickListener(keyboardBtnOnClickListener);
_toggleKeyboardBtnIcon.setOnClickListener(keyboardBtnOnClickListener);
_openMenuBtnIcon.setOnClickListener(menuBtnOnClickListener);
+ _revokeSafPermissionsBtnIcon.setOnClickListener(revokeSafPermissionsBtnOnClickListener);
// Keyboard visibility listener - mainly to hide system UI if keyboard is shown and we return from Suspend to the Activity
setKeyboardVisibilityListener(this);
@@ -1131,6 +1158,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
hideScreenKeyboard();
}
showToggleKeyboardBtnIcon(false);
+ showSAFRevokePermissionsBtnIcon(false);
}
@@ -1298,6 +1326,19 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
}
+ // Show or hide the semi-transparent overlay button
+ // for revoking SAF permissions
+ // This is independent of the toggle keyboard icon and menu icon (which appear together currently in showToggleKeyboardBtnIcon())
+ private void showSAFRevokePermissionsBtnIcon(boolean show) {
+ if (_revokeSafPermissionsBtnIcon != null ) {
+ if (show) {
+ _revokeSafPermissionsBtnIcon.setVisibility(View.VISIBLE);
+ } else {
+ _revokeSafPermissionsBtnIcon.setVisibility(View.GONE);
+ }
+ }
+ }
+
// Listener to check for keyboard visibility changes
// https://stackoverflow.com/a/36259261
private void setKeyboardVisibilityListener(final OnKeyboardVisibilityListener onKeyboardVisibilityListener) {
@@ -2217,6 +2258,26 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return null;
}
+ // A method to revoke SAF granted stored permissions
+ // TODO We need a button or setting to trigger this on user's demand
+ public void clearStorageAccessFrameworkTreeUri() {
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
+ return;
+ }
+
+ Uri treeUri;
+ if ((treeUri = getStorageAccessFrameworkTreeUri()) == null) {
+ return;
+ }
+
+ // revoke SAF permission AND clear the pertinent SharedPreferences key
+ getContentResolver().releasePersistableUriPermission(treeUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ SharedPreferences sharedPref = getPreferences(Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPref.edit();
+ editor.remove(getString(R.string.preference_saf_tree_key));
+ editor.apply();
+ }
+
public File getStorageRootFolder(final File file) {
String filepath;
try {
diff --git a/common/system.h b/common/system.h
index 26c6963a44..72c4cfd9ee 100644
--- a/common/system.h
+++ b/common/system.h
@@ -503,7 +503,12 @@ public:
/**
* For platforms that should not have a Quit button.
*/
- kFeatureNoQuit
+ kFeatureNoQuit,
+
+ /**
+ * Android specific button toggle to revoke storage permissions
+ */
+ kFeatureSAFRevokePermsControl
};
/**
diff --git a/dists/android/res/drawable/ic_lock_icon.xml b/dists/android/res/drawable/ic_lock_icon.xml
new file mode 100644
index 0000000000..8ed59fcf73
--- /dev/null
+++ b/dists/android/res/drawable/ic_lock_icon.xml
@@ -0,0 +1,11 @@
+<vector android:alpha="0.5" android:height="48dp"
+ android:viewportHeight="48" android:viewportWidth="48"
+ android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ffffff" android:pathData="M10,20h30v25h-30z"/>
+ <path android:fillColor="#ffffff"
+ android:pathData="M24.1836,-0.1387C22.4171,-0.1698 20.6862,0.2104 19.0703,1.0039 16.2909,2.3688 14.0478,4.9097 12.5781,8.3594c-0.2786,0.654 -0.7844,2.1021 -0.9727,2.7871l-0.0918,0.3379 2.2363,-0.0117 2.2383,-0.0117 0.2461,-0.5371c1.048,-2.2753 2.5856,-4.0879 4.4082,-5.1992 0.8166,-0.4979 1.7899,-0.8821 2.7891,-1.0977 0.4245,-0.0916 0.6295,-0.1039 1.5391,-0.1055 0.9158,-0.0016 1.115,0.0113 1.5801,0.1055 1.4601,0.2957 2.8223,0.9677 4.0605,2.0039 1.635,1.3683 2.9994,3.5111 3.832,6.0176 0.5823,1.7528 0.9676,3.981 1.0391,5.998l0.0313,0.8496h1.9707,1.9727v-0.4082c-0.0006,-1.2624 -0.2448,-3.3084 -0.584,-4.8867C37.5886,8.2233 34.1417,3.4317 29.5117,1.1875 27.7518,0.3344 25.9501,-0.1075 24.1836,-0.1387Z" android:strokeWidth="0.0465853"/>
+ <path android:fillColor="#ffffff"
+ android:pathData="M10.0624,32.5165V20.0317h14.9073,14.9073v12.4849,12.4849h-14.9073,-14.9073z" android:strokeWidth="0.186341"/>
+ <path android:fillColor="#ffffff"
+ android:pathData="M35.5103,17.8442C35.1329,13.1932 33.6772,9.5353 31.2341,7.0994 27.5554,3.4314 22.1709,3.54 18.5722,7.3548 17.8965,8.0711 16.9975,9.2878 16.5745,10.0586l-0.7691,1.4014H13.7724c-1.705,0 -2.0329,-0.0462 -2.0329,-0.2865 0,-0.5967 1.3591,-3.7746 2.1735,-5.082 1.7542,-2.8164 3.8975,-4.5919 6.719,-5.5661 2.6996,-0.9321 6.0179,-0.6265 8.8984,0.8194 3.4307,1.722 6.4099,5.0833 8.0319,9.0617 1.0465,2.5667 1.7557,5.8582 1.7557,8.1479v0.9182H37.4802,35.6424Z" android:strokeWidth="0.186341"/>
+</vector>
diff --git a/dists/android/res/values/strings.xml b/dists/android/res/values/strings.xml
index 7a9cb9d05c..08eb96d360 100644
--- a/dists/android/res/values/strings.xml
+++ b/dists/android/res/values/strings.xml
@@ -55,5 +55,6 @@
<string name="customkeyboardview_popup_close">Close popup</string>
<string name="saf_request_prompt">Please select the *root* of your external (physical) SD card. This is required for ScummVM to access this path: </string>
+ <string name="saf_revoke_done">Storage Access Framework Permissions for ScummVM were revoked!</string>
<string name="preference_saf_tree_key" translatable="false">pref_key__saf_tree_uri</string>
</resources>
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index 38cd57b98c..77af3405de 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -37,7 +37,7 @@
#include "graphics/pixelformat.h"
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.47"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.48"
class OSystem;
diff --git a/gui/options.cpp b/gui/options.cpp
index a3e28d6a6b..2401994592 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -167,6 +167,7 @@ void OptionsDialog::init() {
_enableControlSettings = false;
_onscreenCheckbox = nullptr;
_touchpadCheckbox = nullptr;
+ _onscreenSAFRevokeCheckbox = nullptr;
_swapMenuAndBackBtnsCheckbox = nullptr;
_kbdMouseSpeedDesc = nullptr;
_kbdMouseSpeedSlider = nullptr;
@@ -262,6 +263,13 @@ void OptionsDialog::build() {
_onscreenCheckbox->setState(onscreenState);
}
}
+ if (g_system->hasFeature(OSystem::kFeatureSAFRevokePermsControl)) {
+ if (ConfMan.hasKey("onscreen_saf_revoke_btn", _domain)) {
+ bool showSAFRevokeState = g_system->getFeatureState(OSystem::kFeatureSAFRevokePermsControl);
+ if (_onscreenSAFRevokeCheckbox != nullptr)
+ _onscreenSAFRevokeCheckbox->setState(showSAFRevokeState);
+ }
+ }
if (g_system->hasFeature(OSystem::kFeatureTouchpadMode)) {
if (ConfMan.hasKey("touchpad_mouse_mode", _domain)) {
bool touchpadState = g_system->getFeatureState(OSystem::kFeatureTouchpadMode);
@@ -806,6 +814,11 @@ void OptionsDialog::apply() {
g_system->setFeatureState(OSystem::kFeatureOnScreenControl, _onscreenCheckbox->getState());
}
}
+ if (g_system->hasFeature(OSystem::kFeatureSAFRevokePermsControl)) {
+ if (ConfMan.getBool("onscreen_saf_revoke_btn", _domain) != _onscreenSAFRevokeCheckbox->getState()) {
+ g_system->setFeatureState(OSystem::kFeatureSAFRevokePermsControl, _onscreenSAFRevokeCheckbox->getState());
+ }
+ }
if (g_system->hasFeature(OSystem::kFeatureTouchpadMode)) {
if (ConfMan.getBool("touchpad_mouse_mode", _domain) != _touchpadCheckbox->getState()) {
g_system->setFeatureState(OSystem::kFeatureTouchpadMode, _touchpadCheckbox->getState());
@@ -1211,6 +1224,10 @@ void OptionsDialog::addControlControls(GuiObject *boss, const Common::String &pr
if (g_system->hasFeature(OSystem::kFeatureOnScreenControl))
_onscreenCheckbox = new CheckboxWidget(boss, prefix + "grOnScreenCheckbox", _("Show On-screen control"));
+ // Show Overlay button to revoke SAF (storage access) ScummVM permissions (Android specific)
+ if (g_system->hasFeature(OSystem::kFeatureSAFRevokePermsControl))
+ _onscreenSAFRevokeCheckbox = new CheckboxWidget(boss, prefix + "grOnScreenSAFRevokeCheckbox ", _("Show SAF revoke permissions overlay button"));
+
// Touchpad Mouse mode
if (g_system->hasFeature(OSystem::kFeatureTouchpadMode))
_touchpadCheckbox = new CheckboxWidget(boss, prefix + "grTouchpadCheckbox", _("Touchpad mouse mode"));
@@ -1952,6 +1969,7 @@ void GlobalOptionsDialog::build() {
//
if (g_system->hasFeature(OSystem::kFeatureTouchpadMode) ||
g_system->hasFeature(OSystem::kFeatureOnScreenControl) ||
+ g_system->hasFeature(OSystem::kFeatureSAFRevokePermsControl) ||
g_system->hasFeature(OSystem::kFeatureSwapMenuAndBackButtons) ||
g_system->hasFeature(OSystem::kFeatureKbdMouseSpeed) ||
g_system->hasFeature(OSystem::kFeatureJoystickDeadzone)) {
diff --git a/gui/options.h b/gui/options.h
index 156a8c762f..0c670959cf 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -131,6 +131,7 @@ private:
CheckboxWidget *_touchpadCheckbox;
CheckboxWidget *_onscreenCheckbox;
+ CheckboxWidget *_onscreenSAFRevokeCheckbox;
CheckboxWidget *_swapMenuAndBackBtnsCheckbox;
StaticTextWidget *_kbdMouseSpeedDesc;
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 99ca9239d1..0bfa8eacd0 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1633,6 +1633,9 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<widget name='grTouchpadCheckbox' "
"type='Checkbox' "
"/>"
+"<widget name='grOnScreenSAFRevokeCheckbox' "
+"type='Checkbox' "
+"/>"
"<widget name='grSwapMenuAndBackBtnsCheckbox' "
"type='Checkbox' "
"/>"
@@ -3473,6 +3476,9 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
"<widget name='grTouchpadCheckbox' "
"type='Checkbox' "
"/>"
+"<widget name='grOnScreenSAFRevokeCheckbox' "
+"type='Checkbox' "
+"/>"
"<widget name='grSwapMenuAndBackBtnsCheckbox' "
"type='Checkbox' "
"/>"
diff --git a/gui/themes/residualvm.zip b/gui/themes/residualvm.zip
index 1373f44636..eef585ee81 100644
Binary files a/gui/themes/residualvm.zip and b/gui/themes/residualvm.zip differ
diff --git a/gui/themes/residualvm/THEMERC b/gui/themes/residualvm/THEMERC
index cf724c376a..38131f98b0 100644
--- a/gui/themes/residualvm/THEMERC
+++ b/gui/themes/residualvm/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.47:ResidualVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.48:ResidualVM Modern Theme:No Author]
diff --git a/gui/themes/residualvm/residualvm_layout.stx b/gui/themes/residualvm/residualvm_layout.stx
index c93237e8c1..6299982b8a 100644
--- a/gui/themes/residualvm/residualvm_layout.stx
+++ b/gui/themes/residualvm/residualvm_layout.stx
@@ -274,6 +274,9 @@
<widget name = 'grTouchpadCheckbox'
type = 'Checkbox'
/>
+ <widget name = 'grOnScreenSAFRevokeCheckbox'
+ type = 'Checkbox'
+ />
<widget name = 'grSwapMenuAndBackBtnsCheckbox'
type = 'Checkbox'
/>
diff --git a/gui/themes/residualvm/residualvm_layout_lowres.stx b/gui/themes/residualvm/residualvm_layout_lowres.stx
index c41d1f8670..7dc0d4695c 100644
--- a/gui/themes/residualvm/residualvm_layout_lowres.stx
+++ b/gui/themes/residualvm/residualvm_layout_lowres.stx
@@ -256,6 +256,9 @@
<widget name = 'grTouchpadCheckbox'
type = 'Checkbox'
/>
+ <widget name = 'grOnScreenSAFRevokeCheckbox'
+ type = 'Checkbox'
+ />
<widget name = 'grSwapMenuAndBackBtnsCheckbox'
type = 'Checkbox'
/>
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 1c042b5757..b47436bf1e 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index 1168571bad..de9947cf51 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.47:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.8.48:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 4250abf48f..478accc81d 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index e9b67c543b..d13e792996 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.47:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.48:ScummVM Modern Theme:No Author]
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index c93237e8c1..6299982b8a 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -274,6 +274,9 @@
<widget name = 'grTouchpadCheckbox'
type = 'Checkbox'
/>
+ <widget name = 'grOnScreenSAFRevokeCheckbox'
+ type = 'Checkbox'
+ />
<widget name = 'grSwapMenuAndBackBtnsCheckbox'
type = 'Checkbox'
/>
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index c41d1f8670..7dc0d4695c 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -256,6 +256,9 @@
<widget name = 'grTouchpadCheckbox'
type = 'Checkbox'
/>
+ <widget name = 'grOnScreenSAFRevokeCheckbox'
+ type = 'Checkbox'
+ />
<widget name = 'grSwapMenuAndBackBtnsCheckbox'
type = 'Checkbox'
/>
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index 90cc62a86e..361b9a8445 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/THEMERC b/gui/themes/scummremastered/THEMERC
index 1272ed64de..bbc4a7857d 100644
--- a/gui/themes/scummremastered/THEMERC
+++ b/gui/themes/scummremastered/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.47:ScummVM Modern Theme Remastered:No Author]
+[SCUMMVM_STX0.8.48:ScummVM Modern Theme Remastered:No Author]
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index 277dd6f3c3..a93dcf87b0 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -276,6 +276,9 @@
<widget name = 'grTouchpadCheckbox'
type = 'Checkbox'
/>
+ <widget name = 'grOnScreenSAFRevokeCheckbox'
+ type = 'Checkbox'
+ />
<widget name = 'grSwapMenuAndBackBtnsCheckbox'
type = 'Checkbox'
/>
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index 4292b8b7ec..3952929640 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -258,6 +258,9 @@
<widget name = 'grTouchpadCheckbox'
type = 'Checkbox'
/>
+ <widget name = 'grOnScreenSAFRevokeCheckbox'
+ type = 'Checkbox'
+ />
<widget name = 'grSwapMenuAndBackBtnsCheckbox'
type = 'Checkbox'
/>
More information about the Scummvm-git-logs
mailing list