public static void destroy() {
    if (sInstance == null) {
      throw new RuntimeException("No instance to destroy");
    }

    Settings.get().saveData();

    MainApplication app = (MainApplication) sInstance.mContext.getApplicationContext();
    Bus bus = app.getBus();
    bus.unregister(sInstance);

    if (Settings.get().isIncognitoMode()) {
      CookieManager cookieManager = CookieManager.getInstance();
      if (cookieManager != null && cookieManager.hasCookies()) {
        cookieManager.removeAllCookie();
      }
    }

    if (Constant.PROFILE_FPS) {
      sInstance.mWindowManager.removeView(sInstance.mTextView);
    }
    sInstance.mBubbleDraggable.destroy();
    sInstance.mBubbleFlowDraggable.destroy();
    sInstance.mCanvasView.destroy();
    sInstance.mChoreographer.removeFrameCallback(sInstance);
    sInstance.endAppPolling();
    sInstance = null;
  }
  protected MainController(Context context, EventHandler eventHandler) {
    Util.Assert(sInstance == null, "non-null instance");
    sInstance = this;
    mContext = context;
    mAppPackageName = mContext.getPackageName();
    mEventHandler = eventHandler;

    mAppPoller = new AppPoller(context);
    mAppPoller.setListener(mAppPollerListener);

    mCanAutoDisplayLink = true;

    mCanDisplay = true;

    mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

    if (Constant.PROFILE_FPS) {
      mTextView = new TextView(mContext);
      mTextView.setTextColor(0xff00ffff);
      mTextView.setTextSize(32.0f);
      mWindowManagerParams.gravity = Gravity.TOP | Gravity.LEFT;
      mWindowManagerParams.x = 500;
      mWindowManagerParams.y = 16;
      mWindowManagerParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
      mWindowManagerParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
      mWindowManagerParams.type = WindowManager.LayoutParams.TYPE_PHONE;
      mWindowManagerParams.flags =
          WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
              | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
      mWindowManagerParams.format = PixelFormat.TRANSPARENT;
      mWindowManagerParams.setTitle("LinkBubble: Debug Text");
      mWindowManager.addView(mTextView, mWindowManagerParams);
    }

    mUpdateScheduled = false;
    mChoreographer = Choreographer.getInstance();
    mCanvasView = new CanvasView(mContext);

    MainApplication app = (MainApplication) mContext.getApplicationContext();
    Bus bus = app.getBus();
    bus.register(this);

    updateIncognitoMode(Settings.get().isIncognitoMode());

    LayoutInflater inflater = LayoutInflater.from(mContext);

    mBubbleDraggable = (BubbleDraggable) inflater.inflate(R.layout.view_bubble_draggable, null);
    Point bubbleRestingPoint = Settings.get().getBubbleRestingPoint();
    int fromX = Settings.get().getBubbleStartingX(bubbleRestingPoint);
    mBubbleDraggable.configure(
        fromX,
        bubbleRestingPoint.y,
        bubbleRestingPoint.x,
        bubbleRestingPoint.y,
        Constant.BUBBLE_SLIDE_ON_SCREEN_TIME,
        mCanvasView);

    mBubbleDraggable.setOnUpdateListener(
        new BubbleDraggable.OnUpdateListener() {
          @Override
          public void onUpdate(Draggable draggable, float dt) {
            if (!draggable.isDragging()) {
              mBubbleFlowDraggable.syncWithBubble(draggable);
            }
          }
        });

    mBubbleFlowDraggable = (BubbleFlowDraggable) inflater.inflate(R.layout.view_bubble_flow, null);
    mBubbleFlowDraggable.configure(null);
    mBubbleFlowDraggable.collapse(0, null);
    mBubbleFlowDraggable.setBubbleDraggable(mBubbleDraggable);
    mBubbleFlowDraggable.setVisibility(View.GONE);

    mBubbleDraggable.setBubbleFlowDraggable(mBubbleFlowDraggable);
  }