Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add a way to select Android User to let Flipper working on devices with Work Profile #4606

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
135c7b1
feat(android-work-profile): support user flag on run-as command to us…
sbatezat Mar 16, 2023
9f9c2cc
Merge branch 'facebook:main' into main
sbatezat Mar 16, 2023
38792c6
Merge branch 'facebook:main' into main
sbatezat Mar 16, 2023
7afef0b
Merge branch 'facebook:main' into main
sbatezat Mar 17, 2023
1effdd5
Merge branch 'facebook:main' into main
sbatezat Mar 21, 2023
b1a24a0
Merge branch 'main' into main
sbatezat Mar 23, 2023
0068dbb
Merge branch 'facebook:main' into main
sbatezat Mar 24, 2023
95d3830
Merge branch 'facebook:main' into main
sbatezat Mar 27, 2023
67e0353
Merge branch 'facebook:main' into main
sbatezat Mar 30, 2023
99497c4
Merge branch 'facebook:main' into main
sbatezat Apr 13, 2023
8f823ec
Merge branch 'facebook:main' into main
sbatezat Apr 23, 2023
a49ff37
Merge branch 'facebook:main' into main
sbatezat Apr 27, 2023
3bd1b6f
Merge branch 'facebook:main' into main
sbatezat May 4, 2023
a152f29
Merge branch 'facebook:main' into main
sbatezat May 15, 2023
375d749
Merge branch 'facebook:main' into main
sbatezat May 17, 2023
7d5a978
Merge branch 'main' into main
sbatezat May 18, 2023
ea4c687
chore: merge changes from facebook's main branch
sbatezat Nov 29, 2023
ca85b69
Merge branch 'fb_main'
sbatezat Nov 29, 2023
5d1f6b1
fix: duplicate import after last merge
sbatezat Nov 29, 2023
920ba5c
Merge branch 'fb_main'
sbatezat Nov 29, 2023
2a02952
Merge branch 'fb_main'
sbatezat Nov 29, 2023
45186b0
Merge branch 'fb_main'
sbatezat Dec 2, 2023
70e2414
Merge branch 'main' into main
sbatezat Dec 4, 2023
78c378c
Merge branch 'main' into main
sbatezat Dec 4, 2023
6b26be3
chore: merge latest changes
sbatezat Dec 13, 2023
33295bd
Merge branch 'facebook:main' into main
sbatezat Dec 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions desktop/flipper-common/src/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export enum Tristate {
*/
export type Settings = {
androidHome: string;
/**
* If unset, this will be set to '0', as it's the default profile on android devices.
* Enterprises using Work Profile might changed it to the Work Profile user id.
*/
androidUserId: string;
enableAndroid: boolean;
enableIOS: boolean;
enablePhysicalIOS: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import {
} from '../../app-connectivity/certificate-exchange/certificate-utils';
import {ClientQuery} from 'flipper-common';
import {recorder} from '../../recorder';
import {FlipperServerImpl} from '../../FlipperServerImpl';

export default class AndroidCertificateProvider extends CertificateProvider {
name = 'AndroidCertificateProvider';
medium = 'FS_ACCESS' as const;

constructor(private adb: Client) {
constructor(private flipperServer: FlipperServerImpl, private adb: Client) {
super();
}

Expand Down Expand Up @@ -109,6 +110,7 @@ export default class AndroidCertificateProvider extends CertificateProvider {
this.adb,
deviceId,
appName,
this.flipperServer.config.settings.androidUserId,
destination + filename,
contents,
clientQuery,
Expand All @@ -126,6 +128,7 @@ export default class AndroidCertificateProvider extends CertificateProvider {
this.adb,
deviceId,
processName,
this.flipperServer.config.settings.androidUserId,
directory + csrFileName,
clientQuery,
);
Expand Down
3 changes: 3 additions & 0 deletions desktop/flipper-server/src/devices/android/AndroidDevice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ export default class AndroidDevice
appIds.map(async (appId): Promise<DeviceDebugData | undefined> => {
const sonarDirFilePaths = await executeCommandAsApp(
this.adb,
this.flipperServer.config.settings.androidUserId,
this.info.serial,
appId,
`find /data/data/${appId}/files/sonar -type f`,
Expand Down Expand Up @@ -370,6 +371,7 @@ export default class AndroidDevice
path: filePath,
data: await pull(
this.adb,
this.flipperServer.config.settings.androidUserId,
this.info.serial,
appId,
filePath,
Expand All @@ -380,6 +382,7 @@ export default class AndroidDevice

const sonarDirContentWithStatsCommandPromise = executeCommandAsApp(
this.adb,
this.flipperServer.config.settings.androidUserId,
this.info.serial,
appId,
`ls -al /data/data/${appId}/files/sonar`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,36 @@ export async function push(
adbClient: Client,
deviceId: string,
app: string,
user: string,
filepath: string,
contents: string,
clientQuery?: ClientQuery,
): Promise<void> {
validateAppName(app);
validateFilePath(filepath);
validateFileContent(contents);
return await _push(adbClient, deviceId, app, filepath, contents, clientQuery);
return await _push(
adbClient,
deviceId,
app,
user,
filepath,
contents,
clientQuery,
);
}

export async function pull(
adbClient: Client,
deviceId: string,
app: string,
user: string,
path: string,
clientQuery?: ClientQuery,
): Promise<string> {
validateAppName(app);
validateFilePath(path);
return await _pull(adbClient, deviceId, app, path, clientQuery);
return await _pull(adbClient, deviceId, app, user, path, clientQuery);
}

function validateAppName(app: string): void {
Expand Down Expand Up @@ -87,6 +97,7 @@ async function _push(
adbClient: Client,
deviceId: string,
app: AppName,
user: string,
filename: FilePath,
contents: FileContent,
clientQuery?: ClientQuery,
Expand Down Expand Up @@ -118,14 +129,14 @@ async function _push(
};

try {
await executeCommandAsApp(adbClient, deviceId, app, cmd);
await executeCommandAsApp(adbClient, deviceId, app, user, cmd);
reportSuccess();
} catch (error) {
if (error instanceof RunAsError) {
// Fall back to running the command directly.
// This will work if adb is running as root.
try {
await executeCommandWithSu(adbClient, deviceId, app, cmd, error);
await executeCommandWithSu(adbClient, deviceId, app, user, cmd, error);
reportSuccess();
return;
} catch (suError) {
Expand All @@ -142,6 +153,7 @@ async function _pull(
adbClient: Client,
deviceId: string,
app: AppName,
user: string,
path: FilePath,
clientQuery?: ClientQuery,
): Promise<string> {
Expand Down Expand Up @@ -170,7 +182,13 @@ async function _pull(
};

try {
const content = await executeCommandAsApp(adbClient, deviceId, app, cmd);
const content = await executeCommandAsApp(
adbClient,
deviceId,
app,
user,
cmd,
);
reportSuccess();
return content;
} catch (error) {
Expand All @@ -182,6 +200,7 @@ async function _pull(
adbClient,
deviceId,
app,
user,
cmd,
error,
);
Expand All @@ -202,26 +221,34 @@ export function executeCommandAsApp(
adbClient: Client,
deviceId: string,
app: string,
user: string,
command: string,
): Promise<string> {
return _executeCommandWithRunner(
adbClient,
deviceId,
app,
command,
`run-as '${app}'`,
`run-as '${app}' --user ${user}`,
);
}

async function executeCommandWithSu(
adbClient: Client,
deviceId: string,
app: string,
user: string,
command: string,
originalErrorToThrow: RunAsError,
): Promise<string> {
try {
return _executeCommandWithRunner(adbClient, deviceId, app, command, 'su');
return _executeCommandWithRunner(
adbClient,
deviceId,
app,
command,
`su --user ${user}`,
);
} catch (e) {
throw originalErrorToThrow;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ export class AndroidDeviceManager {
private readonly flipperServer: FlipperServerImpl,
private readonly adbClient: ADBClient,
) {
this.certificateProvider = new AndroidCertificateProvider(this.adbClient);
this.certificateProvider = new AndroidCertificateProvider(
this.flipperServer,
this.adbClient,
);
}

private createDevice(
Expand Down
1 change: 1 addition & 0 deletions desktop/flipper-server/src/utils/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const DEFAULT_ANDROID_SDK_PATH = getDefaultAndroidSdkPath();
async function getDefaultSettings(): Promise<Settings> {
return {
androidHome: await getDefaultAndroidSdkPath(),
androidUserId: '0',
enableAndroid: true,
enableIOS: os.platform() === 'darwin',
enablePhysicalIOS: os.platform() === 'darwin',
Expand Down
59 changes: 57 additions & 2 deletions desktop/flipper-ui/src/chrome/SettingsSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@
* @format
*/

import React, {Component, useContext} from 'react';
import React, {Component, useContext, useState} from 'react';
import {Radio} from 'antd';
import {updateSettings, Action} from '../reducers/settings';
import {
Action as LauncherAction,
updateLauncherSettings,
} from '../reducers/launcherSettings';
import {connect} from 'react-redux';
import {connect, useSelector} from 'react-redux';
import {State as Store} from '../reducers';
import {flush} from '../utils/persistor';
import ToggledSection from './settings/ToggledSection';
import {
FilePathConfigField,
ConfigText,
URLConfigField,
ComboBoxConfigField,
} from './settings/configFields';
import {isEqual, isMatch, isEmpty} from 'lodash';
import LauncherSettingsPanel from '../fb-stubs/LauncherSettingsPanel';
Expand All @@ -40,7 +41,9 @@ import {
NUX,
} from 'flipper-plugin';
import {loadTheme} from '../utils/loadTheme';
import {getActiveDevice} from '../selectors/connections';
import {getFlipperServer, getFlipperServerConfig} from '../flipperServer';
import BaseDevice from '../devices/BaseDevice';

type OwnProps = {
onHide: () => void;
Expand Down Expand Up @@ -119,6 +122,7 @@ class SettingsSheet extends Component<Props, State> {
const {
enableAndroid,
androidHome,
androidUserId,
enableIOS,
enablePhysicalIOS,
enablePrefetching,
Expand Down Expand Up @@ -169,6 +173,17 @@ class SettingsSheet extends Component<Props, State> {
});
}}
/>
<AndroidUserIdField
defaultValue={androidUserId}
onChange={(v) => {
this.setState({
updatedSettings: {
...this.state.updatedSettings,
androidUserId: v,
},
});
}}
/>
</ToggledSection>
<ToggledSection
label="iOS Developer"
Expand Down Expand Up @@ -382,6 +397,46 @@ export default connect<StateFromProps, DispatchFromProps, OwnProps, Store>(
{updateSettings, updateLauncherSettings},
)(withTrackingScope(SettingsSheet));

function AndroidUserIdField(props: {
defaultValue: string;
onChange: (path: string) => void;
}) {
const activeDevice: BaseDevice = useSelector(getActiveDevice);
const [users, setUsers] = useState([] as {id: string; name: string}[]);

activeDevice
.executeShell('pm list users')
.then((result: string) => {
const users = result
.match(/(?<=UserInfo{)(.*?)(?=})/g)
?.map((userInfo) => {
const infos = userInfo.split(':');
return {id: infos[0], name: `${infos[0]} (${infos[1]})`};
});
setUsers(users || []);
})
.catch((error: Error) => console.error(error));

if (users.length === 0) {
return (
<ConfigText
content={
'Loading... Please be sure to connect a device to show available users.'
}></ConfigText>
);
}

return (
<ComboBoxConfigField
label="Android User"
resetValue={getFlipperServerConfig().settings.androidUserId}
options={users}
defaultValue={props.defaultValue}
onChange={props.onChange}
/>
);
}

function ResetTooltips() {
const nuxManager = useContext(_NuxManagerContext);

Expand Down
Loading