From 8e37bca0c325570dcf22d75fe460fced2890de83 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Fri, 18 Sep 2026 16:20:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(network):=20=E4=BF=AE=E5=A4=8D=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E8=AF=B7=E6=B1=82=E6=8B=A6=E6=88=AA=E5=99=A8=E5=8E=BB?= =?UTF-8?q?=E9=87=8D=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在请求发出前拦截重复请求,复用进行中请求的结果, 并在完成后保留 500ms 结果窗口;同时新增 DX11、G12NL 平台标识与构建变体,更新版本号至 1.6.0914。 --- build.gradle | 69 ++-- iconloaderlib/build.gradle | 4 + keystore/MT6789.keystore | Bin 0 -> 2345 bytes .../os/network/NetInterfaceManager.java | 4 + .../interceptor/RepeatRequestInterceptor.java | 313 +++++++++++++++--- src/com/aoleyun/os/uiuiutils/JgyUtils.java | 15 + 6 files changed, 329 insertions(+), 76 deletions(-) create mode 100644 keystore/MT6789.keystore diff --git a/build.gradle b/build.gradle index ed39c4e..b18fe79 100644 --- a/build.gradle +++ b/build.gradle @@ -75,8 +75,8 @@ android { minSdkVersion 26 targetSdkVersion 28 - versionCode 206 - versionName "1.6.0731" + versionCode 209 + versionName "1.6.0914" ndk { //选择要添加的对应 cpu 类型的 .so 库。 @@ -256,13 +256,36 @@ android { v1SigningEnabled true v2SigningEnabled true } + + MT6789 { + storeFile file("keystore/MT6789.keystore") + storePassword "123456" + keyAlias "mt6789" + keyPassword "123456" + v1SigningEnabled true + v2SigningEnabled true + } } buildTypes { + G12NLDebug.initWith(debug) + G12NLDebug { + buildConfigField "String", "platform", '"G12NL"' + versionNameSuffix "_debug" + debuggable true + signingConfig signingConfigs.MT6789 + } + + G12NLRelease.initWith(release) + G12NLRelease { + buildConfigField "String", "platform", '"G12NL"' + signingConfig signingConfigs.MT6789 + } + DX11Debug.initWith(debug) DX11Debug { buildConfigField "String", "platform", '"DX11"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.DX11 } @@ -276,7 +299,7 @@ android { G122Debug.initWith(debug) G122Debug { buildConfigField "String", "platform", '"MT6765"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.G122 } @@ -290,7 +313,7 @@ android { QualcommDebug.initWith(debug) QualcommDebug { buildConfigField "String", "platform", '"QualcommA"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.zhanRui } @@ -304,7 +327,7 @@ android { G128TDebug.initWith(debug) G128TDebug { buildConfigField "String", "platform", '"G128T"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.G128T } @@ -318,7 +341,7 @@ android { QZ15Debug.initWith(debug) QZ15Debug { buildConfigField "String", "platform", '"QZA15"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.U1302 } @@ -331,7 +354,7 @@ android { seewoDebug.initWith(debug) seewoDebug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.seewo buildConfigField "String", "platform", '"seewo"' @@ -345,7 +368,7 @@ android { P50Debug.initWith(debug) P50Debug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.P50 buildConfigField "String", "platform", '"P50TD"' @@ -359,7 +382,7 @@ android { T40AirDebug.initWith(debug) T40AirDebug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.T40Air buildConfigField "String", "platform", '"HL500"' @@ -373,7 +396,7 @@ android { // AiUduDebug.initWith(debug) // AiUduDebug { -// versionNameSuffix "-debug" +// versionNameSuffix "_debug" // debuggable true // signingConfig signingConfigs.G10P // buildConfigField "String", "platform", '"AUDG104"' @@ -387,7 +410,7 @@ android { Huaruian8768Debug.initWith(debug) Huaruian8768Debug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.Huaruian8768 buildConfigField "String", "platform", '"MT8768"' @@ -401,7 +424,7 @@ android { G11Debug.initWith(debug) G11Debug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.G11Userdebug buildConfigField "String", "platform", '"MTKG11"' @@ -415,7 +438,7 @@ android { YXPD1Debug.initWith(debug) YXPD1Debug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.G10P buildConfigField "String", "platform", '"YXPD1"' @@ -429,7 +452,7 @@ android { c2Debug.initWith(debug) c2Debug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.teclast8183 buildConfigField "String", "platform", '"MTK8183"' @@ -443,7 +466,7 @@ android { G10PDebug.initWith(debug) G10PDebug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.G10P buildConfigField "String", "platform", '"G10P"' @@ -458,7 +481,7 @@ android { G104Debug.initWith(debug) G104Debug { buildConfigField "String", "platform", '"MTK11"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.G10P } @@ -471,7 +494,7 @@ android { zhanRuiDebug.initWith(debug) zhanRuiDebug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" buildConfigField "String", "platform", '"ZhanRui"' debuggable true signingConfig signingConfigs.zhanRui @@ -486,7 +509,7 @@ android { //userdebug rom使用这个版本 zhanRuiUserdebug.initWith(zhanRuiDebug) zhanRuiUserdebug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" buildConfigField "String", "platform", '"ZhanRui"' debuggable true signingConfig signingConfigs.zhanRuiUserdebug @@ -494,7 +517,7 @@ android { zhanRui12Debug.initWith(debug) zhanRui12Debug { - versionNameSuffix "-debug" + versionNameSuffix "_debug" buildConfigField "String", "platform", '"AH6016"' debuggable true signingConfig signingConfigs.zhanRui12 @@ -509,7 +532,7 @@ android { TeclastP20SDebug.initWith(debug) TeclastP20SDebug { debuggable true - versionNameSuffix "-debug" + versionNameSuffix "_debug" buildConfigField "String", "platform", '"P20S"' signingConfig signingConfigs.TeclastP20S } @@ -523,7 +546,7 @@ android { zhanruiG10ZDebug.initWith(debug) zhanruiG10ZDebug { buildConfigField "String", "platform", '"ZR6016"' - versionNameSuffix "-debug" + versionNameSuffix "_debug" debuggable true signingConfig signingConfigs.zhanruiG10Z } @@ -537,7 +560,7 @@ android { debug { buildConfigField "String", "platform", '"MTK"' debuggable true - versionNameSuffix "-debug" + versionNameSuffix "_debug" minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' signingConfig signingConfigs.mtk diff --git a/iconloaderlib/build.gradle b/iconloaderlib/build.gradle index cf92c89..d7ffc18 100644 --- a/iconloaderlib/build.gradle +++ b/iconloaderlib/build.gradle @@ -15,6 +15,10 @@ android { } buildTypes { + MX11Debug {} + MX11Release {} + G12NLDebug {} + G12NLRelease {} DX11Debug {} DX11Release {} G122Debug {} diff --git a/keystore/MT6789.keystore b/keystore/MT6789.keystore new file mode 100644 index 0000000000000000000000000000000000000000..33a16e4b947589e29b32194ec14098ce407184aa GIT binary patch literal 2345 zcmd5-={wYI8=l|H7={^Q%9cUOzVsVpiA0gfzGcsnVMelqh-w;BmdH}sw=9W5Dr9U~ zCQD^s6OW4Q*@emW@*MB`9?ysO4|qRZAI|eW@8iCX^S+Mr+MVB>hd?0E{Q~|jgr~of zvWn_HOm>i|)r3HpU?3H~2eKnrr4axekb-go022gGh0nFd{WM8rzW;qOOEBw!-Ebve za*cKaz`S57-bKI|;4Z!$vmZLD5%ZFRb5?jtQW4XYI@~s0Dd3tl{YFjWg}6sVvte(H z^%YHj>kN*R@wl7brY7Cr?k#>Y)#=d=Ckqt0L$=x_%9L7AGZM*z<|2L=Wj>;s9)$ez0+^ncd93zrfI)gQ(ADdlF@lt zj|*&9^VjJ*dki1+W?S%bj<3W7Nyr##4OwY}l#dZwkf{d7^?vC^uU{d`MM^d*td}?C zuHJ3CVG!DY)r^@end=bz*bc>2mx`i3BJ@SwgHN8u`ZQ4R!ZJ2waSey}A7nz!X#Hi~ zuI!zy#y!_Id-Zg$u$Mpb!<^*iV<&7d3@jBhgL{)G3zFCeLI!S{HzuY?(M7+^-szSc z$KIQ6e-(3K!)Lqly9O&tDhbLqqf74+N^7WhB3&!=7NIx21mDBSh&&9z4k&e1AM)@}98Eqw@&%585YUvv3G2K>c{hC`=*?3b=cja_BxU#ELFK0WnHWU842$p%s zcGEwJL8}W)x9-l%`gOzeT&5J)i#STJY_}F%PPm%u2oP{-CY3yJkH^s0rzKyXizatn z^!u!vX?pCuhlaAQSav#k9dq%i?r+<~v>S+E+{|?cLI$N58~jn ztxgZZqTIyl9Hp6$)RuRxbKL#HBS*@upYpKUF4dhlX+&W7l}OGelMwCZ zxDZesEmu93u&stfCZEQC5~<8SS@wQ)j?=nLF?{jneCjR_qgH$K%WY~>wZQ4wTwY5x zxt;AM2)N9eY<;{u_OoxS14Z!RxQ%(z(xDni<_xL34hKgRUt6}6dF*3fzor+i(tL)p z<8bl!BmJAH=6&o}W*@;US7hd}(DN>k` z4j&7n=PP?Y0cF!ByiR#Fl~1-+>7v1aSR$YA+sR43N(1bzq3Q{_rt924htj=9lNzIy z_A*ACO8S^?d1)Ui_CaQ{B(e|`{T^^_=?URfSlz`D97+XAe?Fk`IU!ziq?!H(U&jE) zN(26Gj*8-t5yCOYR4ch6SQFw$(H4Dfu)HN;A?=U%vL9envNDya$wV}LSpRo4GFi)= z0{4><_6?-MhCwQno&|#fP$&{|ziiUCz_x_~q7g``Fnrhs8UWasAYjNn92GXprpy!BB95tEV?k7!>^Pqey_8^MKU!JhLKUi?FkC8^zhhujfCB|oKUenJuX z<{htpp!u2CExtONOoo&OmEL3()6Ml~&w*IVPm1cSjP->|*7$8b3;8&G?@oPsyw!l?=Rp(wtGtO|<<( z*|ndx+ma>a^5?8_>a7G=ol78_f3z{~A@R1lhge{vbPr!}SykV8hk+cO(cVJ8yId4A zbs#!^sBmw5}7XH>#Y6LYVm$VyYcyC6x*d&D_#9;+YL68Zo(S9LG@hhMoKAHQhl8X z;3_iGtlE?-gtgIu*1Q^-702w(ua1nOKcTu%BS^f(N}|=e8$CO)QNyE728+jr%oGJ| ztSIz}iSCT*Aex@t-KpDaS4H@@7`rR+73Q}e6UJqTQN%MMZ%Ri#%gQTm@NA{Ap+9&J VVheaDts-AKTGh=~C22ji{TCHX{K5bL literal 0 HcmV?d00001 diff --git a/src/com/aoleyun/os/network/NetInterfaceManager.java b/src/com/aoleyun/os/network/NetInterfaceManager.java index 438e55f..cfafb5d 100644 --- a/src/com/aoleyun/os/network/NetInterfaceManager.java +++ b/src/com/aoleyun/os/network/NetInterfaceManager.java @@ -208,6 +208,10 @@ public class NetInterfaceManager { set.add(JgyUtils.AUDG104Tag); } else if (platform == JgyUtils.seewoPlatform) { set.add(JgyUtils.seewoTag); + } else if (platform == JgyUtils.DX11Platform) { + set.add(JgyUtils.DX11_TAG); + } else if (platform == JgyUtils.G12NLPlatform) { + set.add(JgyUtils.G12NL_TAG); } } }); diff --git a/src/com/aoleyun/os/network/interceptor/RepeatRequestInterceptor.java b/src/com/aoleyun/os/network/interceptor/RepeatRequestInterceptor.java index 1949303..c7f7612 100644 --- a/src/com/aoleyun/os/network/interceptor/RepeatRequestInterceptor.java +++ b/src/com/aoleyun/os/network/interceptor/RepeatRequestInterceptor.java @@ -8,9 +8,13 @@ import com.aoleyun.os.uiuiutils.MD5Util; import org.jetbrains.annotations.NotNull; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import okhttp3.Headers; import okhttp3.Interceptor; +import okhttp3.MediaType; import okhttp3.Protocol; import okhttp3.Request; import okhttp3.RequestBody; @@ -19,89 +23,292 @@ import okhttp3.ResponseBody; import okio.Buffer; /** - * v1.0 2022-07-15 16:16:52 + * 重复请求拦截器。 + * + *

原实现是在 {@code chain.proceed()} 之后才判断是否为重复请求,此时请求早已发到服务器, + * 只能丢弃返回结果,所以服务端依然会收到两次(甚至多次)请求;并且记录在 finally 中立即删除, + * 去重窗口几乎为零,重复请求根本拦不住。

+ * + *

优化后的策略:

+ *
    + *
  • 发请求之前先判断是否已经有相同请求:有则等待它的结果并复用,不再访问服务器;
  • + *
  • 请求完成后在 {@link #REUSE_WINDOW_MS} 内保留结果,短时间内相同的请求直接复用结果;
  • + *
  • 复用时使用真实的状态码、响应头和响应体,调用方无感知(原来的空 {@link Response} 会让 + * 解析层直接抛异常);
  • + *
  • 无响应体或响应体过大(超过 {@link #MAX_DEDUP_BODY_BYTES})的请求不参与去重,直接透传, + * 避免占用大量内存。
  • + *
+ * + *

v1.0 2022-07-15 16:16:52

*/ public class RepeatRequestInterceptor implements Interceptor { - private static final String TAG = RepeatRequestInterceptor.class.getSimpleName(); + private static final String TAG = "RepeatRequestInterceptor"; - private final ConcurrentHashMap requestIdsMap = new ConcurrentHashMap<>(); - public static final String REPEAT_REQUEST_PROTOCOL = "OKHTTP_REPEAT_REQUEST_PROTOCOL"; + /** + * 等待进行中请求返回结果的最长时间,超时后本次请求自己访问服务器。 + * 需要大于 OkHttpClient 的超时时间(当前为 5 秒)。 + */ + private static final long WAIT_IN_FLIGHT_TIMEOUT_MS = 10_000L; + + /** + * 请求完成后结果保留的时间。在该时间内收到相同请求,直接复用结果,不再访问服务器。 + * 需要小于业务侧的刷新间隔(ConnectMode 最小为 1 分钟)。 + */ + private static final long REUSE_WINDOW_MS = 500L; + + /** 超过该大小的响应体不参与去重(直接透传),避免内存占用 */ + private static final long MAX_DEDUP_BODY_BYTES = 1024 * 1024L; + + /** 参与去重 key 计算的请求体最大字节数 */ + private static final int MAX_BODY_BYTES_FOR_KEY = 8 * 1024; + + /** 日志中请求体、响应体的最大长度 */ + private static final int MAX_LOG_BODY_LENGTH = 10240; + + private final ConcurrentHashMap recordMap = new ConcurrentHashMap<>(); @NotNull @Override public Response intercept(@NotNull Chain chain) throws IOException { Request request = chain.request(); - Response response = chain.proceed(request); - ResponseBody responseBody = response.body(); + String bodyText = requestBodyToString(request.body()); + String requestKey = buildRequestKey(request, bodyText); - //会消费请求,导致请求多次 - String content = responseBody.string(); -// Response copy = response.newBuilder().body(responseBody).build(); - ResponseBody copy = ResponseBody.create(responseBody.contentType(), content); - if (BuildConfig.DEBUG) { - Log.e(TAG, "请求体返回:| Response: " + request.url().encodedPath() + "\t body: " + content); + clearExpiredRecords(); + + RepeatRecord record = acquireRecord(requestKey); + if (record == null) { + // 已有相同请求,但没有拿到可用结果(上一次失败、超时或结果过大),本次请求直接访问服务器 + return chain.proceed(request); } - //相同的请求 - String requestKey = MD5Util.getUpperMD5Str(request.method() + request.url().toString() + requestBodyToString(request.body())); - long time = System.currentTimeMillis();//请求时间 + if (!record.isOwner()) { + // 复用相同请求的结果:服务端只会收到一次请求 + log("复用请求:", requestKey, request, bodyText); + return record.newResponse(request); + } + + log("注册请求:", requestKey, request, bodyText); try { - if (requestIdsMap.size() > 0 && requestIdsMap.containsKey(requestKey)) { - log("重复请求:", requestKey, request); - //下面这行写了不会抛出onerror -// chain.call().cancel(); - return new Response.Builder() - .protocol(Protocol.get(REPEAT_REQUEST_PROTOCOL)) - .request(request) //multi thread - .build(); + Response response = chain.proceed(request); + ResponseBody responseBody = response.body(); + if (responseBody == null || responseBody.contentLength() > MAX_DEDUP_BODY_BYTES) { + // 无响应体或响应体过大:不消费 body,也不参与去重,直接透传 + logResponse(request, null); + return response; } - requestIdsMap.put(requestKey, time); - log("注册请求:", requestKey, request); -// RepeatRequestInterceptor.Builder builder = request.newBuilder(); -// builder.addHeader("header", jsonObject.toString()); - return response.newBuilder().body(copy).build(); + + // body 只能被消费一次,读出来之后重建一个新的 body 返回给调用方 + MediaType contentType = responseBody.contentType(); + byte[] bytes = responseBody.bytes(); + logResponse(request, bytes); + if (bytes.length <= MAX_DEDUP_BODY_BYTES) { + // 缓存结果,供等待中的、以及短时间内后续的相同请求复用 + record.complete(response, bytes, contentType); + } + return response.newBuilder().body(ResponseBody.create(contentType, bytes)).build(); } catch (IOException e) { Log.e(TAG, "intercept: " + e.getMessage()); throw e; } finally { - if (requestIdsMap.containsKey(requestKey) && requestIdsMap.containsValue(time)) {//请求任务完成删除map中的数据 - requestIdsMap.remove(requestKey); - log("移除请求:", requestKey, request); + // 兜底:无论成功、失败还是异常,都结束记录,避免等待中的相同请求被一直阻塞 + record.finish(); + } + } + + /** + * 获取请求对应的去重记录。 + * + * @return 返回记录表示本次请求要么成为 owner 去访问服务器、要么直接复用已有结果; + * 返回 null 表示已有相同请求但结果不可用,本次请求自己访问服务器(不参与去重) + */ + private RepeatRecord acquireRecord(String requestKey) { + while (true) { + long now = System.currentTimeMillis(); + RepeatRecord record = recordMap.get(requestKey); + if (record == null) { + RepeatRecord created = new RepeatRecord(); + if (recordMap.putIfAbsent(requestKey, created) == null) { + created.markOwner(); + return created; + } + continue;// 其他线程抢先注册,重新判断 + } + if (record.isExpired(now)) { + // 结果已过期,替换为本次请求的记录并成为 owner + RepeatRecord created = new RepeatRecord(); + if (recordMap.replace(requestKey, record, created)) { + created.markOwner(); + return created; + } + continue; + } + // 已有相同请求:等待它的结果,拿到结果直接复用 + if (record.await(WAIT_IN_FLIGHT_TIMEOUT_MS)) { + return record; + } + return null; + } + } + + /** 清理过期记录,释放其缓存的响应体 */ + private void clearExpiredRecords() { + if (recordMap.isEmpty()) { + return; + } + long now = System.currentTimeMillis(); + for (Map.Entry entry : recordMap.entrySet()) { + RepeatRecord record = entry.getValue(); + if (record.isExpired(now)) { + recordMap.remove(entry.getKey(), record); } } } - private void log(String action, String requestKey, Request request) { + private static String buildRequestKey(Request request, String bodyText) { + return MD5Util.getUpperMD5Str(request.method() + "|" + request.url() + "|" + bodyText); + } + + /** + * 请求体转字符串,用于计算去重 key 和输出日志。 + * 只读取可重复读写的请求体,避免把一次性(one-shot)请求体读空。 + */ + private static String requestBodyToString(RequestBody body) { + if (body == null || body.isOneShot()) { + return ""; + } + try { + Buffer buffer = new Buffer(); + body.writeTo(buffer); + long size = buffer.size(); + if (size > MAX_BODY_BYTES_FOR_KEY) { + // 请求体过大时只取前一部分参与去重,避免不必要的内存开销 + return size + ":" + buffer.readByteString(MAX_BODY_BYTES_FOR_KEY).hex(); + } + return buffer.readUtf8(); + } catch (Exception e) { + return ""; + } + } + + private static void log(String action, String requestKey, Request request, String bodyText) { if (BuildConfig.DEBUG) { - Log.e("REPEAT-REQUEST", action + requestKey + " Method @" + request.method() + " --- " + " URL = " + request.url().encodedPath() + "\t" + bodyToString(request)); + String body = bodyText.length() > MAX_LOG_BODY_LENGTH ? "-too long" : bodyText; + Log.e("REPEAT-REQUEST", action + requestKey + " Method @" + request.method() + + " --- " + " URL = " + request.url().encodedPath() + "\t" + body); } else { Log.e("REPEAT-REQUEST", action + requestKey + " Method @" + request.method()); } } - private static String bodyToString(final Request request) { - try { - final Request copy = request.newBuilder().build(); - final Buffer buffer = new Buffer(); - copy.body().writeTo(buffer); - if (buffer.size() > 4096) { - return "-too long"; - } - return buffer.readUtf8(); - } catch (Exception e) { - return "-"; + private static void logResponse(Request request, byte[] bytes) { + if (!BuildConfig.DEBUG) { + return; + } + if (bytes == null || bytes.length > MAX_LOG_BODY_LENGTH) { + Log.e(TAG, "请求体返回:| Response: " + request.url() + "\t body: too long"); + } else { + Log.e(TAG, "请求体返回:| Response: " + request.url() + + "\t body: " + new String(bytes, StandardCharsets.UTF_8)); } } - private static String requestBodyToString(RequestBody body) { - try { - final Buffer buffer = new Buffer(); - body.writeTo(buffer); - if (buffer.size() > 4096) { - return "-too long"; + /** + * 一次请求的去重记录:owner 线程负责访问服务器,其他相同请求等待并复用它的结果 + */ + private static final class RepeatRecord { + private final Object lock = new Object(); + private final long createdTime = System.currentTimeMillis(); + + private boolean owner; + private boolean finished; + private boolean succeed; + private long finishedTime; + private byte[] body; + private MediaType contentType; + private Headers headers; + private Protocol protocol; + private int code; + private String message; + + void markOwner() { + owner = true; + } + + boolean isOwner() { + return owner; + } + + /** + * 等待 owner 请求结束 + * + * @return true 表示已拿到可复用的结果 + */ + boolean await(long timeoutMs) { + synchronized (lock) { + if (!finished) { + try { + lock.wait(timeoutMs); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + return finished && succeed; + } + } + + /** 请求成功,缓存结果并唤醒等待的请求 */ + void complete(Response response, byte[] body, MediaType contentType) { + synchronized (lock) { + if (finished) { + return; + } + this.body = body; + this.contentType = contentType; + this.headers = response.headers(); + this.protocol = response.protocol(); + this.code = response.code(); + this.message = response.message(); + this.succeed = true; + finished = true; + finishedTime = System.currentTimeMillis(); + lock.notifyAll(); + } + } + + /** 请求结束(失败或异常时没有可复用的结果);重复调用忽略 */ + void finish() { + synchronized (lock) { + if (finished) { + return; + } + finished = true; + finishedTime = System.currentTimeMillis(); + lock.notifyAll(); + } + } + + /** 进行中的记录超过等待超时时间、已完成的记录超过结果保留时间即视为过期 */ + boolean isExpired(long now) { + synchronized (lock) { + if (!finished) { + return now - createdTime > WAIT_IN_FLIGHT_TIMEOUT_MS; + } + return now - finishedTime > REUSE_WINDOW_MS; + } + } + + /** 用缓存的结果构建响应,状态码、响应头、响应体都是真实数据 */ + Response newResponse(Request request) { + synchronized (lock) { + return new Response.Builder() + .request(request) + .protocol(protocol) + .code(code) + .message(message) + .headers(headers) + .body(ResponseBody.create(contentType, body)) + .build(); } - return buffer.readUtf8(); - } catch (Exception e) { - return "-"; } } } diff --git a/src/com/aoleyun/os/uiuiutils/JgyUtils.java b/src/com/aoleyun/os/uiuiutils/JgyUtils.java index fb07860..95564e2 100644 --- a/src/com/aoleyun/os/uiuiutils/JgyUtils.java +++ b/src/com/aoleyun/os/uiuiutils/JgyUtils.java @@ -45,6 +45,9 @@ public class JgyUtils { public static final int MT8768Platform = 17; public static final int AUDG104Platform = 18; public static final int seewoPlatform = 25; + public static final int DX11Platform = 31; + public static final int G12NLPlatform = 32; + public static final String Other = "其他"; public static final String MTKTag = "MTK"; @@ -62,6 +65,8 @@ public class JgyUtils { public static final String MT8768Tag = "MT8768"; public static final String AUDG104Tag = "AUDG104"; public static final String seewoTag = "seewo"; + public static final String DX11_TAG = "DX11"; + public static final String G12NL_TAG = "G12NL"; private JgyUtils(Context context) { @@ -120,6 +125,12 @@ public class JgyUtils { } else if (seewoTag.equalsIgnoreCase(platform)) { Log.i(TAG, "checkAppPlatform: " + "seewo"); return seewoPlatform; + } else if (DX11_TAG.equalsIgnoreCase(platform)) { + Log.i(TAG, "checkAppPlatform: " + "DX11"); + return DX11Platform; + } else if (G12NL_TAG.equalsIgnoreCase(platform)) { + Log.i(TAG, "checkAppPlatform: " + "G12NL"); + return G12NLPlatform; } else { Log.i(TAG, "checkAppPlatform: " + "没有数据"); return UnknowPlatform; @@ -154,6 +165,10 @@ public class JgyUtils { getAppPlatformCallback.AppPlatform(AUDG104Platform); } else if (seewoTag.equalsIgnoreCase(platform)) { getAppPlatformCallback.AppPlatform(seewoPlatform); + } else if (DX11_TAG.equalsIgnoreCase(platform)) { + getAppPlatformCallback.AppPlatform(DX11Platform); + } else if (G12NL_TAG.equalsIgnoreCase(platform)) { + getAppPlatformCallback.AppPlatform(G12NLPlatform); } else { getAppPlatformCallback.AppPlatform(UnknowPlatform); }