All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robolectric.shadows.ShadowViewRootImpl Maven / Gradle / Ivy

package org.robolectric.shadows;

import static org.robolectric.annotation.TextLayoutMode.Mode.REALISTIC;
import static org.robolectric.shadow.api.Shadow.directlyOn;
import static org.robolectric.util.reflector.Reflector.reflector;

import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Looper;
import android.os.RemoteException;
import android.util.MergedConfiguration;
import android.view.Display;
import android.view.HandlerActionQueue;
import android.view.IWindowSession;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManager;
import java.util.ArrayList;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.annotation.Resetter;
import org.robolectric.annotation.TextLayoutMode;
import org.robolectric.config.ConfigurationRegistry;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
import org.robolectric.util.reflector.Accessor;
import org.robolectric.util.reflector.ForType;
import org.robolectric.util.reflector.Static;
import org.robolectric.util.reflector.WithType;

@Implements(value = ViewRootImpl.class, isInAndroidSdk = false)
public class ShadowViewRootImpl {

  @RealObject private ViewRootImpl realObject;

  @Implementation(maxSdk = VERSION_CODES.JELLY_BEAN)
  public static IWindowSession getWindowSession(Looper mainLooper) {
    return null;
  }

  @Implementation
  public void playSoundEffect(int effectId) {
  }

  @Implementation
  protected int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
      boolean insetsPending) throws RemoteException {
    // TODO(christianw): probably should return WindowManagerGlobal.RELAYOUT_RES_SURFACE_RESIZED?
    return 0;
  }

  public void callDispatchResized() {
    Display display = getDisplay();
    Rect frame = new Rect();
    display.getRectSize(frame);

    reflector(_ViewRootImpl_.class, realObject).dispatchResized(frame);
  }

  private Display getDisplay() {
    if (RuntimeEnvironment.getApiLevel() > VERSION_CODES.JELLY_BEAN_MR1) {
      return reflector(_ViewRootImpl_.class, realObject).getDisplay();
    } else {
      WindowManager windowManager = (WindowManager) realObject.getView().getContext()
          .getSystemService(Context.WINDOW_SERVICE);
      return windowManager.getDefaultDisplay();
    }
  }

  @Implementation
  protected void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    directlyOn(
        realObject,
        ViewRootImpl.class,
        "setView",
        ClassParameter.from(View.class, view),
        ClassParameter.from(WindowManager.LayoutParams.class, attrs),
        ClassParameter.from(View.class, panelParentView));
    if (ConfigurationRegistry.get(TextLayoutMode.Mode.class) == REALISTIC) {
      Rect winFrame = new Rect();
      getDisplay().getRectSize(winFrame);
      reflector(_ViewRootImpl_.class, realObject).setWinFrame(winFrame);
    }
  }

  @Resetter
  public static void reset() {
    _ViewRootImpl_ _viewRootImplStatic_ = reflector(_ViewRootImpl_.class);
    _viewRootImplStatic_.setRunQueues(new ThreadLocal<>());
    _viewRootImplStatic_.setFirstDrawHandlers(new ArrayList<>());
    _viewRootImplStatic_.setFirstDrawComplete(false);
    _viewRootImplStatic_.setConfigCallbacks(new ArrayList<>());
  }

  /** Accessor interface for {@link ViewRootImpl}'s internals. */
  @ForType(ViewRootImpl.class)
  interface _ViewRootImpl_ {
    @Static @Accessor("sRunQueues")
    void setRunQueues(ThreadLocal threadLocal);

    @Static @Accessor("sFirstDrawHandlers")
    void setFirstDrawHandlers(ArrayList handlers);

    @Static @Accessor("sFirstDrawComplete")
    void setFirstDrawComplete(boolean isComplete);

    @Static @Accessor("sConfigCallbacks")
    void setConfigCallbacks(ArrayList callbacks);

    @Accessor("mWinFrame")
    void setWinFrame(Rect winFrame);

    @Accessor("mDisplay")
    Display getDisplay();

    // <= JELLY_BEAN
    void dispatchResized(
        int w, int h, Rect contentInsets,
        Rect visibleInsets, boolean reportDraw, Configuration newConfig);

    // <= JELLY_BEAN_MR1
    void dispatchResized(
        Rect frame, Rect contentInsets,
        Rect visibleInsets, boolean reportDraw, Configuration newConfig);

    // <= KITKAT
    void dispatchResized(
        Rect frame, Rect overscanInsets, Rect contentInsets,
        Rect visibleInsets, boolean reportDraw, Configuration newConfig);

    // <= LOLLIPOP_MR1
    void dispatchResized(
        Rect frame, Rect overscanInsets, Rect contentInsets,
        Rect visibleInsets, Rect stableInsets, boolean reportDraw, Configuration newConfig);

    // <= M
    void dispatchResized(
        Rect frame, Rect overscanInsets, Rect contentInsets,
        Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
        Configuration newConfig);

    // <= N_MR1
    void dispatchResized(
        Rect frame, Rect overscanInsets, Rect contentInsets,
        Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
        Configuration newConfig, Rect backDropFrame, boolean forceLayout,
        boolean alwaysConsumeNavBar);

    // <= O_MR1
    void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
        Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
        @WithType("android.util.MergedConfiguration")
            Object mergedConfiguration,
        Rect backDropFrame, boolean forceLayout,
        boolean alwaysConsumeNavBar, int displayId);

    // >= P
    void dispatchResized(
        Rect frame, Rect overscanInsets, Rect contentInsets,
        Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
        @WithType("android.util.MergedConfiguration")
            Object mergedConfiguration,
        Rect backDropFrame, boolean forceLayout,
        boolean alwaysConsumeNavBar, int displayId,
        @WithType("android.view.DisplayCutout$ParcelableWrapper")
            Object displayCutout);


    default void dispatchResized(Rect frame) {
      Rect emptyRect = new Rect(0, 0, 0, 0);

      int apiLevel = RuntimeEnvironment.getApiLevel();
      if (apiLevel <= Build.VERSION_CODES.JELLY_BEAN) {
        dispatchResized(frame.width(), frame.height(), emptyRect, emptyRect, true, null);
      } else if (apiLevel <= VERSION_CODES.JELLY_BEAN_MR1) {
        dispatchResized(frame, emptyRect, emptyRect, true, null);
      } else if (apiLevel <= Build.VERSION_CODES.KITKAT) {
        dispatchResized(frame, emptyRect, emptyRect, emptyRect, true, null);
      } else if (apiLevel <= Build.VERSION_CODES.LOLLIPOP_MR1) {
        dispatchResized(frame, emptyRect, emptyRect, emptyRect, emptyRect, true, null);
      } else if (apiLevel <= Build.VERSION_CODES.M) {
        dispatchResized(frame, emptyRect, emptyRect, emptyRect, emptyRect, emptyRect, true, null);
      } else if (apiLevel <= Build.VERSION_CODES.N_MR1) {
        dispatchResized(frame, emptyRect, emptyRect, emptyRect, emptyRect, emptyRect, true, null,
            frame, false, false);
      } else if (apiLevel <= Build.VERSION_CODES.O_MR1) {
        dispatchResized(frame, emptyRect, emptyRect, emptyRect, emptyRect, emptyRect, true,
            new MergedConfiguration(), frame, false, false, 0);
      } else { // apiLevel >= Build.VERSION_CODES.P
        dispatchResized(frame, emptyRect, emptyRect, emptyRect, emptyRect, emptyRect, true,
            new MergedConfiguration(), frame, false, false, 0,
            new android.view.DisplayCutout.ParcelableWrapper());
      }
    }

  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy