Explicitly start adb server
Summary: We've only got about a 75% success rate at initializing an adb client: https://fburl.com/scuba/tr5tkehi This is the second attempt to fix this. The first one D13487864 was reverted because it used 'adb' instead of the full path, and when run as a GUI app, you don't get the PATH variable typically set up in .bashrc files etc. Fixing it by using the full $ANDROID_HOME path. For facebook users, this will always be guessed correctly, but for OSS it could be installed anywhere, so we might get it wrong - it's common for $ANDROID_HOME to not be set at all on mac systems, and setting it for GUI apps is not exactly trivial: https://superuser.com/questions/476752/setting-environment-variables-in-os-x-for-gui-applications Leaving the previous implementation as a fallback for OSS users and in case this method fails for some reason. Metrics wrapped around each implementation as well as the entire thing, so we can see if it solves the issue. Reviewed By: passy Differential Revision: D13818981 fbshipit-source-id: d90bfd9ec80621526accc080778afc44f2a099d9
This commit is contained in:
committed by
Facebook Github Bot
parent
dbb723f8a5
commit
dcfa412080
@@ -8,6 +8,7 @@
|
||||
import AndroidDevice from '../devices/AndroidDevice';
|
||||
import child_process from 'child_process';
|
||||
import promiseRetry from 'promise-retry';
|
||||
import {promisify} from 'util';
|
||||
import type {Store} from '../reducers/index.js';
|
||||
import type BaseDevice from '../devices/BaseDevice';
|
||||
import type Logger from '../fb-stubs/Logger.js';
|
||||
@@ -62,31 +63,56 @@ function getRunningEmulatorName(id: string): Promise<?string> {
|
||||
}
|
||||
|
||||
export default (store: Store, logger: Logger) => {
|
||||
// Using this client before adb server is started up will cause failures.
|
||||
// this gets around this by waiting for listDevices first, which ensures
|
||||
// the server is up and running before allowing any other operations.
|
||||
|
||||
/* Adbkit will attempt to start the adb server if it's not already running,
|
||||
however, it sometimes fails with ENOENT errors. So instead, we start it
|
||||
manually before requesting a client. */
|
||||
function createClient() {
|
||||
const unsafeClient = adb.createClient();
|
||||
return promiseRetry(
|
||||
(retry, number) => {
|
||||
return unsafeClient
|
||||
.listDevices()
|
||||
.then(() => {
|
||||
return unsafeClient;
|
||||
})
|
||||
.catch(e => {
|
||||
console.warn(`Failed to start adb client. Retrying. ${e.message}`);
|
||||
retry(e);
|
||||
});
|
||||
},
|
||||
{
|
||||
minTimeout: 200,
|
||||
retries: 5,
|
||||
},
|
||||
);
|
||||
const adbPath = process.env.ANDROID_HOME
|
||||
? `${process.env.ANDROID_HOME}/platform-tools/adb`
|
||||
: 'adb';
|
||||
return recordSuccessMetric(
|
||||
promisify(child_process.exec)(`${adbPath} start-server`)
|
||||
.then(result => {
|
||||
if (result.error) {
|
||||
throw new Error(
|
||||
`Failed to start adb server: ${result.stderr.toString()}`,
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(adb.createClient),
|
||||
'createADBClient.shell',
|
||||
).catch(err => {
|
||||
console.error(
|
||||
'Failed to create adb client using shell adb command. Trying with adbkit',
|
||||
);
|
||||
|
||||
/* In the event that starting adb with the above method fails, fallback
|
||||
to using adbkit, though its known to be unreliable. */
|
||||
const unsafeClient = adb.createClient();
|
||||
return recordSuccessMetric(
|
||||
promiseRetry(
|
||||
(retry, number) => {
|
||||
return unsafeClient
|
||||
.listDevices()
|
||||
.then(() => {
|
||||
return unsafeClient;
|
||||
})
|
||||
.catch(e => {
|
||||
console.warn(
|
||||
`Failed to start adb client. Retrying. ${e.message}`,
|
||||
);
|
||||
retry(e);
|
||||
});
|
||||
},
|
||||
{
|
||||
minTimeout: 200,
|
||||
retries: 5,
|
||||
},
|
||||
),
|
||||
'createADBClient.adbkit',
|
||||
);
|
||||
});
|
||||
}
|
||||
const clientPromise = recordSuccessMetric(createClient(), 'createADBClient');
|
||||
|
||||
const watchAndroidDevices = () => {
|
||||
// get emulators
|
||||
@@ -105,7 +131,7 @@ export default (store: Store, logger: Logger) => {
|
||||
},
|
||||
);
|
||||
|
||||
clientPromise
|
||||
recordSuccessMetric(createClient(), 'createADBClient')
|
||||
.then(client => {
|
||||
client
|
||||
.trackDevices()
|
||||
|
||||
Reference in New Issue
Block a user