Enable flipper android to use different ports based on prop

Summary:
Part 1 of enabling flipper to run on custom ports: android SDK.
Still to go: iOS SDK and desktop

This should allow you to run mobile apps that use flipper on different ports than the default (8089,8088).

`adb shell`
`su`
`setprop flipper.ports 1111,2222`

From what I can tell, this only works on rooted devices.

Reviewed By: passy

Differential Revision: D13753238

fbshipit-source-id: c5f370c9d8c7382e8c17fb81d4010c642ef7c114
This commit is contained in:
John Knox
2019-01-24 03:08:42 -08:00
committed by Facebook Github Bot
parent c68e74c6a0
commit 324a7ae873
9 changed files with 171 additions and 92 deletions

View File

@@ -1,9 +1,8 @@
/* /**
* Copyright (c) Facebook, Inc. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree. * file in the root directory of this source tree.
*
*/ */
#include <memory> #include <memory>
@@ -465,6 +464,8 @@ class JFlipperClient : public jni::HybridClass<JFlipperClient> {
jni::alias_ref<jclass>, jni::alias_ref<jclass>,
JEventBase* callbackWorker, JEventBase* callbackWorker,
JEventBase* connectionWorker, JEventBase* connectionWorker,
int insecurePort,
int securePort,
const std::string host, const std::string host,
const std::string os, const std::string os,
const std::string device, const std::string device,
@@ -472,20 +473,17 @@ class JFlipperClient : public jni::HybridClass<JFlipperClient> {
const std::string app, const std::string app,
const std::string appId, const std::string appId,
const std::string privateAppDirectory) { const std::string privateAppDirectory) {
FlipperClient::init({{std::move(host),
FlipperClient::init({
{
std::move(host),
std::move(os), std::move(os),
std::move(device), std::move(device),
std::move(deviceId), std::move(deviceId),
std::move(app), std::move(app),
std::move(appId), std::move(appId),
std::move(privateAppDirectory) std::move(privateAppDirectory)},
},
callbackWorker->eventBase(), callbackWorker->eventBase(),
connectionWorker->eventBase() connectionWorker->eventBase(),
}); insecurePort,
securePort});
} }
private: private:

View File

@@ -1,9 +1,8 @@
/* /**
* Copyright (c) 2018-present, Facebook, Inc. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree. * file in the root directory of this source tree.
*
*/ */
package com.facebook.flipper.android; package com.facebook.flipper.android;
@@ -36,6 +35,8 @@ public final class AndroidFlipperClient {
FlipperClientImpl.init( FlipperClientImpl.init(
sFlipperThread.getEventBase(), sFlipperThread.getEventBase(),
sConnectionThread.getEventBase(), sConnectionThread.getEventBase(),
FlipperProps.getInsecurePort(),
FlipperProps.getSecurePort(),
getServerHost(app), getServerHost(app),
"Android", "Android",
getFriendlyDeviceName(), getFriendlyDeviceName(),

View File

@@ -1,9 +1,8 @@
/* /**
* Copyright (c) Facebook, Inc. * Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
* *
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/ */
package com.facebook.flipper.android; package com.facebook.flipper.android;
@@ -36,6 +35,8 @@ class FlipperClientImpl implements FlipperClient {
public static native void init( public static native void init(
EventBase callbackWorker, EventBase callbackWorker,
EventBase connectionWorker, EventBase connectionWorker,
int insecurePort,
int securePort,
String host, String host,
String os, String os,
String device, String device,

View File

@@ -0,0 +1,84 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*/
package com.facebook.flipper.android;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
class FlipperProps {
private static final String FLIPPER_PORTS_PROP_NAME = "flipper.ports";
private static final int DEFAULT_INSECURE_PORT = 8089;
private static final int DEFAULT_SECURE_PORT = 8088;
private static final String TAG = "Flipper";
static int getInsecurePort() {
String propValue = getFlipperPortsPropValue();
return extractIntFromPropValue(propValue, 0, DEFAULT_INSECURE_PORT);
}
static int getSecurePort() {
String propValue = getFlipperPortsPropValue();
return extractIntFromPropValue(propValue, 1, DEFAULT_SECURE_PORT);
}
static int extractIntFromPropValue(String propValue, int index, int fallback) {
if (propValue != null && !propValue.isEmpty()) {
try {
String[] values = propValue.split(",");
if (values.length > index) {
return Integer.parseInt(values[index]);
}
} catch (NumberFormatException e) {
Log.e(TAG, "Failed to parse flipper.ports value: " + propValue);
}
}
return fallback;
}
private static String flipperPortsPropValue = null;
private static synchronized String getFlipperPortsPropValue() {
if (flipperPortsPropValue != null) {
return flipperPortsPropValue;
}
Process process = null;
BufferedReader reader = null;
try {
process =
Runtime.getRuntime().exec(new String[] {"/system/bin/getprop", FLIPPER_PORTS_PROP_NAME});
reader =
new BufferedReader(
new InputStreamReader(process.getInputStream(), Charset.forName("UTF-8")));
String lastLine = "";
String line;
while ((line = reader.readLine()) != null) {
lastLine = line;
}
flipperPortsPropValue = lastLine;
} catch (IOException e) {
Log.e(TAG, "Failed to query for flipper.ports prop", e);
flipperPortsPropValue = "";
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
Log.e(TAG, "Failed to close BufferedReader when reading flipper.ports prop", e);
}
if (process != null) {
process.destroy();
}
}
return flipperPortsPropValue;
}
}

View File

@@ -0,0 +1,43 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package com.facebook.flipper.android;
import static org.junit.Assert.assertEquals;
import com.facebook.testing.robolectric.v3.WithTestDefaultsRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(WithTestDefaultsRunner.class)
public class FlipperPropsTest {
@Test
public void shouldParseExpectedInput() throws Exception {
int value1 = FlipperProps.extractIntFromPropValue("1111,2222", 0, 1234);
assertEquals(value1, 1111);
int value2 = FlipperProps.extractIntFromPropValue("1111,2222", 1, 1234);
assertEquals(value2, 2222);
}
@Test
public void shouldFallbackForTruncatedInput() throws Exception {
int value = FlipperProps.extractIntFromPropValue("1111", 1, 1234);
assertEquals(value, 1234);
}
@Test
public void shouldFallbackForMistypedInput() throws Exception {
int value = FlipperProps.extractIntFromPropValue("111ds1", 0, 1234);
assertEquals(value, 1234);
}
@Test
public void shouldFallbackForEmptyInput() throws Exception {
int value = FlipperProps.extractIntFromPropValue("", 0, 1234);
assertEquals(value, 1234);
}
}

View File

@@ -1,49 +0,0 @@
/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*
*/
package com.facebook.flipper.plugins.console;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;
import com.facebook.flipper.core.FlipperObject;
import com.facebook.flipper.testing.FlipperConnectionMock;
import com.facebook.flipper.testing.FlipperResponderMock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class ConsoleFlipperPluginTest {
FlipperConnectionMock connection;
FlipperResponderMock responder;
@Before
public void setup() throws Exception {
JavascriptEnvironment jsEnvironment = new JavascriptEnvironment();
final ConsoleFlipperPlugin plugin = new ConsoleFlipperPlugin(jsEnvironment);
connection = new FlipperConnectionMock();
responder = new FlipperResponderMock();
plugin.onConnect(connection);
}
@Test
public void simpleExpressionShouldEvaluateCorrectly() throws Exception {
receiveScript("2 + 2");
assertThat(
responder.successes,
hasItem(new FlipperObject.Builder().put("value", 4).put("type", "json").build()));
}
private void receiveScript(String a) throws Exception {
FlipperObject getValue = new FlipperObject.Builder().put("command", a).build();
connection.receivers.get("executeCommand").onReceive(getValue, responder);
}
}

View File

@@ -24,8 +24,6 @@
static constexpr int reconnectIntervalSeconds = 2; static constexpr int reconnectIntervalSeconds = 2;
static constexpr int connectionKeepaliveSeconds = 10; static constexpr int connectionKeepaliveSeconds = 10;
static constexpr int securePort = 8088;
static constexpr int insecurePort = 8089;
static constexpr int maxPayloadSize = 0xFFFFFF; static constexpr int maxPayloadSize = 0xFFFFFF;
@@ -84,6 +82,8 @@ FlipperConnectionManagerImpl::FlipperConnectionManagerImpl(
std::shared_ptr<ConnectionContextStore> contextStore) std::shared_ptr<ConnectionContextStore> contextStore)
: deviceData_(config.deviceData), : deviceData_(config.deviceData),
flipperState_(state), flipperState_(state),
insecurePort(config.insecurePort),
securePort(config.securePort),
flipperEventBase_(config.callbackWorker), flipperEventBase_(config.callbackWorker),
connectionEventBase_(config.connectionWorker), connectionEventBase_(config.connectionWorker),
contextStore_(contextStore) { contextStore_(contextStore) {

View File

@@ -1,11 +1,9 @@
/* /**
* Copyright (c) 2018-present, Facebook, Inc. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree. * file in the root directory of this source tree.
*
*/ */
#pragma once #pragma once
#include "FlipperInitConfig.h" #include "FlipperInitConfig.h"
@@ -49,6 +47,8 @@ class FlipperConnectionManagerImpl : public FlipperConnectionManager {
Callbacks* callbacks_; Callbacks* callbacks_;
DeviceData deviceData_; DeviceData deviceData_;
std::shared_ptr<FlipperState> flipperState_; std::shared_ptr<FlipperState> flipperState_;
int insecurePort;
int securePort;
folly::EventBase* flipperEventBase_; folly::EventBase* flipperEventBase_;
folly::EventBase* connectionEventBase_; folly::EventBase* connectionEventBase_;

View File

@@ -1,11 +1,9 @@
/* /**
* Copyright (c) 2018-present, Facebook, Inc. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree. * file in the root directory of this source tree.
*
*/ */
#pragma once #pragma once
#include <folly/io/async/EventBase.h> #include <folly/io/async/EventBase.h>
@@ -39,6 +37,9 @@ struct FlipperInitConfig {
EventBase to be used to maintain the network connection. EventBase to be used to maintain the network connection.
*/ */
folly::EventBase* connectionWorker; folly::EventBase* connectionWorker;
int insecurePort = 8089;
int securePort = 8088;
}; };
} // namespace flipper } // namespace flipper