Skip to content

Commit

Permalink
feat(mobile): add usb priority mode for FW update (#15848)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nodonisko authored Dec 10, 2024
1 parent 479fcff commit 8460127
Show file tree
Hide file tree
Showing 9 changed files with 47 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const val INTERFACE_INDEX = 0
class ReactNativeUsbModule : Module() {
private val moduleCoroutineScope = CoroutineScope(Dispatchers.IO)
private var isAppInForeground = false
// We use priority mode to prevent closing device when app is in background for example during firmware update
private var isInPriorityMode = false

// List of devices for which permission has already been requested to prevent redundant requests if the user denies permission.
private var devicesRequestedPermissions = mutableListOf<String>()
Expand All @@ -57,6 +59,10 @@ class ReactNativeUsbModule : Module() {
// Defines event names that the module can send to JavaScript.
Events(ON_DEVICE_CONNECT_EVENT_NAME, ON_DEVICE_DISCONNECT_EVENT_NAME)

Function("setPriorityMode") { priorityMode: Boolean ->
isInPriorityMode = priorityMode
}

AsyncFunction("getDevices") {
return@AsyncFunction getDevices()
}
Expand Down Expand Up @@ -175,8 +181,10 @@ class ReactNativeUsbModule : Module() {
}

OnActivityEntersBackground {
isAppInForeground = false
closeAllOpenedDevices()
if (!isInPriorityMode) {
isAppInForeground = false
closeAllOpenedDevices()
}
}

OnDestroy {
Expand Down
1 change: 1 addition & 0 deletions packages/react-native-usb/src/ReactNativeUsbModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ declare class ReactNativeUsbModuleDeclaration extends NativeModule<DeviceEvents>
selectConfiguration: (deviceName: string, configurationValue: number) => Promise<void>;
transferIn: (deviceName: string, endpointNumber: number, length: number) => Promise<number[]>;
transferOut: (deviceName: string, endpointNumber: number, data: string) => Promise<void>;
setPriorityMode: (isInPriorityMode: boolean) => void;
}

// It loads the native module object from the JSI or falls back to
Expand Down
3 changes: 3 additions & 0 deletions packages/react-native-usb/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const debugLog = (...args: any[]) => {
}
};

export const setPriorityMode = (isInPriorityMode: boolean) =>
ReactNativeUsbModule.setPriorityMode(isInPriorityMode);

const open = (deviceName: string) => ReactNativeUsbModule.open(deviceName);

const close = (deviceName: string) => ReactNativeUsbModule.close(deviceName);
Expand Down
2 changes: 1 addition & 1 deletion suite-native/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export default ({ config }: ConfigContext): ExpoConfig => {
slug: appSlugs[buildType],
owner: appOwners[buildType],
version: suiteNativeVersion,
runtimeVersion: '17',
runtimeVersion: '18',
...(buildType === 'production'
? {}
: {
Expand Down
1 change: 1 addition & 0 deletions suite-native/firmware/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@suite-common/icons": "workspace:*",
"@suite-native/link": "workspace:*",
"@trezor/connect": "workspace:*",
"@trezor/react-native-usb": "workspace:*",
"@trezor/styles": "workspace:*",
"react": "18.2.0",
"react-native": "0.76.1",
Expand Down
3 changes: 3 additions & 0 deletions suite-native/firmware/src/hooks/useFirmware.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
UseFirmwareInstallationParams,
} from '@suite-common/firmware';
import { TxKeyPath, useTranslate } from '@suite-native/intl';
import { setPriorityMode } from '@trezor/react-native-usb';

import { nativeFirmwareActions } from '../nativeFirmwareSlice';

Expand Down Expand Up @@ -60,6 +61,7 @@ export const useFirmware = (params: UseFirmwareInstallationParams) => {
}, [progress, status, setMayBeStuckedTimeout, resetMayBeStuckedTimeout]);

const firmwareUpdate = useCallback(async () => {
setPriorityMode(true);
const result = await firmwareUpdateCommon({ ignoreBaseUrl: true })
.unwrap()
.catch(error => {
Expand All @@ -73,6 +75,7 @@ export const useFirmware = (params: UseFirmwareInstallationParams) => {
return connectResponse;
})
.finally(() => {
setPriorityMode(false);
resetMayBeStuckedTimeout();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useEffect, useMemo, useState } from 'react';
import Animated, {
FadeIn,
FadeInDown,
FadeInUp,
FadeOutDown,
Expand All @@ -11,7 +12,7 @@ import { useDispatch } from 'react-redux';
import { useNavigation } from '@react-navigation/native';

import { authorizeDeviceThunk } from '@suite-common/wallet-core';
import { Box, Button, Text, VStack } from '@suite-native/atoms';
import { Box, Button, Text, VStack, IconButton } from '@suite-native/atoms';
import { ConfirmOnTrezorImage, setDeviceForceRememberedThunk } from '@suite-native/device';
import { requestPrioritizedDeviceAccess } from '@suite-native/device-mutex';
import { Translation } from '@suite-native/intl';
Expand Down Expand Up @@ -44,6 +45,12 @@ const bottomButtonsContainerStyle = prepareNativeStyle<{ bottom: number }>((util
bottom,
}));

const cancelButtonStyle = prepareNativeStyle(utils => ({
position: 'absolute',
left: utils.spacings.sp8,
top: utils.spacings.sp8,
}));

export const FirmwareUpdateInProgressScreen = () => {
const dispatch = useDispatch();
const { applyStyle } = useNativeStyles();
Expand Down Expand Up @@ -81,6 +88,10 @@ export const FirmwareUpdateInProgressScreen = () => {
navigation.goBack();
}, [dispatch, navigation]);

const handleCancel = useCallback(() => {
navigation.goBack();
}, [navigation]);

const startFirmwareUpdate = useCallback(async () => {
setIsFirmwareInstallationRunning(true);

Expand Down Expand Up @@ -161,6 +172,18 @@ export const FirmwareUpdateInProgressScreen = () => {

return (
<Screen>
{isError && (
<Animated.View entering={FadeIn} style={applyStyle(cancelButtonStyle)}>
<IconButton
iconName="x"
size="medium"
colorScheme="tertiaryElevation0"
accessibilityRole="button"
accessibilityLabel="close"
onPress={handleCancel}
/>
</Animated.View>
)}
<VStack justifyContent="center" alignItems="center" flex={1}>
<UpdateProgressIndicator progress={progress} status={indicatorStatus} />
<Animated.View entering={FadeInUp} exiting={FadeOutDown} key={translatedText.title}>
Expand Down
3 changes: 3 additions & 0 deletions suite-native/firmware/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
{ "path": "../../suite-common/icons" },
{ "path": "../link" },
{ "path": "../../packages/connect" },
{
"path": "../../packages/react-native-usb"
},
{ "path": "../../packages/styles" }
]
}
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10311,6 +10311,7 @@ __metadata:
"@suite-common/icons": "workspace:*"
"@suite-native/link": "workspace:*"
"@trezor/connect": "workspace:*"
"@trezor/react-native-usb": "workspace:*"
"@trezor/styles": "workspace:*"
react: "npm:18.2.0"
react-native: "npm:0.76.1"
Expand Down

0 comments on commit 8460127

Please sign in to comment.