1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.Q; 4 import static android.os.Build.VERSION_CODES.R; 5 import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; 6 import static org.robolectric.util.reflector.Reflector.reflector; 7 8 import android.view.InsetsSource; 9 import android.view.InsetsState; 10 import android.view.WindowInsets; 11 import org.robolectric.RuntimeEnvironment; 12 import org.robolectric.annotation.Implements; 13 import org.robolectric.annotation.RealObject; 14 import org.robolectric.annotation.ReflectorObject; 15 import org.robolectric.util.reflector.Accessor; 16 import org.robolectric.util.reflector.ForType; 17 import org.robolectric.util.reflector.Static; 18 19 /** Shadow of {@link InsetsState}. */ 20 @Implements(value = InsetsState.class, minSdk = Q, isInAndroidSdk = false) 21 public class ShadowInsetsState { 22 // These must align with the indexes declared in InsetsState in SDK up to 33 23 static final int STATUS_BARS = 0; 24 static final int NAVIGATION_BARS = 1; 25 26 @RealObject private InsetsState realInsetsState; 27 @ReflectorObject private InsetsStateReflector insetsStateReflector; 28 getOrCreateSource(int id)29 InsetsSource getOrCreateSource(int id) { 30 return RuntimeEnvironment.getApiLevel() < UPSIDE_DOWN_CAKE 31 ? insetsStateReflector.getSource(id) 32 : realInsetsState.getOrCreateSource(id, getType(id)); 33 } 34 getSourceSize()35 int getSourceSize() { 36 if (RuntimeEnvironment.getApiLevel() >= UPSIDE_DOWN_CAKE) { 37 return realInsetsState.sourceSize(); 38 } else if (RuntimeEnvironment.getApiLevel() >= R) { 39 return reflector(InsetsStateReflector.class).getLastType() + 1; 40 } else { 41 return insetsStateReflector.getSourcesCount(); 42 } 43 } 44 getType(int id)45 private static int getType(int id) { 46 switch (id) { 47 case STATUS_BARS: 48 return RuntimeEnvironment.getApiLevel() < Q 49 ? reflector(WindowInsetsTypeReflector.class).topBar() 50 : WindowInsets.Type.statusBars(); 51 case NAVIGATION_BARS: 52 return RuntimeEnvironment.getApiLevel() < Q 53 ? reflector(WindowInsetsTypeReflector.class).sideBars() 54 : WindowInsets.Type.navigationBars(); 55 default: 56 throw new IllegalArgumentException(); 57 } 58 } 59 60 @ForType(InsetsState.class) 61 interface InsetsStateReflector { getSource(int type)62 InsetsSource getSource(int type); 63 64 @Accessor("ITYPE_IME") 65 @Static getImeType()66 int getImeType(); 67 68 @Accessor("LAST_TYPE") 69 @Static getLastType()70 int getLastType(); 71 getSourcesCount()72 int getSourcesCount(); 73 } 74 75 @ForType(WindowInsets.Type.class) 76 interface WindowInsetsTypeReflector { 77 @Static topBar()78 int topBar(); 79 80 @Static sideBars()81 int sideBars(); 82 } 83 } 84