/**
   * Create a new BrowserFrame to be used in an application.
   *
   * @param context An application context to use when retrieving assets.
   * @param w A WebViewCore used as the view for this frame.
   * @param proxy A CallbackProxy for posting messages to the UI thread and querying a client for
   *     information.
   * @param settings A WebSettings object that holds all settings. XXX: Called by WebCore thread.
   */
  public BrowserFrame(
      Context context,
      WebViewCore w,
      CallbackProxy proxy,
      WebSettings settings,
      Map<String, Object> javascriptInterfaces) {

    Context appContext = context.getApplicationContext();

    // Create a global JWebCoreJavaBridge to handle timers and
    // cookies in the WebCore thread.
    if (sJavaBridge == null) {
      sJavaBridge = new JWebCoreJavaBridge();
      // set WebCore native cache size
      ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
      if (am.getMemoryClass() > 16) {
        sJavaBridge.setCacheSize(8 * 1024 * 1024);
      } else {
        sJavaBridge.setCacheSize(4 * 1024 * 1024);
      }
      // initialize CacheManager
      CacheManager.init(appContext);
      // create CookieSyncManager with current Context
      CookieSyncManager.createInstance(appContext);
      // create PluginManager with current Context
      PluginManager.getInstance(appContext);
    }

    if (sConfigCallback == null) {
      sConfigCallback =
          new ConfigCallback((WindowManager) appContext.getSystemService(Context.WINDOW_SERVICE));
      ViewRootImpl.addConfigCallback(sConfigCallback);
    }
    sConfigCallback.addHandler(this);

    mJavaScriptObjects = javascriptInterfaces;
    if (mJavaScriptObjects == null) {
      mJavaScriptObjects = new HashMap<String, Object>();
    }
    mRemovedJavaScriptObjects = new HashSet<Object>();

    mSettings = settings;
    mContext = context;
    mCallbackProxy = proxy;
    mDatabase = WebViewDatabase.getInstance(appContext);
    mWebViewCore = w;

    mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
    mJavaScriptObjects.put(SearchBoxImpl.JS_INTERFACE_NAME, mSearchBox);

    AssetManager am = context.getAssets();
    nativeCreateFrame(w, am, proxy.getBackForwardList());

    if (DebugFlags.BROWSER_FRAME) {
      Log.v(LOGTAG, "BrowserFrame constructor: this=" + this);
    }
  }
  @Override
  protected void onAttachedToWindow() {
    super.onAttachedToWindow();

    mSettingsObserver.observe();
    mDoubleTapGesture =
        new GestureDetector(
            mContext,
            new GestureDetector.SimpleOnGestureListener() {
              @Override
              public boolean onDoubleTap(MotionEvent e) {
                PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
                Log.d(TAG, "Gesture!!");
                if (pm != null) pm.goToSleep(e.getEventTime());
                else Log.d(TAG, "getSystemService returned null PowerManager");

                return true;
              }
            });

    // We really need to be able to animate while window animations are going on
    // so that activities may be started asynchronously from panel animations
    final ViewRootImpl root = getViewRootImpl();
    if (root != null) {
      root.setDrawDuringWindowsAnimating(true);
    }

    // We need to ensure that our window doesn't suffer from overdraw which would normally
    // occur if our window is translucent. Since we are drawing the whole window anyway with
    // the scrim, we don't need the window to be cleared in the beginning.
    if (mService.isScrimSrcModeEnabled()) {
      IBinder windowToken = getWindowToken();
      WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
      lp.token = windowToken;
      setLayoutParams(lp);
      WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
      setWillNotDraw(false);
    } else {
      setWillNotDraw(!DEBUG);
    }
  }
 /**
  * Notify the host application that a key was not handled by the WebView. Except system keys,
  * WebView always consumes the keys in the normal flow or if shouldOverrideKeyEvent returns true.
  * This is called asynchronously from where the key is dispatched. It gives the host application a
  * chance to handle the unhandled key events.
  *
  * @param view The WebView that is initiating the callback.
  * @param event The key event.
  */
 public void onUnhandledKeyEvent(WebView view, KeyEvent event) {
   ViewRootImpl root = view.getViewRootImpl();
   if (root != null) {
     root.dispatchUnhandledKey(event);
   }
 }