[Scummvm-git-logs] scummvm master -> 30b8842885414662c0371943e63da7c6eee2b9e1

antoniou79 a.antoniou79 at gmail.com
Mon Sep 14 13:22:57 UTC 2020


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
30b8842885 ANDROID: Use custom handler for long key press detection


Commit: 30b8842885414662c0371943e63da7c6eee2b9e1
    https://github.com/scummvm/scummvm/commit/30b8842885414662c0371943e63da7c6eee2b9e1
Author: antoniou (a.antoniou79 at gmail.com)
Date: 2020-09-14T16:16:46+03:00

Commit Message:
ANDROID: Use custom handler for long key press detection

To avoid possible mem leaks (see "This Handler Class Should Be Static Or Leaks Might Occur” warning

Also a few optimizations based on recommendations from the Android Studio error highlighting/fix suggestions (F2)

Changed paths:
    backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
    backends/platform/android/org/scummvm/scummvm/ScummVM.java
    backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
    backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java


diff --git a/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java b/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
index 01482a3d5a..31b754280a 100644
--- a/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
+++ b/backends/platform/android/org/scummvm/scummvm/ExternalStorage.java
@@ -51,13 +51,13 @@ public class ExternalStorage {
 	}
 
 	private static Pattern
-		/** Pattern that SD card device should match */
+		// Pattern that SD card device should match
 		devicePattern = Pattern.compile("/dev/(block/.*vold.*|fuse)|/mnt/.*"),
-		/** Pattern that SD card mount path should match */
+		// Pattern that SD card mount path should match
 		pathPattern = Pattern.compile("/(mnt|storage|external_sd|extsd|_ExternalSD|Removable|.*MicroSD).*", Pattern.CASE_INSENSITIVE),
-		/** Pattern that the mount path should not match.
-		 * 'emulated' indicates an internal storage location, so skip it.
-		 * 'asec' is an encrypted package file, decrypted and mounted as a directory. */
+		// Pattern that the mount path should not match.
+		//' emulated' indicates an internal storage location, so skip it.
+		// 'asec' is an encrypted package file, decrypted and mounted as a directory.
 		pathAntiPattern = Pattern.compile(".*(/secure|/asec|/emulated).*"),
 		/** These are expected fs types, including vfat. tmpfs is not OK.
 		 * fuse can be removable SD card (as on Moto E or Asus ZenPad), or can be internal (Huawei G610). */
@@ -116,14 +116,14 @@ public class ExternalStorage {
 	public static LinkedHashSet<File> findSdCardPath() {
 		String[] mountFields;
 		BufferedReader bufferedReader = null;
-		String lineRead = null;
+		String lineRead;
 
-		/** Possible SD card paths */
-		LinkedHashSet<File> candidatePaths = new LinkedHashSet<File>();
+		// Possible SD card paths
+		LinkedHashSet<File> candidatePaths = new LinkedHashSet<>();
 
-		/** Build a list of candidate paths, roughly in order of preference. That way if
-		 * we can't definitively detect removable storage, we at least can pick a more likely
-		 * candidate. */
+		// Build a list of candidate paths, roughly in order of preference. That way if
+		// we can't definitively detect removable storage, we at least can pick a more likely
+		// candidate.
 
 		// Could do: use getExternalStorageState(File path), with and without an argument, when
 		// available. With an argument is available since API level 21.
@@ -153,7 +153,7 @@ public class ExternalStorage {
 		}
 
 		// Get listing of mounted devices with their properties.
-		ArrayList<File> mountedPaths = new ArrayList<File>();
+		ArrayList<File> mountedPaths = new ArrayList<>();
 		try {
 			// Note: Despite restricting some access to /proc (http://stackoverflow.com/a/38728738/423105),
 			// Android 7.0 does *not* block access to /proc/mounts, according to our test on George's Alcatel A30 GSM.
@@ -334,10 +334,7 @@ public class ExternalStorage {
 	 */
 	public static boolean isAvailable() {
 		String state = Environment.getExternalStorageState();
-		if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
-			return true;
-		}
-		return false;
+		return Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
 	}
 
 	public static String getSdCardPath() {
@@ -349,10 +346,7 @@ public class ExternalStorage {
 	 */
 	public static boolean isWritable() {
 		String state = Environment.getExternalStorageState();
-		if (Environment.MEDIA_MOUNTED.equals(state)) {
-			return true;
-		}
-		return false;
+		return Environment.MEDIA_MOUNTED.equals(state);
 
 	}
 
@@ -360,10 +354,10 @@ public class ExternalStorage {
 	 * @return list of locations available. Odd elements are names, even are paths
 	 */
 	public static List<String> getAllStorageLocations() {
-		List<String> map = new ArrayList<String>(20);
+		List<String> map = new ArrayList<>(20);
 
-		List<String> mMounts = new ArrayList<String>(10);
-		List<String> mVold = new ArrayList<String>(10);
+		List<String> mMounts = new ArrayList<>(10);
+		List<String> mVold = new ArrayList<>(10);
 		mMounts.add("/mnt/sdcard");
 		mVold.add("/mnt/sdcard");
 
@@ -417,27 +411,27 @@ public class ExternalStorage {
 		}
 		mVold.clear();
 
-		List<String> mountHash = new ArrayList<String>(10);
+		List<String> mountHash = new ArrayList<>(10);
 
 		for (String mount : mMounts) {
 			File root = new File(mount);
 			if (root.exists() && root.isDirectory() && root.canRead()) {
 				File[] list = root.listFiles();
-				String hash = "[";
+				StringBuilder hash = new StringBuilder("[");
 				if (list != null) {
 					for (File f : list) {
-						hash += f.getName().hashCode() + ":" + f.length() + ", ";
+						hash.append(f.getName().hashCode()).append(":").append(f.length()).append(", ");
 					}
 				}
-				hash += "]";
-				if (!mountHash.contains(hash)) {
+				hash.append("]");
+				if (!mountHash.contains(hash.toString())) {
 					String key = SD_CARD + "_" + (map.size() / 2);
 					if (map.size() == 0) {
 						key = SD_CARD;
 					} else if (map.size() == 2) {
 						key = EXTERNAL_SD_CARD;
 					}
-					mountHash.add(hash);
+					mountHash.add(hash.toString());
 					map.add(key);
 					map.add(root.getAbsolutePath());
 				}
@@ -456,7 +450,6 @@ public class ExternalStorage {
 
 			//Retrieve the External Storages root directory:
 			String externalStorageRootDir;
-			int count = 0;
 			if ((externalStorageRootDir = primaryExternalStorage.getParent()) == null) {  // no parent...
 				String key = primaryExternalStorage.getAbsolutePath();
 				if (!map.contains(key)) {
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index 22cf3fceca..0c28a83f47 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
@@ -1,23 +1,21 @@
 package org.scummvm.scummvm;
 
-import android.util.Log;
 import android.content.res.AssetManager;
-import android.view.SurfaceHolder;
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioTrack;
+import android.util.Log;
+import android.view.SurfaceHolder;
+
+import java.io.UnsupportedEncodingException;
+import java.util.LinkedHashMap;
 
-import javax.microedition.khronos.opengles.GL10;
 import javax.microedition.khronos.egl.EGL10;
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.egl.EGLContext;
 import javax.microedition.khronos.egl.EGLDisplay;
 import javax.microedition.khronos.egl.EGLSurface;
-
-import java.io.File;
-import java.io.UnsupportedEncodingException;
-import java.util.LinkedHashMap;
-import java.util.List;
+import javax.microedition.khronos.opengles.GL10;
 
 public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	final protected static String LOG_TAG = "ScummVM";
@@ -37,13 +35,15 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 
 	private String[] _args;
 
-	final private native void create(AssetManager asset_manager,
-										EGL10 egl, EGLDisplay egl_display,
-										AudioTrack audio_track,
-										int sample_rate, int buffer_size);
-	final private native void destroy();
-	final private native void setSurface(int width, int height);
-	final private native int main(String[] args);
+	private native void create(AssetManager asset_manager,
+	                           EGL10 egl,
+							   EGLDisplay egl_display,
+	                           AudioTrack audio_track,
+							   int sample_rate,
+							   int buffer_size);
+	private native void destroy();
+	private native void setSurface(int width, int height);
+	private native int main(String[] args);
 
 	// pause the engine and all native threads
 	final public native void setPause(boolean pause);
@@ -152,7 +152,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 		System.exit(res);
 	}
 
-	final private void initEGL() throws Exception {
+	private void initEGL() throws Exception {
 		_egl = (EGL10)EGLContext.getEGL();
 		_egl_display = _egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
 
@@ -219,7 +219,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 		_egl_surface = EGL10.EGL_NO_SURFACE;
 	}
 
-	final private void deinitEGL() {
+	private void deinitEGL() {
 		if (_egl_display != EGL10.EGL_NO_DISPLAY) {
 			_egl.eglMakeCurrent(_egl_display, EGL10.EGL_NO_SURFACE,
 								EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
@@ -240,7 +240,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 		_egl = null;
 	}
 
-	final private void initAudio() throws Exception {
+	private void initAudio() throws Exception {
 		_sample_rate = AudioTrack.getNativeOutputSampleRate(
 									AudioManager.STREAM_MUSIC);
 		_buffer_size = AudioTrack.getMinBufferSize(_sample_rate,
@@ -273,7 +273,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 								_audio_track.getState()));
 	}
 
-	final private void deinitAudio() {
+	private void deinitAudio() {
 		if (_audio_track != null)
 			_audio_track.stop();
 
@@ -406,9 +406,9 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 
 			return s;
 		}
-	};
+	}
 
-	final private EGLConfig chooseEglConfig(EGLConfig[] configs) {
+	private EGLConfig chooseEglConfig(EGLConfig[] configs) {
 		EGLConfig res = configs[0];
 		int bestScore = -1;
 
@@ -447,7 +447,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 		if (sleep_for_debugger) {
 			try {
 				Thread.sleep(20 * 1000);
-			} catch (InterruptedException e) {
+			} catch (InterruptedException ignored) {
 			}
 		}
 
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 31a9ee8dab..07965ae275 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -334,6 +334,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 		super.onDestroy();
 
 		if (_events != null) {
+			_events.clearEventHandler();
 			_events.sendQuitEvent();
 
 			try {
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
index 07c4233f0a..414033ab78 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEvents.java
@@ -1,5 +1,6 @@
 package org.scummvm.scummvm;
 
+import androidx.annotation.NonNull;
 import android.os.Handler;
 import android.os.Message;
 import android.content.Context;
@@ -12,6 +13,8 @@ import android.view.GestureDetector;
 import android.view.InputDevice;
 import android.view.inputmethod.InputMethodManager;
 
+import java.lang.ref.WeakReference;
+
 public class ScummVMEvents implements
 		android.view.View.OnKeyListener,
 		android.view.View.OnTouchListener,
@@ -48,6 +51,8 @@ public class ScummVMEvents implements
 	final protected int _longPress;
 	final protected MouseHelper _mouseHelper;
 
+	final private ScummVMEventHandler keyHandler;
+
 	public ScummVMEvents(Context context, ScummVM scummvm, MouseHelper mouseHelper) {
 		_context = context;
 		_scummvm = scummvm;
@@ -58,6 +63,28 @@ public class ScummVMEvents implements
 		_gd.setIsLongpressEnabled(false);
 
 		_longPress = ViewConfiguration.getLongPressTimeout();
+
+		keyHandler = new ScummVMEventHandler(new ScummVMEventHandler.OnMessageReceivedListener() {
+			@Override
+			public void handleMessage(final Message msg) {
+				if (msg.what == MSG_SMENU_LONG_PRESS) {
+					// this displays the android keyboard (see showVirtualKeyboard() in ScummVMActivity.java)
+					// when menu key is long-pressed
+					InputMethodManager imm = (InputMethodManager)
+						_context.getSystemService(Context.INPUT_METHOD_SERVICE);
+
+					if (imm != null)
+						imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
+				} else if (msg.what == MSG_SBACK_LONG_PRESS) {
+					_scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+					_scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+				}
+			}
+		});
+	}
+
+	public void clearEventHandler() {
+		keyHandler.clear();
 	}
 
 	final public void sendQuitEvent() {
@@ -79,23 +106,31 @@ public class ScummVMEvents implements
 	final static int MSG_SMENU_LONG_PRESS = 1;
 	final static int MSG_SBACK_LONG_PRESS = 2;
 
-	final private Handler keyHandler = new Handler() {
-		@Override
-		public void handleMessage(Message msg) {
-			if (msg.what == MSG_SMENU_LONG_PRESS) {
-				// this displays the android keyboard (see showVirtualKeyboard() in ScummVMActivity.java)
-				// when menu key is long-pressed
-				InputMethodManager imm = (InputMethodManager)
-					_context.getSystemService(Context.INPUT_METHOD_SERVICE);
-
-				if (imm != null)
-					imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
-			} else if (msg.what == MSG_SBACK_LONG_PRESS) {
-				_scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
-				_scummvm.pushEvent(JE_SYS_KEY, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MENU, 0, 0, 0, 0);
+	// Custom handler code (to avoid mem leaks, see warning "This Handler Class Should Be Static Or Leaks Might Occur”) based on:
+	// https://stackoverflow.com/a/57926736
+	public static class ScummVMEventHandler extends Handler {
+
+		WeakReference<OnMessageReceivedListener> mListenerReference;
+
+		public ScummVMEventHandler(OnMessageReceivedListener listener) {
+			mListenerReference = new WeakReference<>(listener);
+		}
+
+		public synchronized void handleMessage(@NonNull Message msg) {
+			OnMessageReceivedListener listener = mListenerReference.get();
+			if(listener != null) {
+				listener.handleMessage(msg);
 			}
 		}
-	};
+
+		public void clear() {
+			mListenerReference.clear();
+		}
+
+		public interface OnMessageReceivedListener {
+			void handleMessage(final Message message);
+		}
+	}
 
 	// OnKeyListener
 	@Override




More information about the Scummvm-git-logs mailing list