/* Simple DirectMedia Layer Java source code (C) 2009-2014 Sergii Pylypenko This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ package net.sourceforge.clonekeenplus; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.view.MotionEvent; import android.view.KeyEvent; import android.view.Window; import android.view.WindowManager; import android.widget.TextView; import android.util.Log; import java.io.*; import android.app.AlertDialog; import android.content.DialogInterface; import android.os.Environment; import android.os.StatFs; import java.util.Locale; import java.util.ArrayList; import java.util.Arrays; import java.util.zip.GZIPInputStream; import java.util.Collections; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; import java.lang.String; import android.graphics.Matrix; import android.graphics.RectF; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.FrameLayout; import android.graphics.drawable.BitmapDrawable; import android.graphics.BitmapFactory; import android.graphics.Bitmap; import android.widget.TextView; import android.widget.EditText; import android.widget.ScrollView; import android.widget.Button; import android.view.View; import android.widget.LinearLayout; import android.text.Editable; import android.text.SpannedString; import android.content.Intent; import android.app.PendingIntent; import android.app.AlarmManager; import android.util.DisplayMetrics; import android.net.Uri; import java.util.concurrent.Semaphore; import java.util.Arrays; import android.graphics.Color; import android.hardware.SensorEventListener; import android.hardware.SensorEvent; import android.hardware.Sensor; import android.widget.Toast; import android.content.pm.PackageManager; import android.os.Build; import android.content.Intent; // TODO: too much code here, split into multiple files, possibly auto-generated menus? class Settings { static String SettingsFileName = "libsdl-settings.cfg"; static boolean settingsLoaded = false; static boolean settingsChanged = false; static final int SETTINGS_FILE_VERSION = 5; static void Save(final MainActivity p) { try { ObjectOutputStream out = new ObjectOutputStream(p.openFileOutput( SettingsFileName, p.MODE_WORLD_READABLE )); out.writeInt(SETTINGS_FILE_VERSION); out.writeBoolean(Globals.DownloadToSdcard); out.writeBoolean(Globals.PhoneHasArrowKeys); out.writeBoolean(false); out.writeBoolean(Globals.UseAccelerometerAsArrowKeys); out.writeBoolean(Globals.UseTouchscreenKeyboard); out.writeInt(Globals.TouchscreenKeyboardSize); out.writeInt(Globals.AccelerometerSensitivity); out.writeInt(Globals.AccelerometerCenterPos); out.writeInt(0); out.writeInt(Globals.AudioBufferConfig); out.writeInt(Globals.TouchscreenKeyboardTheme); out.writeInt(Globals.RightClickMethod); out.writeInt(Globals.ShowScreenUnderFinger); out.writeInt(Globals.LeftClickMethod); out.writeBoolean(Globals.MoveMouseWithJoystick); out.writeBoolean(Globals.ClickMouseWithDpad); out.writeInt(Globals.ClickScreenPressure); out.writeInt(Globals.ClickScreenTouchspotSize); out.writeBoolean(Globals.KeepAspectRatio); out.writeInt(Globals.MoveMouseWithJoystickSpeed); out.writeInt(Globals.MoveMouseWithJoystickAccel); out.writeInt(SDL_Keys.JAVA_KEYCODE_LAST); for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ ) { out.writeInt(Globals.RemapHwKeycode[i]); } out.writeInt(Globals.RemapScreenKbKeycode.length); for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ ) { out.writeInt(Globals.RemapScreenKbKeycode[i]); } out.writeInt(Globals.ScreenKbControlsShown.length); for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ ) { out.writeBoolean(Globals.ScreenKbControlsShown[i]); } out.writeInt(Globals.TouchscreenKeyboardTransparency); out.writeInt(Globals.RemapMultitouchGestureKeycode.length); for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ ) { out.writeInt(Globals.RemapMultitouchGestureKeycode[i]); out.writeBoolean(Globals.MultitouchGesturesUsed[i]); } out.writeInt(Globals.MultitouchGestureSensitivity); for( int i = 0; i < Globals.TouchscreenCalibration.length; i++ ) out.writeInt(Globals.TouchscreenCalibration[i]); out.writeInt(Globals.DataDir.length()); for( int i = 0; i < Globals.DataDir.length(); i++ ) out.writeChar(Globals.DataDir.charAt(i)); out.writeInt(Globals.CommandLine.length()); for( int i = 0; i < Globals.CommandLine.length(); i++ ) out.writeChar(Globals.CommandLine.charAt(i)); out.writeInt(Globals.ScreenKbControlsLayout.length); for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ ) for( int ii = 0; ii < 4; ii++ ) out.writeInt(Globals.ScreenKbControlsLayout[i][ii]); out.writeInt(Globals.LeftClickKey); out.writeInt(Globals.RightClickKey); out.writeBoolean(Globals.VideoLinearFilter); out.writeInt(Globals.LeftClickTimeout); out.writeInt(Globals.RightClickTimeout); out.writeBoolean(Globals.RelativeMouseMovement); out.writeInt(Globals.RelativeMouseMovementSpeed); out.writeInt(Globals.RelativeMouseMovementAccel); out.writeBoolean(Globals.MultiThreadedVideo); out.writeInt(Globals.OptionalDataDownload.length); for(int i = 0; i < Globals.OptionalDataDownload.length; i++) out.writeBoolean(Globals.OptionalDataDownload[i]); out.writeBoolean(false); // Unused out.writeInt(Globals.TouchscreenKeyboardDrawSize); out.writeInt(p.getApplicationVersion()); // Gyroscope calibration data, now unused out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeFloat(0.0f); out.writeBoolean(Globals.OuyaEmulation); out.writeBoolean(Globals.HoverJitterFilter); out.writeBoolean(Globals.MoveMouseWithGyroscope); out.writeInt(Globals.MoveMouseWithGyroscopeSpeed); out.writeBoolean(Globals.FingerHover); out.writeBoolean(Globals.FloatingScreenJoystick); out.writeBoolean(Globals.GenerateSubframeTouchEvents); out.writeInt(Globals.VideoDepthBpp); out.writeBoolean(Globals.HorizontalOrientation); out.writeBoolean(Globals.ImmersiveMode); out.writeBoolean(Globals.AutoDetectOrientation); out.writeBoolean(Globals.TvBorders); out.close(); settingsLoaded = true; } catch( FileNotFoundException e ) { } catch( SecurityException e ) { } catch ( IOException e ) {}; } static void Load( final MainActivity p ) { if(settingsLoaded) // Prevent starting twice { return; } Log.i("SDL", "libSDL: Settings.Load(): enter"); nativeInitKeymap(); for( int i = 0; i < SDL_Keys.JAVA_KEYCODE_LAST; i++ ) { int sdlKey = nativeGetKeymapKey(i); int idx = 0; for(int ii = 0; ii < SDL_Keys.values.length; ii++) if(SDL_Keys.values[ii] == sdlKey) idx = ii; Globals.RemapHwKeycode[i] = idx; } for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ ) { int sdlKey = nativeGetKeymapKeyScreenKb(i); int idx = 0; for(int ii = 0; ii < SDL_Keys.values.length; ii++) if(SDL_Keys.values[ii] == sdlKey) idx = ii; Globals.RemapScreenKbKeycode[i] = idx; } Globals.ScreenKbControlsShown[0] = (Globals.AppNeedsArrowKeys || Globals.AppUsesJoystick); Globals.ScreenKbControlsShown[1] = Globals.AppNeedsTextInput; for( int i = 2; i < Globals.ScreenKbControlsShown.length; i++ ) Globals.ScreenKbControlsShown[i] = ( i - 2 < Globals.AppTouchscreenKeyboardKeysAmount ); if( Globals.AppUsesSecondJoystick ) Globals.ScreenKbControlsShown[8] = true; if( Globals.AppUsesThirdJoystick ) Globals.ScreenKbControlsShown[9] = true; for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ ) { int sdlKey = nativeGetKeymapKeyMultitouchGesture(i); int idx = 0; for(int ii = 0; ii < SDL_Keys.values.length; ii++) if(SDL_Keys.values[ii] == sdlKey) idx = ii; Globals.RemapMultitouchGestureKeycode[i] = idx; } for( int i = 0; i < Globals.MultitouchGesturesUsed.length; i++ ) Globals.MultitouchGesturesUsed[i] = true; // Adjust coordinates of on-screen buttons from 800x480 int displayX = 800; int displayY = 480; try { DisplayMetrics dm = new DisplayMetrics(); p.getWindowManager().getDefaultDisplay().getMetrics(dm); displayX = dm.widthPixels; displayY = dm.heightPixels; } catch (Exception eeeee) {} for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ ) { Globals.ScreenKbControlsLayout[i][0] *= (float)displayX / 800.0f; Globals.ScreenKbControlsLayout[i][2] *= (float)displayX / 800.0f; Globals.ScreenKbControlsLayout[i][1] *= (float)displayY / 480.0f; Globals.ScreenKbControlsLayout[i][3] *= (float)displayY / 480.0f; // Make them square int wh = Math.min( Globals.ScreenKbControlsLayout[i][2] - Globals.ScreenKbControlsLayout[i][0], Globals.ScreenKbControlsLayout[i][3] - Globals.ScreenKbControlsLayout[i][1] ); Globals.ScreenKbControlsLayout[i][2] = Globals.ScreenKbControlsLayout[i][0] + wh; Globals.ScreenKbControlsLayout[i][3] = Globals.ScreenKbControlsLayout[i][1] + wh; } Log.i("SDL", "android.os.Build.MODEL: " + android.os.Build.MODEL); if( (android.os.Build.MODEL.equals("GT-N7000") || android.os.Build.MODEL.equals("SGH-I717")) && android.os.Build.VERSION.SDK_INT <= android.os.Build.VERSION_CODES.GINGERBREAD_MR1 ) { // Samsung Galaxy Note generates a keypress when you hover a stylus over the screen, and that messes up OpenTTD dialogs // ICS update sends events in a proper way Globals.RemapHwKeycode[112] = SDL_1_2_Keycodes.SDLK_UNKNOWN; } try { ObjectInputStream settingsFile = new ObjectInputStream(new FileInputStream( p.getFilesDir().getAbsolutePath() + "/" + SettingsFileName )); if( settingsFile.readInt() != SETTINGS_FILE_VERSION ) throw new IOException(); Globals.DownloadToSdcard = settingsFile.readBoolean(); Globals.PhoneHasArrowKeys = settingsFile.readBoolean(); settingsFile.readBoolean(); Globals.UseAccelerometerAsArrowKeys = settingsFile.readBoolean(); Globals.UseTouchscreenKeyboard = settingsFile.readBoolean(); Globals.TouchscreenKeyboardSize = settingsFile.readInt(); Globals.AccelerometerSensitivity = settingsFile.readInt(); Globals.AccelerometerCenterPos = settingsFile.readInt(); settingsFile.readInt(); Globals.AudioBufferConfig = settingsFile.readInt(); Globals.TouchscreenKeyboardTheme = settingsFile.readInt(); Globals.RightClickMethod = settingsFile.readInt(); Globals.ShowScreenUnderFinger = settingsFile.readInt(); Globals.LeftClickMethod = settingsFile.readInt(); Globals.MoveMouseWithJoystick = settingsFile.readBoolean(); Globals.ClickMouseWithDpad = settingsFile.readBoolean(); Globals.ClickScreenPressure = settingsFile.readInt(); Globals.ClickScreenTouchspotSize = settingsFile.readInt(); Globals.KeepAspectRatio = settingsFile.readBoolean(); Globals.MoveMouseWithJoystickSpeed = settingsFile.readInt(); Globals.MoveMouseWithJoystickAccel = settingsFile.readInt(); int readKeys = settingsFile.readInt(); for( int i = 0; i < readKeys; i++ ) { Globals.RemapHwKeycode[i] = settingsFile.readInt(); } if( settingsFile.readInt() != Globals.RemapScreenKbKeycode.length ) throw new IOException(); for( int i = 0; i < Globals.RemapScreenKbKeycode.length; i++ ) { Globals.RemapScreenKbKeycode[i] = settingsFile.readInt(); } if( settingsFile.readInt() != Globals.ScreenKbControlsShown.length ) throw new IOException(); for( int i = 0; i < Globals.ScreenKbControlsShown.length; i++ ) { Globals.ScreenKbControlsShown[i] = settingsFile.readBoolean(); } Globals.TouchscreenKeyboardTransparency = settingsFile.readInt(); if( settingsFile.readInt() != Globals.RemapMultitouchGestureKeycode.length ) throw new IOException(); for( int i = 0; i < Globals.RemapMultitouchGestureKeycode.length; i++ ) { Globals.RemapMultitouchGestureKeycode[i] = settingsFile.readInt(); Globals.MultitouchGesturesUsed[i] = settingsFile.readBoolean(); } Globals.MultitouchGestureSensitivity = settingsFile.readInt(); for( int i = 0; i < Globals.TouchscreenCalibration.length; i++ ) Globals.TouchscreenCalibration[i] = settingsFile.readInt(); StringBuilder b = new StringBuilder(); int len = settingsFile.readInt(); for( int i = 0; i < len; i++ ) b.append( settingsFile.readChar() ); Globals.DataDir = b.toString(); b = new StringBuilder(); len = settingsFile.readInt(); for( int i = 0; i < len; i++ ) b.append( settingsFile.readChar() ); Globals.CommandLine = b.toString(); if( settingsFile.readInt() != Globals.ScreenKbControlsLayout.length ) throw new IOException(); for( int i = 0; i < Globals.ScreenKbControlsLayout.length; i++ ) for( int ii = 0; ii < 4; ii++ ) Globals.ScreenKbControlsLayout[i][ii] = settingsFile.readInt(); Globals.LeftClickKey = settingsFile.readInt(); Globals.RightClickKey = settingsFile.readInt(); Globals.VideoLinearFilter = settingsFile.readBoolean(); Globals.LeftClickTimeout = settingsFile.readInt(); Globals.RightClickTimeout = settingsFile.readInt(); Globals.RelativeMouseMovement = settingsFile.readBoolean(); Globals.RelativeMouseMovementSpeed = settingsFile.readInt(); Globals.RelativeMouseMovementAccel = settingsFile.readInt(); Globals.MultiThreadedVideo = settingsFile.readBoolean(); Globals.OptionalDataDownload = new boolean[settingsFile.readInt()]; for(int i = 0; i < Globals.OptionalDataDownload.length; i++) Globals.OptionalDataDownload[i] = settingsFile.readBoolean(); settingsFile.readBoolean(); // Unused Globals.TouchscreenKeyboardDrawSize = settingsFile.readInt(); int cfgVersion = settingsFile.readInt(); // Gyroscope calibration data, now unused settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); settingsFile.readFloat(); Globals.OuyaEmulation = settingsFile.readBoolean(); Globals.HoverJitterFilter = settingsFile.readBoolean(); Globals.MoveMouseWithGyroscope = settingsFile.readBoolean(); Globals.MoveMouseWithGyroscopeSpeed = settingsFile.readInt(); Globals.FingerHover = settingsFile.readBoolean(); Globals.FloatingScreenJoystick = settingsFile.readBoolean(); Globals.GenerateSubframeTouchEvents = settingsFile.readBoolean(); Globals.VideoDepthBpp = settingsFile.readInt(); Globals.HorizontalOrientation = settingsFile.readBoolean(); Globals.ImmersiveMode = settingsFile.readBoolean(); Globals.AutoDetectOrientation = settingsFile.readBoolean(); Globals.TvBorders = settingsFile.readBoolean(); settingsLoaded = true; Log.i("SDL", "libSDL: Settings.Load(): loaded settings successfully"); settingsFile.close(); Log.i("SDL", "libSDL: old cfg version " + cfgVersion + ", our version " + p.getApplicationVersion()); if( cfgVersion != p.getApplicationVersion() ) { DeleteFilesOnUpgrade(p); if( Globals.ResetSdlConfigForThisVersion ) { Log.i("SDL", "libSDL: old cfg version " + cfgVersion + ", our version " + p.getApplicationVersion() + " and we need to clean up config file"); // Delete settings file, and restart the application DeleteSdlConfigOnUpgradeAndRestart(p); } Save(p); } return; } catch( FileNotFoundException e ) { } catch( SecurityException e ) { } catch ( IOException e ) { DeleteFilesOnUpgrade(p); if( Globals.ResetSdlConfigForThisVersion ) { Log.i("SDL", "libSDL: old cfg version unknown or too old, our version " + p.getApplicationVersion() + " and we need to clean up config file"); DeleteSdlConfigOnUpgradeAndRestart(p); } }; if( Globals.DataDir.length() == 0 ) { if( !Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) ) { Log.i("SDL", "libSDL: SD card or external storage is not mounted (state " + Environment.getExternalStorageState() + "), switching to the internal storage."); Globals.DownloadToSdcard = false; } if( p.getPackageManager().checkPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE, p.getPackageName()) != PackageManager.PERMISSION_GRANTED && android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT ) { Log.i("SDL", "libSDL: We don't have permission to write to SD card, switching to the internal storage."); Globals.DownloadToSdcard = false; } Globals.DataDir = Globals.DownloadToSdcard ? SdcardAppPath.getBestPath(p) : p.getFilesDir().getAbsolutePath(); if( Globals.DownloadToSdcard ) { // Check if data already installed into deprecated location at /sdcard/app-data/ String[] fileList = new File(SdcardAppPath.deprecatedPath(p)).list(); if( fileList != null ) for( String s: fileList ) if( s.toUpperCase().startsWith(DataDownloader.DOWNLOAD_FLAG_FILENAME.toUpperCase()) ) Globals.DataDir = SdcardAppPath.deprecatedPath(p); // Also check for pre-Kitkat files location fileList = new File(SdcardAppPath.getPath(p)).list(); if( fileList != null ) for( String s: fileList ) if( s.toUpperCase().startsWith(DataDownloader.DOWNLOAD_FLAG_FILENAME.toUpperCase()) ) Globals.DataDir = SdcardAppPath.getPath(p); try { new File(Globals.DataDir).mkdirs(); new FileOutputStream( new File(Globals.DataDir, ".nomedia") ).close(); } catch (Exception e) { Log.i("SDL", "libSDL: cannot create .nomedia file at " + Globals.DataDir + " - switching to internal storage"); Globals.DownloadToSdcard = false; // SD card not writable Globals.DataDir = p.getFilesDir().getAbsolutePath(); } } } Log.i("SDL", "libSDL: Settings.Load(): loading settings failed, running config dialog"); p.setScreenOrientation(); p.setUpStatusLabel(); if( checkRamSize(p) ) SettingsMenu.showConfig(p, true); } // =============================================================================================== public static boolean deleteRecursively(File dir) { if (dir.isDirectory()) { String[] children = dir.list(); for (int i=0; i Globals.TouchscreenCalibration[0] ) nativeSetTouchscreenCalibration(Globals.TouchscreenCalibration[0], Globals.TouchscreenCalibration[1], Globals.TouchscreenCalibration[2], Globals.TouchscreenCalibration[3]); } static void setEnvVars(MainActivity p) { String lang = new String(Locale.getDefault().getLanguage()); if( Locale.getDefault().getCountry().length() > 0 ) lang = lang + "_" + Locale.getDefault().getCountry(); Log.i("SDL", "libSDL: setting envvar LANGUAGE to '" + lang + "'"); nativeSetEnv( "LANG", lang ); nativeSetEnv( "LANGUAGE", lang ); // TODO: get current user name and set envvar USER, the API is not availalbe on Android 1.6 so I don't bother with this nativeSetEnv( "APPDIR", p.getFilesDir().getAbsolutePath() ); nativeSetEnv( "SECURE_STORAGE_DIR", p.getFilesDir().getAbsolutePath() ); nativeSetEnv( "DATADIR", Globals.DataDir ); nativeSetEnv( "UNSECURE_STORAGE_DIR", Globals.DataDir ); SdcardAppPath.setEnv(p); nativeSetEnv( "HOME", Globals.DataDir ); nativeSetEnv( "SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath() ); nativeSetEnv( "SDCARD_DOWNLOADS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() ); nativeSetEnv( "SDCARD_PICTURES", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath() ); nativeSetEnv( "SDCARD_MOVIES", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).getAbsolutePath() ); nativeSetEnv( "SDCARD_DCIM", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).getAbsolutePath() ); nativeSetEnv( "SDCARD_MUSIC", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath() ); nativeSetEnv( "SDCARD_MUSIC", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath() ); nativeSetEnv( "ANDROID_VERSION", String.valueOf(android.os.Build.VERSION.SDK_INT) ); nativeSetEnv( "ANDROID_PACKAGE_NAME", p.getPackageName() ); nativeSetEnv( "ANDROID_MY_OWN_APP_FILE", p.getPackageResourcePath() ); try { nativeSetEnv( "ANDROID_APP_NAME", p.getString(p.getApplicationInfo().labelRes) ); } catch (Exception eeeeee) {} if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO ) nativeSetEnv( "ANDROID_PACKAGE_PATH", p.getPackageCodePath() ); Log.d("SDL", "libSDL: Is running on OUYA: " + p.isRunningOnOUYA()); if( p.isRunningOnOUYA() ) { nativeSetEnv( "OUYA", "1" ); nativeSetEnv( "TV", "1" ); nativeSetEnv( "ANDROID_TV", "1" ); } if (p.getIntent().getCategories() != null && p.getIntent().getCategories().contains("com.google.intent.category.CARDBOARD")) { nativeSetEnv( "CARDBOARD", "1" ); nativeSetEnv( "VR", "1" ); nativeSetEnv( "CARDBOARD_VR", "1" ); } if (p.getIntent().getStringExtra(RestartMainActivity.SDL_RESTART_PARAMS) != null) nativeSetEnv( RestartMainActivity.SDL_RESTART_PARAMS, p.getIntent().getStringExtra(RestartMainActivity.SDL_RESTART_PARAMS) ); try { DisplayMetrics dm = new DisplayMetrics(); p.getWindowManager().getDefaultDisplay().getMetrics(dm); float xx = dm.widthPixels/dm.xdpi; float yy = dm.heightPixels/dm.ydpi; float x = Math.max(xx, yy); float y = Math.min(xx, yy); float displayInches = (float)Math.sqrt( x*x + y*y ); nativeSetEnv( "DISPLAY_SIZE", String.valueOf(displayInches) ); nativeSetEnv( "DISPLAY_SIZE_MM", String.valueOf((int)(displayInches*25.4f)) ); nativeSetEnv( "DISPLAY_WIDTH", String.valueOf(x) ); nativeSetEnv( "DISPLAY_HEIGHT", String.valueOf(y) ); nativeSetEnv( "DISPLAY_WIDTH_MM", String.valueOf((int)(x*25.4f)) ); nativeSetEnv( "DISPLAY_HEIGHT_MM", String.valueOf((int)(y*25.4f)) ); nativeSetEnv( "DISPLAY_RESOLUTION_WIDTH", String.valueOf(Math.max(dm.widthPixels, dm.heightPixels)) ); nativeSetEnv( "DISPLAY_RESOLUTION_HEIGHT", String.valueOf(Math.min(dm.widthPixels, dm.heightPixels)) ); } catch (Exception eeeee) {} } static byte [] loadRaw(Activity p, int res) { byte [] buf = new byte[65536 * 2]; byte [] a = new byte[1048576 * 5]; // We need 5Mb buffer for Keen theme, and this Java code is inefficient int written = 0; try{ InputStream is = new GZIPInputStream(p.getResources().openRawResource(res)); int readed = 0; while( (readed = is.read(buf)) >= 0 ) { if( written + readed > a.length ) { byte [] b = new byte [written + readed]; System.arraycopy(a, 0, b, 0, written); a = b; } System.arraycopy(buf, 0, a, written, readed); written += readed; } } catch(Exception e) {}; byte [] b = new byte [written]; System.arraycopy(a, 0, b, 0, written); return b; } static void SetupTouchscreenKeyboardGraphics(Activity p) { if( Globals.UseTouchscreenKeyboard ) { if(Globals.TouchscreenKeyboardTheme < 0) Globals.TouchscreenKeyboardTheme = 0; if(Globals.TouchscreenKeyboardTheme > 9) Globals.TouchscreenKeyboardTheme = 9; if( Globals.TouchscreenKeyboardTheme == 0 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.ultimatedroid)); if( Globals.TouchscreenKeyboardTheme == 1 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.simpletheme)); if( Globals.TouchscreenKeyboardTheme == 2 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.sun)); if( Globals.TouchscreenKeyboardTheme == 3 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.keen)); if( Globals.TouchscreenKeyboardTheme == 4 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.retro)); if( Globals.TouchscreenKeyboardTheme == 5 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.gba)); if( Globals.TouchscreenKeyboardTheme == 6 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.psx)); if( Globals.TouchscreenKeyboardTheme == 7 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.snes)); if( Globals.TouchscreenKeyboardTheme == 8 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.dualshock)); if( Globals.TouchscreenKeyboardTheme == 9 ) nativeSetupScreenKeyboardButtons(loadRaw(p, R.raw.n64)); } } abstract static class SdcardAppPath { private static SdcardAppPath get() { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) return Kitkat.Holder.sInstance; else if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.FROYO) return Froyo.Holder.sInstance; else return Dummy.Holder.sInstance; } public abstract String path(final Context p); private void setEnvInternal(final Context p) { nativeSetEnv( "UNSECURE_STORAGE_DIR_0", Globals.DataDir ); } public static void setEnv(final Context p) { get().setEnvInternal(p); } public String bestPath(final Context p) { return path(p); }; public static String deprecatedPath(final Context p) { return Environment.getExternalStorageDirectory().getAbsolutePath() + "/app-data/" + p.getPackageName(); } public static String getPath(final Context p) { try { return get().path(p); } catch(Exception e) { } return Dummy.Holder.sInstance.path(p); } public static String getBestPath(final Context p) { try { return get().bestPath(p); } catch(Exception e) { } return Dummy.Holder.sInstance.path(p); } private static class Froyo extends SdcardAppPath { private static class Holder { private static final Froyo sInstance = new Froyo(); } public String path(final Context p) { return p.getExternalFilesDir(null).getAbsolutePath(); } } private static class Kitkat extends Froyo { private static class Holder { private static final Kitkat sInstance = new Kitkat(); } public String bestPath(final Context p) { File[] paths = p.getExternalFilesDirs(null); String ret = path(p); long maxSize = -1; for( File path: paths ) { if( path == null ) continue; StatFs stat = new StatFs(path.getPath()); long size = (long)stat.getAvailableBlocks() * stat.getBlockSize() / 1024 / 1024; try { path.mkdirs(); new FileOutputStream( new File(path, ".nomedia") ).close(); } catch (Exception e) { size = -1; // Not writable } if( size > maxSize ) { maxSize = size; ret = path.getAbsolutePath(); } } return ret; }; public void setEnvInternal(final Context p) { File[] paths = p.getExternalFilesDirs(null); int index = 0; for( File path: paths ) { if( path == null ) continue; if( !path.exists() ) path.mkdirs(); nativeSetEnv( "UNSECURE_STORAGE_DIR_" + index, path.getAbsolutePath() ); index++; } } } private static class Dummy extends SdcardAppPath { private static class Holder { private static final Dummy sInstance = new Dummy(); } public String path(final Context p) { return Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + p.getPackageName() + "/files"; } } } static boolean checkRamSize(final MainActivity p) { try { BufferedReader reader = new BufferedReader(new FileReader("/proc/meminfo")); String line = null; while( ( line = reader.readLine() ) != null ) { if( line.indexOf("MemTotal:") == 0 ) { String[] fields = line.split("[ \t]+"); Long size = Long.parseLong(fields[1]); Log.i("SDL", "Device RAM size: " + size / 1024 + " Mb, required minimum RAM: " + Globals.AppMinimumRAM + " Mb" ); if( size / 1024 < Globals.AppMinimumRAM ) { settingsChanged = true; AlertDialog.Builder builder = new AlertDialog.Builder(p); builder.setTitle(R.string.not_enough_ram); builder.setMessage(p.getResources().getString( R.string.not_enough_ram_size, Globals.AppMinimumRAM, (int)(size / 1024)) ); builder.setPositiveButton(p.getResources().getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { p.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + p.getPackageName()))); System.exit(0); } }); builder.setNegativeButton(p.getResources().getString(R.string.ignore), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { SettingsMenu.showConfig(p, true); return; } }); builder.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { p.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + p.getPackageName()))); System.exit(0); } }); final AlertDialog alert = builder.create(); alert.setOwnerActivity(p); alert.show(); return false; } } } } catch ( Exception e ) { Log.i("SDL", "Error: cannot parse /proc/meminfo: " + e.toString()); } return true; } static final int SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP = 0; public static void setConfigOptionFromSDL(int option, int value) { switch (option) { case SDL_ANDROID_CONFIG_VIDEO_DEPTH_BPP: Globals.VideoDepthBpp = value; break; default: Log.e("SDL", "setConfigOptionFromSDL: cannot find option with ID " + option + ", value " + value); break; } Save(MainActivity.instance); } private static native void nativeSetAccelerometerSettings(int sensitivity, int centerPos); private static native void nativeSetMouseUsed(int RightClickMethod, int ShowScreenUnderFinger, int LeftClickMethod, int MoveMouseWithJoystick, int ClickMouseWithDpad, int MaxForce, int MaxRadius, int MoveMouseWithJoystickSpeed, int MoveMouseWithJoystickAccel, int leftClickKeycode, int rightClickKeycode, int leftClickTimeout, int rightClickTimeout, int relativeMovement, int relativeMovementSpeed, int relativeMovementAccel, int showMouseCursor, int HoverJitterFilter, int RightMouseButtonLongPress, int MoveMouseWithGyroscope, int MoveMouseWithGyroscopeSpeed, int ForceScreenUpdateMouseClick, int ScreenFollowsMouse); private static native void nativeSetJoystickUsed(int amount); private static native void nativeSetAccelerometerUsed(); private static native void nativeSetMultitouchUsed(); private static native void nativeSetTouchscreenKeyboardUsed(); private static native void nativeSetVideoLinearFilter(); private static native void nativeSetVideoDepth(int bpp, int gles2); private static native void nativeSetCompatibilityHacks(); private static native void nativeSetVideoMultithreaded(); private static native void nativeSetVideoForceSoftwareMode(); private static native void nativeSetupScreenKeyboard(int size, int drawsize, int theme, int transparency, int floatingScreenJoystick); private static native void nativeSetupScreenKeyboardButtons(byte[] img); private static native void nativeInitKeymap(); private static native int nativeGetKeymapKey(int key); private static native void nativeSetKeymapKey(int javakey, int key); private static native int nativeGetKeymapKeyScreenKb(int keynum); private static native void nativeSetKeymapKeyScreenKb(int keynum, int key); private static native void nativeSetScreenKbKeyUsed(int keynum, int used); private static native void nativeSetScreenKbKeyLayout(int keynum, int x1, int y1, int x2, int y2); private static native int nativeGetKeymapKeyMultitouchGesture(int keynum); private static native void nativeSetKeymapKeyMultitouchGesture(int keynum, int key); private static native void nativeSetMultitouchGestureSensitivity(int sensitivity); private static native void nativeSetTouchscreenCalibration(int x1, int y1, int x2, int y2); public static native void nativeSetEnv(final String name, final String value); public static native int nativeChmod(final String name, int mode); public static native void nativeChdir(final String dir); }