@Override
 protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
   mMetrics.physicalWidth = width;
   mMetrics.physicalHeight = height;
   mSkyEngine.onViewportMetricsChanged(mMetrics);
   super.onSizeChanged(width, height, oldWidth, oldHeight);
 }
  public void runFromBundle(String bundlePath, String snapshotPath) {
    preRun();

    if (FlutterMain.isRunningPrecompiledCode()) {
      mSkyEngine.runFromPrecompiledSnapshot(bundlePath);
    } else {
      String scriptUri = "file://" + bundlePath;
      if (snapshotPath != null) {
        mSkyEngine.runFromBundleAndSnapshot(scriptUri, bundlePath, snapshotPath);
      } else {
        mSkyEngine.runFromBundle(scriptUri, bundlePath);
      }
    }

    postRun();
  }
 @Override
 public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
   mMetrics.physicalPaddingTop = insets.getSystemWindowInsetTop();
   mMetrics.physicalPaddingRight = insets.getSystemWindowInsetRight();
   mMetrics.physicalPaddingBottom = insets.getSystemWindowInsetBottom();
   mMetrics.physicalPaddingLeft = insets.getSystemWindowInsetLeft();
   mSkyEngine.onViewportMetricsChanged(mMetrics);
   return super.onApplyWindowInsets(insets);
 }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    // TODO(abarth): This version check might not be effective in some
    // versions of Android that statically compile code and will be upset
    // at the lack of |requestUnbufferedDispatch|. Instead, we should factor
    // version-dependent code into separate classes for each supported
    // version and dispatch dynamically.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      requestUnbufferedDispatch(event);
    }

    ArrayList<Pointer> pointers = new ArrayList<Pointer>();

    // TODO(abarth): Rather than unpacking these events here, we should
    // probably send them in one packet to the engine.
    int maskedAction = event.getActionMasked();
    // ACTION_UP, ACTION_POINTER_UP, ACTION_DOWN, and ACTION_POINTER_DOWN
    // only apply to a single pointer, other events apply to all pointers.
    if (maskedAction == MotionEvent.ACTION_UP
        || maskedAction == MotionEvent.ACTION_POINTER_UP
        || maskedAction == MotionEvent.ACTION_DOWN
        || maskedAction == MotionEvent.ACTION_POINTER_DOWN) {
      addPointerForIndex(event, event.getActionIndex(), pointers);
    } else {
      // ACTION_MOVE may not actually mean all pointers have moved
      // but it's the responsibility of a later part of the system to
      // ignore 0-deltas if desired.
      for (int p = 0; p < event.getPointerCount(); p++) {
        addPointerForIndex(event, p, pointers);
      }
    }

    PointerPacket packet = new PointerPacket();
    packet.pointers = pointers.toArray(new Pointer[0]);
    mSkyEngine.onPointerPacket(packet);

    return true;
  }
  public void destroy() {
    if (discoveryReceiver != null) {
      getContext().unregisterReceiver(discoveryReceiver);
    }

    if (mPlatformServiceProviderBinding != null) {
      mPlatformServiceProviderBinding.unbind().close();
      mPlatformServiceProvider.unbindServices();
    }

    if (mViewServiceProviderBinding != null) {
      mViewServiceProviderBinding.unbind().close();
      mViewServiceProvider.unbindServices();
    }

    getHolder().removeCallback(mSurfaceCallback);
    nativeDetach(mNativePlatformView);
    mNativePlatformView = 0;

    mSkyEngine.close();
    mDartServiceProvider.close();
    mFlutterAppMessages.close();
  }
  private void preRun() {
    if (mPlatformServiceProviderBinding != null) {
      mPlatformServiceProviderBinding.unbind().close();
      mPlatformServiceProvider.unbindServices();
    }
    if (mViewServiceProviderBinding != null) {
      mViewServiceProviderBinding.unbind().close();
      mViewServiceProvider.unbindServices();
    }
    if (mDartServiceProvider != null) {
      mDartServiceProvider.close();
    }

    Core core = CoreImpl.getInstance();

    Pair<ServiceProvider.Proxy, InterfaceRequest<ServiceProvider>> dartServiceProvider =
        ServiceProvider.MANAGER.getInterfaceRequest(core);
    mDartServiceProvider = dartServiceProvider.first;

    Pair<ServiceProvider.Proxy, InterfaceRequest<ServiceProvider>> platformServiceProvider =
        ServiceProvider.MANAGER.getInterfaceRequest(core);
    mPlatformServiceProviderBinding =
        ServiceProvider.MANAGER.bind(mPlatformServiceProvider, platformServiceProvider.second);

    Pair<ServiceProvider.Proxy, InterfaceRequest<ServiceProvider>> viewServiceProvider =
        ServiceProvider.MANAGER.getInterfaceRequest(core);
    mViewServiceProviderBinding =
        ServiceProvider.MANAGER.bind(mViewServiceProvider, viewServiceProvider.second);

    ServicesData services = new ServicesData();
    services.incomingServices = platformServiceProvider.first;
    services.outgoingServices = dartServiceProvider.second;
    services.viewServices = viewServiceProvider.first;
    mSkyEngine.setServices(services);

    resetAccessibilityTree();
  }
 private void setLocale(Locale locale) {
   mSkyEngine.onLocaleChanged(locale.getLanguage(), locale.getCountry());
 }
 public void popRoute() {
   mSkyEngine.popRoute();
 }
 public void pushRoute(String route) {
   mSkyEngine.pushRoute(route);
 }
  public void onPostResume() {
    for (ActivityLifecycleListener listener : mActivityLifecycleListeners) listener.onPostResume();

    mSkyEngine.onAppLifecycleStateChanged(AppLifecycleState.RESUMED);
  }
 public void onPause() {
   mSkyEngine.onAppLifecycleStateChanged(AppLifecycleState.PAUSED);
 }