UserPreferences.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package com.xugame.gameconsole.preferences;
  2. import android.annotation.TargetApi;
  3. import android.content.Context;
  4. import android.content.SharedPreferences;
  5. import android.content.pm.PackageManager;
  6. import android.media.AudioManager;
  7. import android.media.AudioTrack;
  8. import android.os.Build;
  9. import android.preference.PreferenceManager;
  10. import android.util.Log;
  11. import com.xugame.gameconsole.util.DebugUtil;
  12. import java.io.File;
  13. import java.io.IOException;
  14. public class UserPreferences {
  15. // Logging tag.
  16. private static final String TAG = "UserPreferences";
  17. // Disallow explicit instantiation.
  18. private UserPreferences() {
  19. }
  20. /**
  21. * Retrieves the path to the default location of the libretro config.
  22. *
  23. * @param ctx the current {@link Context}
  24. * @return the path to the default location of the libretro config.
  25. */
  26. public static String getDefaultConfigPath(Context ctx) {
  27. // Internal/External storage dirs.
  28. final String internal = ctx.getFilesDir().getAbsolutePath();
  29. String external = null;
  30. // Get the App's external storage folder
  31. final String state = android.os.Environment.getExternalStorageState();
  32. if (android.os.Environment.MEDIA_MOUNTED.equals(state)) {
  33. File extsd = ctx.getExternalFilesDir(null);
  34. external = extsd.getAbsolutePath();
  35. }
  36. // Native library directory and data directory for this front-end.
  37. final String dataDir = ctx.getApplicationInfo().dataDir;
  38. final String coreDir = dataDir + "/cores/";
  39. // Get libretro name and path
  40. final SharedPreferences prefs = getPreferences(ctx);
  41. final String libretro_path = prefs.getString("libretro_path", coreDir);
  42. // Check if global config is being used. Return true upon failure.
  43. final boolean globalConfigEnabled = prefs.getBoolean("global_config_enable", true);
  44. String append_path;
  45. // If we aren't using the global config.
  46. if (!globalConfigEnabled && !libretro_path.equals(coreDir)) {
  47. String sanitized_name = sanitizeLibretroPath(libretro_path);
  48. append_path = File.separator + sanitized_name + ".cfg";
  49. } else // Using global config.
  50. {
  51. append_path = File.separator + "retroarch.cfg";
  52. }
  53. if (external != null) {
  54. String confPath = external + append_path;
  55. if (new File(confPath).exists())
  56. return confPath;
  57. } else if (internal != null) {
  58. String confPath = internal + append_path;
  59. if (new File(confPath).exists())
  60. return confPath;
  61. } else {
  62. String confPath = "/mnt/extsd" + append_path;
  63. if (new File(confPath).exists())
  64. return confPath;
  65. }
  66. // Config file does not exist. Create empty one.
  67. // emergency fallback
  68. String new_path = "/mnt/sd" + append_path;
  69. if (external != null)
  70. new_path = external + append_path;
  71. else if (internal != null)
  72. new_path = internal + append_path;
  73. else if (dataDir != null)
  74. new_path = dataDir + append_path;
  75. try {
  76. new File(new_path).createNewFile();
  77. } catch (IOException e) {
  78. Log.e(TAG, "Failed to create config file to: " + new_path);
  79. }
  80. return new_path;
  81. }
  82. /**
  83. * Updates the libretro configuration file
  84. * with new values if settings have changed.
  85. *
  86. * @param ctx the current {@link Context}.
  87. */
  88. public static void updateConfigFile(Context ctx, String systemDir) {
  89. String path = getDefaultConfigPath(ctx);
  90. ConfigFile config = new ConfigFile(path);
  91. Log.i(TAG, "Writing config to: " + path);
  92. final String dataDir = ctx.getApplicationInfo().dataDir;
  93. final String coreDir = dataDir + "/cores/";
  94. final SharedPreferences prefs = getPreferences(ctx);
  95. config.setString("libretro_directory", coreDir);
  96. //设置没有触摸屏
  97. config.setString("input_overlay_enable", "false");
  98. config.setBoolean("log_verbosity", true);
  99. config.setBoolean("fps_show", true);
  100. config.setString("system_directory", systemDir);//20230829添加system路径设置
  101. DebugUtil.i(TAG,"write system dir:"+systemDir);
  102. config.setInt("input_player1_analog_dpad_mode", 1);
  103. config.setInt("frontend_log_level", 1);
  104. config.setInt("libretro_log_level", 1);
  105. int samplingRate = getOptimalSamplingRate(ctx);
  106. if (samplingRate != -1) {
  107. config.setInt("audio_out_rate", samplingRate);
  108. }
  109. try {
  110. int version = ctx.getPackageManager().
  111. getPackageInfo(ctx.getPackageName(), 0).versionCode;
  112. final String dst_path = dataDir;
  113. final String dst_path_subdir = "assets";
  114. Log.i(TAG, "dst dir is: " + dst_path);
  115. Log.i(TAG, "dst subdir is: " + dst_path_subdir);
  116. config.setString("bundle_assets_src_path", ctx.getApplicationInfo().sourceDir);
  117. DebugUtil.i(TAG, "source=" + ctx.getApplicationInfo().sourceDir);
  118. DebugUtil.i(TAG, "versionCode=" + version);
  119. config.setString("bundle_assets_dst_path", dst_path);
  120. config.setString("bundle_assets_dst_path_subdir", dst_path_subdir);
  121. config.setInt("bundle_assets_extract_version_current", version);
  122. } catch (PackageManager.NameNotFoundException ignored) {
  123. }
  124. // Refactor this entire mess and make this usable for per-core config
  125. if (Build.VERSION.SDK_INT >= 17 && prefs.getBoolean("audio_latency_auto", true)) {
  126. int bufferSize = getLowLatencyBufferSize(ctx);
  127. if (bufferSize != -1) {
  128. config.setInt("audio_block_frames", bufferSize);
  129. }
  130. }
  131. try {
  132. config.write(path);
  133. } catch (IOException e) {
  134. Log.e(TAG, "Failed to save config file to: " + path);
  135. }
  136. }
  137. private static void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
  138. if (cfg.keyExists(key))
  139. edit.putString(key, cfg.getString(key));
  140. else
  141. edit.remove(key);
  142. }
  143. private static void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
  144. if (cfg.keyExists(key))
  145. edit.putBoolean(key, cfg.getBoolean(key));
  146. else
  147. edit.remove(key);
  148. }
  149. private static void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
  150. if (cfg.keyExists(key))
  151. edit.putFloat(key, (float) cfg.getDouble(key));
  152. else
  153. edit.remove(key);
  154. }
  155. /*
  156. private static void readbackFloat(ConfigFile cfg, SharedPreferences.Editor edit, String key)
  157. {
  158. if (cfg.keyExists(key))
  159. edit.putFloat(key, cfg.getFloat(key));
  160. else
  161. edit.remove(key);
  162. }
  163. */
  164. /**
  165. private static void readbackInt(ConfigFile cfg, SharedPreferences.Editor edit, String key)
  166. {
  167. if (cfg.keyExists(key))
  168. edit.putInt(key, cfg.getInt(key));
  169. else
  170. edit.remove(key);
  171. }
  172. */
  173. /**
  174. * Sanitizes a libretro core path.
  175. *
  176. * @param path The path to the libretro core.
  177. * @return the sanitized libretro path.
  178. */
  179. private static String sanitizeLibretroPath(String path) {
  180. String sanitized_name = path.substring(
  181. path.lastIndexOf('/') + 1,
  182. path.lastIndexOf('.'));
  183. sanitized_name = sanitized_name.replace("neon", "");
  184. sanitized_name = sanitized_name.replace("libretro_", "");
  185. return sanitized_name;
  186. }
  187. /**
  188. * Gets a {@link SharedPreferences} instance containing current settings.
  189. *
  190. * @param ctx the current {@link Context}.
  191. * @return A SharedPreference instance containing current settings.
  192. */
  193. public static SharedPreferences getPreferences(Context ctx) {
  194. return PreferenceManager.getDefaultSharedPreferences(ctx);
  195. }
  196. /**
  197. * Gets the optimal sampling rate for low-latency audio playback.
  198. *
  199. * @param ctx the current {@link Context}.
  200. * @return the optimal sampling rate for low-latency audio playback in Hz.
  201. */
  202. @TargetApi(17)
  203. private static int getLowLatencyOptimalSamplingRate(Context ctx) {
  204. AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
  205. String value = manager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
  206. if (value == null || value.isEmpty()) {
  207. return -1;
  208. }
  209. return Integer.parseInt(value);
  210. }
  211. /**
  212. * Gets the optimal buffer size for low-latency audio playback.
  213. *
  214. * @param ctx the current {@link Context}.
  215. * @return the optimal output buffer size in decimal PCM frames.
  216. */
  217. @TargetApi(17)
  218. private static int getLowLatencyBufferSize(Context ctx) {
  219. AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
  220. String value = manager.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER);
  221. if (value == null || value.isEmpty()) {
  222. return -1;
  223. }
  224. int buffersize = Integer.parseInt(value);
  225. Log.i(TAG, "Queried ideal buffer size (frames): " + buffersize);
  226. return buffersize;
  227. }
  228. /**
  229. * Gets the optimal audio sampling rate.
  230. * <p>
  231. * On Android 4.2+ devices this will retrieve the optimal low-latency sampling rate,
  232. * since Android 4.2 adds support for low latency audio in general.
  233. * <p>
  234. * On other devices, it simply returns the regular optimal sampling rate
  235. * as returned by the hardware.
  236. *
  237. * @param ctx The current {@link Context}.
  238. * @return the optimal audio sampling rate in Hz.
  239. */
  240. private static int getOptimalSamplingRate(Context ctx) {
  241. int ret;
  242. if (Build.VERSION.SDK_INT >= 17)
  243. ret = getLowLatencyOptimalSamplingRate(ctx);
  244. else
  245. ret = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
  246. Log.i(TAG, "Using sampling rate: " + ret + " Hz");
  247. return ret;
  248. }
  249. }