Skip to content

Commit

Permalink
Fix Android keyboard in hot mode (flutter#2944)
Browse files Browse the repository at this point in the history
  • Loading branch information
johnmccutchan authored Aug 18, 2016
1 parent 26f8970 commit b8c1fe7
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 36 deletions.
36 changes: 30 additions & 6 deletions sky/shell/platform/android/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ private void attach() {
Pair<SkyEngine.Proxy, InterfaceRequest<SkyEngine>> engine =
SkyEngine.MANAGER.getInterfaceRequest(core);
mSkyEngine = engine.first;
mNativePlatformView = nativeAttach(engine.second.passHandle().releaseNativeHandle());
mNativePlatformView =
nativeAttach(engine.second.passHandle().releaseNativeHandle(), this);
}

private void preRun() {
Expand Down Expand Up @@ -472,13 +473,36 @@ public void runFromBundle(String bundlePath, String snapshotPath) {
postRun();
}

public void runFromFile(String main, String packageRoot) {
preRun();
mSkyEngine.runFromFile(main, packageRoot, "");
postRun();
public void runFromSource(final String main,
final String packages,
final String assetsDirectory) {
Runnable runnable = new Runnable() {
public void run() {
preRun();
mSkyEngine.runFromFile(main,
packages,
assetsDirectory);
postRun();
synchronized (this) {
notify();
}
}
};

try {
synchronized (runnable) {
// Post to the Android UI thread and wait for the response.
post(runnable);
runnable.wait();
}
} catch (InterruptedException e) {
Log.e(TAG, "Thread got interrupted waiting for " +
"RunFromSourceRunnable to finish", e);
}
}

private static native long nativeAttach(int inputObserverHandle);
private static native long nativeAttach(int skyEngineHandle,
FlutterView view);
private static native int nativeGetObservatoryPort();
private static native void nativeDetach(long nativePlatformViewAndroid);
private static native void nativeSurfaceCreated(long nativePlatformViewAndroid,
Expand Down
13 changes: 2 additions & 11 deletions sky/shell/platform/android/org/domokit/sky/shell/SkyActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,9 @@ protected void onNewIntent(Intent intent) {
public boolean loadIntent(Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_RUN.equals(action)) {
String file = intent.getStringExtra("file");
String packageRoot = intent.getStringExtra("packages");
String route = intent.getStringExtra("route");
// TODO(johnmccutchan): Remove the need for the runFromFile
// intent by launching an empty application at startup and
// reloading from within that.
if ((file != null) && (packageRoot != null)) {
mView.runFromFile(file, packageRoot);
} else {
mView.runFromBundle(intent.getDataString(),
intent.getStringExtra("snapshot"));
}
mView.runFromBundle(intent.getDataString(),
intent.getStringExtra("snapshot"));
if (route != null)
mView.pushRoute(route);
return true;
Expand Down
57 changes: 55 additions & 2 deletions sky/shell/platform/android/platform_view_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <utility>

#include "base/android/jni_android.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/trace_event/trace_event.h"
Expand Down Expand Up @@ -343,10 +344,17 @@ class AndroidGLContext {
FTL_DISALLOW_COPY_AND_ASSIGN(AndroidGLContext);
};

static jlong Attach(JNIEnv* env, jclass clazz, jint skyEngineHandle) {
static jlong Attach(JNIEnv* env,
jclass clazz,
jint skyEngineHandle,
jobject flutterView) {
PlatformViewAndroid* view = new PlatformViewAndroid();
view->ConnectToEngine(mojo::InterfaceRequest<SkyEngine>(
mojo::ScopedMessagePipeHandle(mojo::MessagePipeHandle(skyEngineHandle))));

// Create a weak reference to the flutterView Java object so that we can make
// calls into it later.
view->set_flutter_view(JavaObjectWeakGlobalRef(env, flutterView));
return reinterpret_cast<jlong>(view);
}

Expand All @@ -359,7 +367,8 @@ bool PlatformViewAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}

PlatformViewAndroid::PlatformViewAndroid() : weak_factory_(this) {
PlatformViewAndroid::PlatformViewAndroid()
: weak_factory_(this) {
// If this is the first PlatformView, then intiialize EGL and set up
// the resource context.
if (g_display == EGL_NO_DISPLAY)
Expand Down Expand Up @@ -435,5 +444,49 @@ void PlatformViewAndroid::Resize(const SkISize& size) {
context_->Resize(size);
}

void PlatformViewAndroid::RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) {
FTL_CHECK(base::android::IsVMInitialized());
JNIEnv* env = base::android::AttachCurrentThread();
FTL_CHECK(env);

{
base::android::ScopedJavaLocalRef<jobject> local_flutter_view =
flutter_view_.get(env);
if (local_flutter_view.is_null()) {
// Collected.
return;
}

// Grab the class of the flutter view.
jclass flutter_view_class = env->GetObjectClass(local_flutter_view.obj());
FTL_CHECK(flutter_view_class);

// Grab the runFromSource method id.
jmethodID run_from_source_method_id = env->GetMethodID(
flutter_view_class,
"runFromSource",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
FTL_CHECK(run_from_source_method_id);

// Invoke runFromSource on the Android UI thread.
jstring java_main = env->NewStringUTF(main.c_str());
FTL_CHECK(java_main);
jstring java_packages = env->NewStringUTF(packages.c_str());
FTL_CHECK(java_packages);
jstring java_assets_directory = env->NewStringUTF(assets_directory.c_str());
FTL_CHECK(java_assets_directory);
env->CallVoidMethod(local_flutter_view.obj(),
run_from_source_method_id,
java_main,
java_packages,
java_assets_directory);
}

// Detaching from the VM deletes any stray local references.
base::android::DetachFromVM();
}

} // namespace shell
} // namespace sky
10 changes: 10 additions & 0 deletions sky/shell/platform/android/platform_view_android.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define SKY_SHELL_PLATFORM_ANDROID_PLATFORM_VIEW_ANDROID_H_

#include "base/android/jni_android.h"
#include "base/android/jni_weak_ref.h"
#include "lib/ftl/memory/weak_ptr.h"
#include "flutter/sky/shell/platform_view.h"

Expand Down Expand Up @@ -52,9 +53,18 @@ class PlatformViewAndroid : public PlatformView {
// sky::shell::PlatformView override
virtual void Resize(const SkISize& size);

virtual void RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory);

void set_flutter_view(const JavaObjectWeakGlobalRef& flutter_view) {
flutter_view_ = flutter_view;
}

private:
std::unique_ptr<AndroidGLContext> context_;
ftl::WeakPtrFactory<PlatformViewAndroid> weak_factory_;
JavaObjectWeakGlobalRef flutter_view_;

FTL_DISALLOW_COPY_AND_ASSIGN(PlatformViewAndroid);
};
Expand Down
4 changes: 4 additions & 0 deletions sky/shell/platform/ios/platform_view_ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ class PlatformViewIOS : public PlatformView {

bool SwapBuffers() override;

void RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) override;

private:
std::unique_ptr<IOSGLContext> context_;
ftl::WeakPtrFactory<PlatformViewIOS> weak_factory_;
Expand Down
8 changes: 8 additions & 0 deletions sky/shell/platform/ios/platform_view_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -296,5 +296,13 @@ bool UpdateStorageSizeIfNecessary() {
return context_ != nullptr ? context_->PresentRenderBuffer() : false;
}

void PlatformViewIOS::RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) {
// TODO(johnmccutchan): Call to the iOS UI thread so that services work
// properly like we do in PlatformViewAndroid.
engine().RunFromSource(main, packages, assets_directory);
}

} // namespace shell
} // namespace sky
4 changes: 4 additions & 0 deletions sky/shell/platform/mac/platform_view_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class PlatformViewMac : public PlatformView {

bool SwapBuffers() override;

void RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) override;

private:
base::scoped_nsobject<NSOpenGLView> opengl_view_;
base::scoped_nsobject<NSOpenGLContext> resource_loading_context_;
Expand Down
8 changes: 8 additions & 0 deletions sky/shell/platform/mac/platform_view_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,13 @@
return true;
}

void PlatformViewMac::RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) {
// TODO(johnmccutchan): Call to the Mac UI thread so that services work
// properly like we do in PlatformViewAndroid.
engine().RunFromSource(main, packages, assets_directory);
}

} // namespace shell
} // namespace sky
4 changes: 4 additions & 0 deletions sky/shell/platform_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class PlatformView {

Engine& engine() { return *engine_; }

virtual void RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) = 0;

protected:
Config config_;
SurfaceConfig surface_config_;
Expand Down
22 changes: 6 additions & 16 deletions sky/shell/platform_view_service_protocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,6 @@ static bool ErrorUnknownView(const char** json_object, const char* view_id) {
return false;
}

static bool ErrorIsolateSpawn(const char** json_object, const char* view_id) {
const intptr_t kInvalidParams = -32602;
std::stringstream response;
response << "{\"code\":" << std::to_string(kInvalidParams) << ",";
response << "\"message\":\"Invalid params\",";
response << "\"data\": {\"details\": \"view " << view_id;
response << " did not spawn an isolate\"}}";
*json_object = strdup(response.str().c_str());
return false;
}

static void AppendIsolateRef(std::stringstream* stream,
int64_t main_port,
const std::string name) {
Expand All @@ -99,8 +88,12 @@ static void AppendFlutterView(std::stringstream* stream,
int64_t isolate_id,
const std::string isolate_name) {
*stream << "{\"type\":\"FlutterView\", \"id\": \"" << kViewIdPrefx << "0x"
<< std::hex << view_id << std::dec << "\"," << "\"isolate\":";
AppendIsolateRef(stream, isolate_id, isolate_name);
<< std::hex << view_id << std::dec;
if (isolate_id != ILLEGAL_PORT) {
// Append the isolate (if it exists).
*stream << "\"," << "\"isolate\":";
AppendIsolateRef(stream, isolate_id, isolate_name);
}
*stream << "}";
}

Expand Down Expand Up @@ -168,9 +161,6 @@ bool PlatformViewServiceProtocol::RunInView(const char* method,
if (!view_existed) {
// If the view did not exist this request has definitely failed.
return ErrorUnknownView(json_object, view_id);
} else if (main_port == ILLEGAL_PORT) {
// We did not create an isolate.
return ErrorIsolateSpawn(json_object, view_id);
} else {
// The view existed and the isolate was created. Success.
std::stringstream response;
Expand Down
2 changes: 1 addition & 1 deletion sky/shell/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void Shell::RunInPlatformViewUIThread(uintptr_t view_id,
PlatformView* view = it->get();
if (reinterpret_cast<uintptr_t>(view) == view_id) {
*view_existed = true;
view->engine().RunFromSource(main, packages, assets_directory);
view->RunFromSource(main, packages, assets_directory);
*dart_isolate_id = view->engine().GetUIIsolateMainPort();
*isolate_name = view->engine().GetUIIsolateName();
break;
Expand Down
5 changes: 5 additions & 0 deletions sky/shell/testing/platform_view_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,10 @@ bool PlatformViewTest::SwapBuffers() {
return false;
}

void PlatformViewTest::RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) {
}

} // namespace shell
} // namespace sky
4 changes: 4 additions & 0 deletions sky/shell/testing/platform_view_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ class PlatformViewTest : public PlatformView {

bool SwapBuffers() override;

void RunFromSource(const std::string& main,
const std::string& packages,
const std::string& assets_directory) override;

private:
ftl::WeakPtrFactory<PlatformViewTest> weak_factory_;

Expand Down

0 comments on commit b8c1fe7

Please sign in to comment.