@onekeyfe/hd-core 1.2.2-alpha.6 → 1.2.2-alpha.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/device-lifecycle-events.test.ts +14 -0
- package/__tests__/pro2HostAssetPackage.test.ts +108 -1
- package/__tests__/protocol-v2.test.ts +129 -19
- package/__tests__/protocolV2FileWrite.test.ts +40 -0
- package/dist/api/FirmwareUpdateV4.d.ts.map +1 -1
- package/dist/api/helpers/protocolV2FileWrite.d.ts +1 -0
- package/dist/api/helpers/protocolV2FileWrite.d.ts.map +1 -1
- package/dist/api/protocol-v2/DeviceUploadWallpaper.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/index.js +107 -41
- package/dist/utils/pro2HostAssetPackage.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/api/FirmwareUpdateV4.ts +33 -6
- package/src/api/helpers/protocolV2FileWrite.ts +11 -5
- package/src/api/protocol-v2/DeviceUploadWallpaper.ts +8 -2
- package/src/core/index.ts +19 -8
- package/src/utils/pro2HostAssetPackage.ts +73 -27
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
isProtocolV2PeerRemovedPairingError,
|
|
9
9
|
isRetryableBleConnectionError,
|
|
10
10
|
isRetryableBleProtocolV2ProbeError,
|
|
11
|
+
resolveBleConnectProtocol,
|
|
11
12
|
} from '../src/core';
|
|
12
13
|
import { DataManager } from '../src/data-manager';
|
|
13
14
|
import TransportManager from '../src/data-manager/TransportManager';
|
|
@@ -71,6 +72,19 @@ describe('public device lifecycle events', () => {
|
|
|
71
72
|
jest.restoreAllMocks();
|
|
72
73
|
});
|
|
73
74
|
|
|
75
|
+
test('prefers Protocol V2 only when the method contract is explicitly V2-only', () => {
|
|
76
|
+
const createMethod = (protocols: readonly ('V1' | 'V2')[], connectProtocol?: 'V1' | 'V2') =>
|
|
77
|
+
({
|
|
78
|
+
payload: { connectProtocol },
|
|
79
|
+
getSupportedProtocols: () => protocols,
|
|
80
|
+
} as never);
|
|
81
|
+
|
|
82
|
+
expect(resolveBleConnectProtocol(createMethod(['V2']))).toBe('V2');
|
|
83
|
+
expect(resolveBleConnectProtocol(createMethod(['V1']))).toBeUndefined();
|
|
84
|
+
expect(resolveBleConnectProtocol(createMethod(['V1', 'V2']))).toBeUndefined();
|
|
85
|
+
expect(resolveBleConnectProtocol(createMethod(['V2'], 'V1'))).toBe('V1');
|
|
86
|
+
});
|
|
87
|
+
|
|
74
88
|
test('registers the shared device lifecycle listeners exactly once', async () => {
|
|
75
89
|
jest.spyOn(DataManager, 'getSettings').mockReturnValue('react-native' as never);
|
|
76
90
|
core = initCore();
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-bitwise -- LZ4 decoding and deterministic test data generation require bitwise operations. */
|
|
1
2
|
import { sha3_512 } from '@noble/hashes/sha3';
|
|
2
3
|
|
|
3
4
|
import {
|
|
@@ -5,6 +6,82 @@ import {
|
|
|
5
6
|
supportsPro2HostAssetPackage,
|
|
6
7
|
} from '../src/utils/pro2HostAssetPackage';
|
|
7
8
|
|
|
9
|
+
const decodeRawLz4Block = (compressed: Uint8Array, expectedLength: number) => {
|
|
10
|
+
const output = new Uint8Array(expectedLength);
|
|
11
|
+
let inputOffset = 0;
|
|
12
|
+
let outputOffset = 0;
|
|
13
|
+
|
|
14
|
+
const readLength = (initialLength: number) => {
|
|
15
|
+
let length = initialLength;
|
|
16
|
+
if (length === 15) {
|
|
17
|
+
let extension = 255;
|
|
18
|
+
while (extension === 255) {
|
|
19
|
+
extension = compressed[inputOffset];
|
|
20
|
+
inputOffset += 1;
|
|
21
|
+
length += extension;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return length;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
while (inputOffset < compressed.byteLength) {
|
|
28
|
+
const token = compressed[inputOffset];
|
|
29
|
+
inputOffset += 1;
|
|
30
|
+
const literalLength = readLength(token >>> 4);
|
|
31
|
+
output.set(compressed.subarray(inputOffset, inputOffset + literalLength), outputOffset);
|
|
32
|
+
inputOffset += literalLength;
|
|
33
|
+
outputOffset += literalLength;
|
|
34
|
+
if (inputOffset >= compressed.byteLength) break;
|
|
35
|
+
|
|
36
|
+
const matchOffset = compressed[inputOffset] | (compressed[inputOffset + 1] << 8);
|
|
37
|
+
inputOffset += 2;
|
|
38
|
+
const matchLength = readLength(token & 0x0f) + 4;
|
|
39
|
+
for (let index = 0; index < matchLength; index += 1) {
|
|
40
|
+
output[outputOffset] = output[outputOffset - matchOffset];
|
|
41
|
+
outputOffset += 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
expect(outputOffset).toBe(expectedLength);
|
|
46
|
+
return output;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const decodeFirstPackageEntry = (packageData: Uint8Array, rawLength: number) => {
|
|
50
|
+
const containerHeaderSize = 0x5f90;
|
|
51
|
+
const archive = packageData.subarray(containerHeaderSize);
|
|
52
|
+
const archiveView = new DataView(archive.buffer, archive.byteOffset, archive.byteLength);
|
|
53
|
+
const compressedOffset = archiveView.getUint32(42 + 0x100, true);
|
|
54
|
+
const compressed = archive.subarray(compressedOffset);
|
|
55
|
+
const compressedView = new DataView(
|
|
56
|
+
compressed.buffer,
|
|
57
|
+
compressed.byteOffset,
|
|
58
|
+
compressed.byteLength
|
|
59
|
+
);
|
|
60
|
+
const blockCount = compressedView.getUint16(0, true);
|
|
61
|
+
const blockSize = 1 << compressedView.getUint16(2, true);
|
|
62
|
+
let blockOffset = 8 + blockCount * 4;
|
|
63
|
+
const decodedBlocks: Uint8Array[] = [];
|
|
64
|
+
|
|
65
|
+
for (let index = 0; index < blockCount; index += 1) {
|
|
66
|
+
const compressedLength = compressedView.getUint32(8 + index * 4, true);
|
|
67
|
+
const expectedLength = Math.min(blockSize, rawLength - index * blockSize);
|
|
68
|
+
decodedBlocks.push(
|
|
69
|
+
decodeRawLz4Block(
|
|
70
|
+
compressed.subarray(blockOffset, blockOffset + compressedLength),
|
|
71
|
+
expectedLength
|
|
72
|
+
)
|
|
73
|
+
);
|
|
74
|
+
blockOffset += compressedLength;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const decoded = new Uint8Array(rawLength);
|
|
78
|
+
decodedBlocks.reduce((offset, block) => {
|
|
79
|
+
decoded.set(block, offset);
|
|
80
|
+
return offset + block.byteLength;
|
|
81
|
+
}, 0);
|
|
82
|
+
return decoded;
|
|
83
|
+
};
|
|
84
|
+
|
|
8
85
|
describe('Pro2 host asset package', () => {
|
|
9
86
|
test('builds the unsigned RESOURCE container and LZ4-blocked archive expected by firmware', () => {
|
|
10
87
|
const raw = new TextEncoder().encode('123456789');
|
|
@@ -40,12 +117,42 @@ describe('Pro2 host asset package', () => {
|
|
|
40
117
|
|
|
41
118
|
const compressedOffset = archiveView.getUint32(42 + 0x100, true);
|
|
42
119
|
expect(archiveView.getUint16(compressedOffset, true)).toBe(1);
|
|
43
|
-
expect(archiveView.getUint16(compressedOffset + 2, true)).toBe(
|
|
120
|
+
expect(archiveView.getUint16(compressedOffset + 2, true)).toBe(14);
|
|
44
121
|
expect(archiveView.getUint32(compressedOffset + 4, true)).toBe(0);
|
|
45
122
|
expect(archiveView.getUint32(compressedOffset + 8, true)).toBe(10);
|
|
46
123
|
expect(payload.subarray(compressedOffset + 12)).toEqual(new Uint8Array([0x90, ...raw]));
|
|
47
124
|
});
|
|
48
125
|
|
|
126
|
+
test('round-trips multi-block data byte-for-byte with best-match compression', () => {
|
|
127
|
+
const raw = Uint8Array.from({ length: 16_384 * 3 + 137 }, (_, index) => {
|
|
128
|
+
const column = index % 604;
|
|
129
|
+
const row = Math.floor(index / 604);
|
|
130
|
+
return (column * 31 + row * 17) & 0xff;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const packageData = buildPro2HostAssetPackage([{ name: 'wallpaper.bin', data: raw }]);
|
|
134
|
+
|
|
135
|
+
expect(decodeFirstPackageEntry(packageData, raw.byteLength)).toEqual(raw);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
test('falls back to 8 KiB blocks when a compressed 16 KiB block exceeds firmware capacity', () => {
|
|
139
|
+
let state = 0x12345678;
|
|
140
|
+
const raw = Uint8Array.from({ length: 16_384 }, () => {
|
|
141
|
+
state ^= state << 13;
|
|
142
|
+
state ^= state >>> 17;
|
|
143
|
+
state ^= state << 5;
|
|
144
|
+
return state & 0xff;
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
const packageData = buildPro2HostAssetPackage([{ name: 'wallpaper.bin', data: raw }]);
|
|
148
|
+
const archive = packageData.subarray(0x5f90);
|
|
149
|
+
const archiveView = new DataView(archive.buffer, archive.byteOffset, archive.byteLength);
|
|
150
|
+
const compressedOffset = archiveView.getUint32(42 + 0x100, true);
|
|
151
|
+
|
|
152
|
+
expect(archiveView.getUint16(compressedOffset + 2, true)).toBe(13);
|
|
153
|
+
expect(decodeFirstPackageEntry(packageData, raw.byteLength)).toEqual(raw);
|
|
154
|
+
});
|
|
155
|
+
|
|
49
156
|
test.each([
|
|
50
157
|
['1.0.0', false],
|
|
51
158
|
['1.0.1-beta.1', false],
|
|
@@ -256,6 +256,9 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
256
256
|
});
|
|
257
257
|
|
|
258
258
|
test('uploads and applies the fixed wallpaper package on firmware 1.0.1', async () => {
|
|
259
|
+
const getSettingsSpy = jest
|
|
260
|
+
.spyOn(DataManager, 'getSettings')
|
|
261
|
+
.mockReturnValue('react-native' as any);
|
|
259
262
|
const typedCall = jest.fn().mockImplementation((request, _response, params) => {
|
|
260
263
|
if (request === 'FilesystemDirMake') return { message: {} };
|
|
261
264
|
if (request === 'FilesystemFileWrite') {
|
|
@@ -283,8 +286,13 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
283
286
|
(method as any).device = device;
|
|
284
287
|
method.postMessage = jest.fn();
|
|
285
288
|
|
|
286
|
-
|
|
287
|
-
|
|
289
|
+
let result;
|
|
290
|
+
try {
|
|
291
|
+
method.init();
|
|
292
|
+
result = await method.run();
|
|
293
|
+
} finally {
|
|
294
|
+
getSettingsSpy.mockRestore();
|
|
295
|
+
}
|
|
288
296
|
|
|
289
297
|
const fileWrites = typedCall.mock.calls.filter(call => call[0] === 'FilesystemFileWrite');
|
|
290
298
|
expect(new Set(fileWrites.map(call => call[2].file.path))).toEqual(
|
|
@@ -293,6 +301,7 @@ describe('DeviceUploadWallpaper', () => {
|
|
|
293
301
|
expect(fileWrites[0][2].file.data.subarray(0, 4)).toEqual(
|
|
294
302
|
new Uint8Array([0x4f, 0x4b, 0x50, 0x50])
|
|
295
303
|
);
|
|
304
|
+
expect(fileWrites[0][2].file.data).toHaveLength(1960);
|
|
296
305
|
expect(typedCall).toHaveBeenLastCalledWith('DeviceSettingsSet', 'Success', {
|
|
297
306
|
settings: { wallpaper_path: 'vol1:/wallpapers/wallpaper.okpkg' },
|
|
298
307
|
});
|
|
@@ -5654,7 +5663,7 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
5654
5663
|
expect(method.postTipMessage).not.toHaveBeenCalled();
|
|
5655
5664
|
expect(method.postProgressMessage).not.toHaveBeenCalled();
|
|
5656
5665
|
await cancelableAction?.();
|
|
5657
|
-
expect(cancelDevice).
|
|
5666
|
+
expect(cancelDevice).not.toHaveBeenCalled();
|
|
5658
5667
|
});
|
|
5659
5668
|
|
|
5660
5669
|
test('does not send the install request when Protocol V2 staging fails', async () => {
|
|
@@ -7175,7 +7184,14 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7175
7184
|
true
|
|
7176
7185
|
);
|
|
7177
7186
|
expect((method as any).exitProtocolV2BootloaderToNormal).not.toHaveBeenCalled();
|
|
7178
|
-
expect(method.postProgressMessage).toHaveBeenCalledWith(
|
|
7187
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(
|
|
7188
|
+
100,
|
|
7189
|
+
'transferData',
|
|
7190
|
+
expect.objectContaining({
|
|
7191
|
+
transferredBytes: 5,
|
|
7192
|
+
totalBytes: 5,
|
|
7193
|
+
})
|
|
7194
|
+
);
|
|
7179
7195
|
expect((method as any).completeProtocolV2FinalVerification).toHaveBeenCalledTimes(1);
|
|
7180
7196
|
});
|
|
7181
7197
|
|
|
@@ -7249,7 +7265,14 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
7249
7265
|
expect.objectContaining({ processedSize: 2, totalSize: 3 })
|
|
7250
7266
|
);
|
|
7251
7267
|
expect(method.postProgressMessage).toHaveBeenCalledTimes(1);
|
|
7252
|
-
expect(method.postProgressMessage).toHaveBeenCalledWith(
|
|
7268
|
+
expect(method.postProgressMessage).toHaveBeenCalledWith(
|
|
7269
|
+
100,
|
|
7270
|
+
'transferData',
|
|
7271
|
+
expect.objectContaining({
|
|
7272
|
+
transferredBytes: 3,
|
|
7273
|
+
totalBytes: 3,
|
|
7274
|
+
})
|
|
7275
|
+
);
|
|
7253
7276
|
expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenCalledTimes(1);
|
|
7254
7277
|
expect((method as any).protocolV2StartFirmwareUpdate).toHaveBeenCalledWith({
|
|
7255
7278
|
targets: [{ target_id: 4, path: 'vol0:/application_p1.bin' }],
|
|
@@ -8569,26 +8592,43 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8569
8592
|
(method as any).verifyProtocolV2StagedFile = jest.fn().mockResolvedValue(undefined);
|
|
8570
8593
|
(method as any).protocolV2StartFirmwareUpdate = jest.fn();
|
|
8571
8594
|
(method as any).waitForProtocolV2FirmwareUpdateComplete = jest.fn();
|
|
8595
|
+
const dateNowSpy = jest
|
|
8596
|
+
.spyOn(Date, 'now')
|
|
8597
|
+
.mockReturnValueOnce(1_000)
|
|
8598
|
+
.mockReturnValueOnce(5_000);
|
|
8572
8599
|
|
|
8573
|
-
|
|
8574
|
-
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8600
|
+
try {
|
|
8601
|
+
await (method as any).executeProtocolV2SourceUpdate({
|
|
8602
|
+
installSources: [],
|
|
8603
|
+
resourceSources: [
|
|
8604
|
+
{
|
|
8605
|
+
name: 'images.okpkg',
|
|
8606
|
+
source: {
|
|
8607
|
+
size: 3,
|
|
8608
|
+
readAt: jest.fn(),
|
|
8609
|
+
close: jest.fn(),
|
|
8610
|
+
},
|
|
8611
|
+
devicePath: 'vol0:/bundles/images/images.okpkg',
|
|
8582
8612
|
},
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8613
|
+
],
|
|
8614
|
+
});
|
|
8615
|
+
} finally {
|
|
8616
|
+
dateNowSpy.mockRestore();
|
|
8617
|
+
}
|
|
8587
8618
|
|
|
8588
8619
|
expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenCalledTimes(1);
|
|
8589
8620
|
expect((method as any).protocolV2SourceUpdateProcess).toHaveBeenCalledWith(
|
|
8590
|
-
expect.objectContaining({
|
|
8621
|
+
expect.objectContaining({
|
|
8622
|
+
filePath: 'vol0:/bundles/images/images.okpkg',
|
|
8623
|
+
transferStartedAt: 1_000,
|
|
8624
|
+
})
|
|
8591
8625
|
);
|
|
8626
|
+
expect(method.postProgressMessage).toHaveBeenLastCalledWith(100, 'transferData', {
|
|
8627
|
+
transferredBytes: 3,
|
|
8628
|
+
totalBytes: 3,
|
|
8629
|
+
rateBytesPerSecond: 1,
|
|
8630
|
+
elapsedMs: 4_000,
|
|
8631
|
+
});
|
|
8592
8632
|
expect((method as any).verifyProtocolV2StagedFile).toHaveBeenCalledWith(
|
|
8593
8633
|
'vol0:/bundles/images/images.okpkg',
|
|
8594
8634
|
3
|
|
@@ -8818,6 +8858,40 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
8818
8858
|
expect(recoverProtocolV2FileTransfer).not.toHaveBeenCalled();
|
|
8819
8859
|
});
|
|
8820
8860
|
|
|
8861
|
+
test('does not recover or wrap a cancelled V4 file transfer', async () => {
|
|
8862
|
+
const method = new FirmwareUpdateV4({
|
|
8863
|
+
id: 1,
|
|
8864
|
+
payload: {
|
|
8865
|
+
method: 'firmwareUpdateV4',
|
|
8866
|
+
},
|
|
8867
|
+
});
|
|
8868
|
+
const abortController = new AbortController();
|
|
8869
|
+
method.abortSignal = abortController.signal;
|
|
8870
|
+
(method as any).fileWriteChunk = jest.fn().mockImplementation(() => {
|
|
8871
|
+
abortController.abort();
|
|
8872
|
+
return Promise.reject(new Error('transport disposed'));
|
|
8873
|
+
});
|
|
8874
|
+
const recoverProtocolV2FileTransfer = jest.fn();
|
|
8875
|
+
(method as any).recoverProtocolV2FileTransfer = recoverProtocolV2FileTransfer;
|
|
8876
|
+
const source = await openFirmwareByteSource({
|
|
8877
|
+
binary: new Uint8Array([1]).buffer,
|
|
8878
|
+
});
|
|
8879
|
+
|
|
8880
|
+
try {
|
|
8881
|
+
await expect(
|
|
8882
|
+
(method as any).protocolV2SourceUpdateProcess({
|
|
8883
|
+
source,
|
|
8884
|
+
filePath: 'vol1:firmware.bin',
|
|
8885
|
+
processedSize: 0,
|
|
8886
|
+
totalSize: 1,
|
|
8887
|
+
})
|
|
8888
|
+
).rejects.toMatchObject({ errorCode: HardwareErrorCode.CallQueueActionCancelled });
|
|
8889
|
+
} finally {
|
|
8890
|
+
await source?.close();
|
|
8891
|
+
}
|
|
8892
|
+
expect(recoverProtocolV2FileTransfer).not.toHaveBeenCalled();
|
|
8893
|
+
});
|
|
8894
|
+
|
|
8821
8895
|
test('throttles repeated transfer progress while preserving file completion', async () => {
|
|
8822
8896
|
const method = new FirmwareUpdateV4({
|
|
8823
8897
|
id: 1,
|
|
@@ -9176,6 +9250,42 @@ describe('Protocol V2 firmware update targets', () => {
|
|
|
9176
9250
|
expect(typedCall).toHaveBeenCalledTimes(6);
|
|
9177
9251
|
});
|
|
9178
9252
|
|
|
9253
|
+
test('preserves the underlying transport error code after firmware transfer retries', async () => {
|
|
9254
|
+
const method = new FirmwareUpdateV4({
|
|
9255
|
+
id: 1,
|
|
9256
|
+
payload: {
|
|
9257
|
+
method: 'firmwareUpdateV4',
|
|
9258
|
+
},
|
|
9259
|
+
});
|
|
9260
|
+
const typedCall = jest
|
|
9261
|
+
.fn()
|
|
9262
|
+
.mockRejectedValue(ERRORS.TypedError(HardwareErrorCode.BleTimeoutError, 'response timeout'));
|
|
9263
|
+
|
|
9264
|
+
(method as any).device = stubDevice({
|
|
9265
|
+
getCommands: () => ({ typedCall }),
|
|
9266
|
+
});
|
|
9267
|
+
method.postProgressMessage = jest.fn();
|
|
9268
|
+
method.postTipMessage = jest.fn();
|
|
9269
|
+
(method as any).recoverProtocolV2FileTransfer = jest.fn().mockResolvedValue(undefined);
|
|
9270
|
+
|
|
9271
|
+
const source = await openFirmwareByteSource({
|
|
9272
|
+
binary: new Uint8Array([1, 2, 3]).buffer,
|
|
9273
|
+
});
|
|
9274
|
+
await expect(
|
|
9275
|
+
(method as any).protocolV2SourceUpdateProcess({
|
|
9276
|
+
source,
|
|
9277
|
+
filePath: 'vol0:/firmware.bin',
|
|
9278
|
+
processedSize: 0,
|
|
9279
|
+
totalSize: 3,
|
|
9280
|
+
})
|
|
9281
|
+
).rejects.toMatchObject({
|
|
9282
|
+
errorCode: HardwareErrorCode.EmmcFileWriteFirmwareError,
|
|
9283
|
+
params: { causeCode: HardwareErrorCode.BleTimeoutError },
|
|
9284
|
+
});
|
|
9285
|
+
await source?.close();
|
|
9286
|
+
expect(typedCall).toHaveBeenCalledTimes(3);
|
|
9287
|
+
});
|
|
9288
|
+
|
|
9179
9289
|
// TODO(#850/#855): PR #855 added resume-on-retry and per-chunk retry on the
|
|
9180
9290
|
// writeProtocolV2File path. PR #850 replaced that path with FirmwareByteSource
|
|
9181
9291
|
// streaming (protocolV2SourceUpdateProcess), which restarts a failed transfer from
|
|
@@ -10,6 +10,46 @@ jest.mock('../src/data/config', () => ({
|
|
|
10
10
|
}));
|
|
11
11
|
|
|
12
12
|
describe('writeProtocolV2File', () => {
|
|
13
|
+
test('allows a verified caller-specific BLE chunk limit', async () => {
|
|
14
|
+
const getSettingsSpy = jest
|
|
15
|
+
.spyOn(DataManager, 'getSettings')
|
|
16
|
+
.mockReturnValue('react-native' as any);
|
|
17
|
+
const isBleConnectSpy = jest.spyOn(DataManager, 'isBleConnect').mockReturnValue(true);
|
|
18
|
+
const data = new Uint8Array(1961);
|
|
19
|
+
const typedCall = jest.fn().mockResolvedValue({ message: {} });
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await writeProtocolV2File({
|
|
23
|
+
commands: { typedCall } as any,
|
|
24
|
+
path: 'vol1:/wallpapers/wallpaper.okpkg',
|
|
25
|
+
data,
|
|
26
|
+
bleChunkSizeLimit: 1960,
|
|
27
|
+
});
|
|
28
|
+
} finally {
|
|
29
|
+
getSettingsSpy.mockRestore();
|
|
30
|
+
isBleConnectSpy.mockRestore();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
expect(typedCall).toHaveBeenCalledTimes(2);
|
|
34
|
+
expect(typedCall.mock.calls[0][2].file.data).toEqual(data.slice(0, 1960));
|
|
35
|
+
expect(typedCall.mock.calls[1][2].file.data).toEqual(data.slice(1960));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('does not apply the BLE-only limit to WebUSB', async () => {
|
|
39
|
+
const data = new Uint8Array(1961);
|
|
40
|
+
const typedCall = jest.fn().mockResolvedValue({ message: {} });
|
|
41
|
+
|
|
42
|
+
await writeProtocolV2File({
|
|
43
|
+
commands: { typedCall } as any,
|
|
44
|
+
path: 'vol1:/wallpapers/wallpaper.okpkg',
|
|
45
|
+
data,
|
|
46
|
+
bleChunkSizeLimit: 1960,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
expect(typedCall).toHaveBeenCalledTimes(1);
|
|
50
|
+
expect(typedCall.mock.calls[0][2].file.data).toEqual(data);
|
|
51
|
+
});
|
|
52
|
+
|
|
13
53
|
test('按分片写入并只在首片设置 overwrite', async () => {
|
|
14
54
|
const data = new Uint8Array(4097);
|
|
15
55
|
const typedCall = jest.fn().mockResolvedValue({ message: {} });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAMZ,MAAM,qBAAqB,CAAC;AA0B7B,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAiC/E,OAAO,KAAK,EAEV,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AAqErC,wBAAgB,wCAAwC,CACtD,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,sBAAsB,EAC9B,0BAA0B,UAAQ,QAiCnC;
|
|
1
|
+
{"version":3,"file":"FirmwareUpdateV4.d.ts","sourceRoot":"","sources":["../../src/api/FirmwareUpdateV4.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocolV2FileWrite.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/protocolV2FileWrite.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAIlE,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"protocolV2FileWrite.d.ts","sourceRoot":"","sources":["../../../src/api/helpers/protocolV2FileWrite.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAIlE,MAAM,MAAM,uBAAuB,GAAG,WAAW,GAAG,UAAU,GAAG,IAAI,GAAG,MAAM,CAAC;AAE/E,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,+BAA+B,KAAK,MAAM,GAAG,SAAS,CAAC;IACnF,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,2BAA2B,KAAK,IAAI,CAAC;CAC9D,CAAC;AAyDF,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,WASzD;AAkDD,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B;;;;;;GAuO5E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceUploadWallpaper.d.ts","sourceRoot":"","sources":["../../../src/api/protocol-v2/DeviceUploadWallpaper.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,2BAA2B,CAAC;AAMnC,MAAM,MAAM,2BAA2B,GAAG;IACxC,UAAU,EAAE,MAAM,CAAC;IAKnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAK1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,wBAAwB,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;
|
|
1
|
+
{"version":3,"file":"DeviceUploadWallpaper.d.ts","sourceRoot":"","sources":["../../../src/api/protocol-v2/DeviceUploadWallpaper.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAO3C,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,2BAA2B,CAAC;AAMnC,MAAM,MAAM,2BAA2B,GAAG;IACxC,UAAU,EAAE,MAAM,CAAC;IAKnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAK1C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,wBAAwB,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAsBF,MAAM,CAAC,OAAO,OAAO,qBAAsB,SAAQ,UAAU,CAAC,2BAA2B,CAAC;IACxF,qBAAqB;IAIrB,OAAO,CAAC,OAAO,CAAC,CAA8D;IAE9E,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,IAAI,CAAM;IAElB,IAAI;YA2BU,kBAAkB;YAgBlB,eAAe;YAaf,MAAM;IAuBd,GAAG,IAAI,OAAO,CAAC,6BAA6B,CAAC;CAoCpD"}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import EventEmitter from 'events';
|
|
3
|
+
import { type LowlevelTransportSharedPlugin, type ProtocolType } from '@onekeyfe/hd-transport';
|
|
3
4
|
import { Device } from '../device/Device';
|
|
4
5
|
import DeviceConnector from '../device/DeviceConnector';
|
|
5
6
|
import type { ConnectSettings } from '../types';
|
|
6
7
|
import type { CoreMessage } from '../events';
|
|
7
|
-
import type { LowlevelTransportSharedPlugin } from '@onekeyfe/hd-transport';
|
|
8
8
|
import type { BaseMethod } from '../api/BaseMethod';
|
|
9
9
|
export type CoreContext = ReturnType<Core['getCoreContext']>;
|
|
10
10
|
export declare const callAPI: (context: CoreContext, message: CoreMessage) => Promise<any>;
|
|
@@ -12,6 +12,7 @@ export declare function isRetryableBleProtocolV2ProbeError(method: BaseMethod, e
|
|
|
12
12
|
export declare function isRetryableBleConnectionError(method: BaseMethod, error: unknown): boolean;
|
|
13
13
|
export declare function isMissingDetectedProtocolV2Error(method: BaseMethod, error: unknown): boolean;
|
|
14
14
|
export declare function isProtocolV2PeerRemovedPairingError(method: BaseMethod, error: unknown): boolean;
|
|
15
|
+
export declare function resolveBleConnectProtocol(method: BaseMethod): ProtocolType | undefined;
|
|
15
16
|
export declare const cancel: (context: CoreContext, connectId?: string) => void;
|
|
16
17
|
export declare const onDeviceButtonHandler: (__0_0: Device, __0_1: import("../events").DeviceButtonRequestPayload) => void;
|
|
17
18
|
export default class Core extends EventEmitter {
|
package/dist/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":";AACA,OAAO,YAAY,MAAM,QAAQ,CAAC;AAClC,OAAO,EAEL,KAAK,6BAA6B,EAElC,KAAK,YAAY,EAIlB,MAAM,wBAAwB,CAAC;AA+BhC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAsB1C,OAAO,eAAe,MAAM,2BAA2B,CAAC;AAYxD,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAmD,MAAM,WAAW,CAAC;AAI9F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAWpD,MAAM,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;AA0E7D,eAAO,MAAM,OAAO,YAAmB,WAAW,WAAW,WAAW,iBAoFvE,CAAC;AAyqBF,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAWpF;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAW/E;AAED,wBAAgB,gCAAgC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAQlF;AAED,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,WAMrF;AA6JD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,CAMtF;AAwLD,eAAO,MAAM,MAAM,YAAa,WAAW,cAAc,MAAM,SA0G9D,CAAC;AAuGF,eAAO,MAAM,qBAAqB,gFAejC,CAAC;AAiLF,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,YAAY;IAC5C,OAAO,CAAC,cAAc,CAAoB;IAE1C,SAAgB,aAAa,EAAE,MAAM,CAAC;IAEtC,OAAO,CAAC,YAAY,CAAsB;IAE1C,OAAO,CAAC,cAAc,CAAC,CAAgB;IAGvC,OAAO,CAAC,sBAAsB,CAAoC;IAElE,OAAO,CAAC,iBAAiB,CAAoB;;IAS7C,OAAO,CAAC,cAAc;IA6BhB,aAAa,CAAC,OAAO,EAAE,WAAW;IAuExC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAOV,gBAAgB;CAiC/B;AAED,eAAO,MAAM,QAAQ,YAIpB,CAAC;AAEF,eAAO,MAAM,aAAa,uBAYzB,CAAC;AAMF,eAAO,MAAM,IAAI,aACL,eAAe,aACd,GAAG,WACL,6BAA6B,8BAiBvC,CAAC;AAEF,eAAO,MAAM,eAAe;SAKrB,eAAe,CAAC,KAAK,CAAC;eAChB,GAAG;;UASf,CAAC"}
|