UserPreferences.java 10 KB

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