AppLogger.kt 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. package com.flashlink.vpn
  2. import android.annotation.SuppressLint
  3. import android.content.Context
  4. import android.os.SystemClock
  5. import org.json.JSONObject
  6. import java.io.File
  7. import java.util.concurrent.locks.ReentrantLock
  8. import kotlin.concurrent.withLock
  9. /**
  10. * 应用日志记录器 - Kotlin版本
  11. * 优化点:
  12. * 1. 优化文件读写操作,使用缓冲区
  13. * 2. 减少锁持有时间
  14. * 3. 优化JSON操作
  15. * 4. 改进异常处理和资源管理
  16. */
  17. class AppLogger private constructor(context: Context) {
  18. private val context: Context = context.applicationContext
  19. // 全局文件锁,防止多个方法同时读写文件
  20. private val fileLock = ReentrantLock()
  21. companion object {
  22. private const val LOG_FOLDER = "boost_logs"
  23. private const val CURRENT_APP_LOG_FILE = "app.json"
  24. private const val BUFFER_SIZE = 8192
  25. @SuppressLint("StaticFieldLeak")
  26. @Volatile
  27. private var instance: AppLogger? = null
  28. fun getInstance(context: Context): AppLogger {
  29. return instance ?: synchronized(this) {
  30. instance ?: AppLogger(context).also { instance = it }
  31. }
  32. }
  33. }
  34. /**
  35. * 获取app.json文件路径
  36. */
  37. private fun getAppLogFile(): File {
  38. val logDir = File(context.filesDir, LOG_FOLDER)
  39. if (!logDir.exists()) {
  40. logDir.mkdirs()
  41. }
  42. return File(logDir, CURRENT_APP_LOG_FILE)
  43. }
  44. /**
  45. * 读取app.json文件内容 - 优化版本
  46. * 使用缓冲区提高读取效率
  47. */
  48. private fun readAppJsonFile(): JSONObject {
  49. val appLogFile = getAppLogFile()
  50. if (!appLogFile.exists()) {
  51. throw RuntimeException("app.json file does not exist")
  52. }
  53. val content = appLogFile.bufferedReader(bufferSize = BUFFER_SIZE).use { it.readText() }
  54. if (content.isEmpty()) {
  55. throw RuntimeException("app.json file is empty")
  56. }
  57. return JSONObject(content)
  58. }
  59. /**
  60. * 写入app.json文件内容 - 优化版本
  61. */
  62. private fun writeAppJsonFile(appData: JSONObject) {
  63. val appLogFile = getAppLogFile()
  64. appLogFile.bufferedWriter().use { writer ->
  65. writer.write(appData.toString(2))
  66. writer.flush()
  67. }
  68. }
  69. /**
  70. * 安全地更新app.json文件 - 优化版本
  71. * 减少锁持有时间
  72. */
  73. private inline fun safeUpdateAppJson(operationName: String, crossinline update: (JSONObject) -> Unit) {
  74. fileLock.withLock {
  75. try {
  76. val appData = readAppJsonFile()
  77. val sessionInfo = appData.optJSONObject("sessionInfo")
  78. if (sessionInfo == null) {
  79. VLog.w(TAG, "$operationName sessionInfo not found in app.json")
  80. return
  81. }
  82. // 执行具体的更新操作
  83. try {
  84. update(sessionInfo)
  85. } catch (e: Exception) {
  86. VLog.e(TAG, "$operationName Error in update callback: ${e.message}")
  87. return
  88. }
  89. // 保存更新后的文件
  90. writeAppJsonFile(appData)
  91. VLog.i(TAG, "$operationName successfully updated app.json")
  92. } catch (e: Exception) {
  93. VLog.e(TAG, "$operationName Error updating app.json: ${e.message}")
  94. }
  95. }
  96. }
  97. /**
  98. * 安全地更新JSONObject - 优化版本
  99. */
  100. private fun safePut(jsonObject: JSONObject?, key: String, value: Any?, operationName: String) {
  101. if (jsonObject == null) {
  102. VLog.e(TAG, "$operationName JSONObject is null, cannot put key: $key")
  103. return
  104. }
  105. try {
  106. jsonObject.put(key, value)
  107. } catch (e: Exception) {
  108. VLog.e(TAG, "$operationName Failed to put key '$key' with value '$value': ${e.message}")
  109. }
  110. }
  111. /**
  112. * 更新app.json文件中的boostStopTime、boostDuration
  113. * 通过 app.json 中的 boostStartTime 和 elapsedRealtime 计算
  114. * boostStopTime = SystemClock.elapsedRealtime() - elapsedRealtime + boostStartTime
  115. */
  116. fun updateAppJsonStopTime() {
  117. safeUpdateAppJson("updateAppJsonStopTime") { sessionInfo ->
  118. val boostStartTime = sessionInfo.optLong("boostStartTime", 0)
  119. val boostSuccessTime = sessionInfo.optLong("boostSuccessTime", 0)
  120. val savedElapsedRealtime = sessionInfo.optLong("elapsedRealtime", 0)
  121. if (boostStartTime == 0L) {
  122. throw RuntimeException("boostStartTime not found or invalid in app.json")
  123. }
  124. // 计算 boostStopTime
  125. var boostStopTime = if (savedElapsedRealtime != 0L) {
  126. // 使用保存的 elapsedRealtime 计算精确的停止时间
  127. SystemClock.elapsedRealtime() - savedElapsedRealtime + boostStartTime
  128. } else {
  129. // 降级使用系统时间
  130. System.currentTimeMillis()
  131. }
  132. // 计算 boostDuration
  133. val boostDuration: Long
  134. if (boostSuccessTime != 0L) {
  135. if (boostStopTime < boostSuccessTime) {
  136. boostStopTime = boostSuccessTime
  137. }
  138. boostDuration = (boostStopTime - boostSuccessTime) / 1000
  139. } else {
  140. if (boostStopTime < boostStartTime) {
  141. boostStopTime = boostStartTime
  142. }
  143. boostDuration = (boostStopTime - boostStartTime) / 1000
  144. }
  145. safePut(sessionInfo, "boostStopTime", boostStopTime, "updateAppJsonStopTime")
  146. safePut(sessionInfo, "boostDuration", boostDuration, "updateAppJsonStopTime")
  147. }
  148. }
  149. /**
  150. * 更新app.json文件中的success、errorCode、boostSuccessTime
  151. * 通过 app.json 中的 boostStartTime 和 elapsedRealtime 计算
  152. * boostSuccessTime = SystemClock.elapsedRealtime() - elapsedRealtime + boostStartTime
  153. */
  154. fun updateAppJsonStatusInfo(success: Boolean, errorCode: Long) {
  155. safeUpdateAppJson("updateAppJsonStatusInfo") { sessionInfo ->
  156. safePut(sessionInfo, "success", success, "updateAppJsonStatusInfo")
  157. safePut(sessionInfo, "errorCode", errorCode, "updateAppJsonStatusInfo")
  158. val boostStartTime = sessionInfo.optLong("boostStartTime", 0)
  159. val savedElapsedRealtime = sessionInfo.optLong("elapsedRealtime", 0)
  160. if (boostStartTime == 0L) {
  161. throw RuntimeException("boostStartTime not found or invalid in app.json")
  162. }
  163. // 计算 boostSuccessTime
  164. var boostSuccessTime = if (savedElapsedRealtime != 0L) {
  165. // 使用保存的 elapsedRealtime 计算精确的成功时间
  166. SystemClock.elapsedRealtime() - savedElapsedRealtime + boostStartTime
  167. } else {
  168. // 降级使用系统时间
  169. System.currentTimeMillis()
  170. }
  171. if (success) {
  172. // 校验时间合理性:不能早于开始时间,也不能晚于开始时间超过3分钟
  173. if (boostSuccessTime < boostStartTime || boostSuccessTime - 180000 > boostStartTime) {
  174. boostSuccessTime = boostStartTime
  175. }
  176. safePut(sessionInfo, "boostSuccessTime", boostSuccessTime, "updateAppJsonStatusInfo")
  177. safePut(sessionInfo, "boostStopTime", boostSuccessTime, "updateAppJsonStatusInfo")
  178. safePut(sessionInfo, "boostDuration", 0, "updateAppJsonStatusInfo")
  179. }
  180. }
  181. }
  182. /**
  183. * 更新app.json文件中的boostDownloadDuration - 优化版本
  184. */
  185. fun updateAppJsonDownloadDuration(downloadDuration: Long) {
  186. safeUpdateAppJson("updateAppJsonDownloadDuration") { sessionInfo ->
  187. safePut(sessionInfo, "boostDownloadDuration", downloadDuration, "updateAppJsonDownloadDuration")
  188. }
  189. }
  190. /**
  191. * 更新app.json文件中的errorCode - 优化版本
  192. */
  193. fun updateAppJsonCode(code: Int) {
  194. safeUpdateAppJson("updateAppJsonCode") { sessionInfo ->
  195. safePut(sessionInfo, "errorCode", code, "updateAppJsonCode")
  196. }
  197. }
  198. }
  199. private const val TAG = "AppLogger"