Home | History | Annotate | Download | only in shadows
      1 package org.robolectric.shadows;
      2 
      3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
      4 import static android.os.Build.VERSION_CODES.KITKAT;
      5 import static android.os.Build.VERSION_CODES.LOLLIPOP;
      6 import static android.os.Build.VERSION_CODES.O;
      7 import static org.robolectric.shadow.api.Shadow.directlyOn;
      8 
      9 import android.app.ActivityManager;
     10 import android.app.IActivityManager;
     11 import android.content.Context;
     12 import android.content.pm.ConfigurationInfo;
     13 import android.os.Build.VERSION_CODES;
     14 import android.os.Process;
     15 import java.util.List;
     16 import java.util.concurrent.CopyOnWriteArrayList;
     17 import org.robolectric.RuntimeEnvironment;
     18 import org.robolectric.annotation.HiddenApi;
     19 import org.robolectric.annotation.Implementation;
     20 import org.robolectric.annotation.Implements;
     21 import org.robolectric.annotation.RealObject;
     22 import org.robolectric.annotation.Resetter;
     23 import org.robolectric.shadow.api.Shadow;
     24 import org.robolectric.util.ReflectionHelpers;
     25 
     26 @Implements(ActivityManager.class)
     27 public class ShadowActivityManager {
     28   private int memoryClass = 16;
     29   private String backgroundPackage;
     30   private ActivityManager.MemoryInfo memoryInfo;
     31   private final List<ActivityManager.AppTask> appTasks = new CopyOnWriteArrayList<>();
     32   private final List<ActivityManager.RunningTaskInfo> tasks = new CopyOnWriteArrayList<>();
     33   private final List<ActivityManager.RunningServiceInfo> services = new CopyOnWriteArrayList<>();
     34   private static List<ActivityManager.RunningAppProcessInfo> processes =
     35       new CopyOnWriteArrayList<>();
     36   @RealObject private ActivityManager realObject;
     37   private Boolean isLowRamDeviceOverride = null;
     38   private int lockTaskModeState = ActivityManager.LOCK_TASK_MODE_NONE;
     39 
     40   public ShadowActivityManager() {
     41     ActivityManager.RunningAppProcessInfo processInfo = new ActivityManager.RunningAppProcessInfo();
     42     fillInProcessInfo(processInfo);
     43     processInfo.processName = RuntimeEnvironment.application.getPackageName();
     44     processInfo.pkgList = new String[] {RuntimeEnvironment.application.getPackageName()};
     45     processes.add(processInfo);
     46   }
     47 
     48   @Implementation
     49   protected int getMemoryClass() {
     50     return memoryClass;
     51   }
     52 
     53   @Implementation
     54   protected static boolean isUserAMonkey() {
     55     return false;
     56   }
     57 
     58   @Implementation
     59   protected List<ActivityManager.RunningTaskInfo> getRunningTasks(int maxNum) {
     60     return tasks;
     61   }
     62 
     63   /**
     64    * For tests, returns the list of {@link android.app.ActivityManager.AppTask} set using {@link
     65    * #setAppTasks(List)}. Returns empty list if nothing is set.
     66    *
     67    * @see #setAppTasks(List)
     68    * @return List of current AppTask.
     69    */
     70   @Implementation(minSdk = LOLLIPOP)
     71   protected List<ActivityManager.AppTask> getAppTasks() {
     72     return appTasks;
     73   }
     74 
     75   @Implementation
     76   protected List<ActivityManager.RunningServiceInfo> getRunningServices(int maxNum) {
     77     return services;
     78   }
     79 
     80   @Implementation
     81   protected List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
     82     // This method is explicitly documented not to return an empty list
     83     if (processes.isEmpty()) {
     84       return null;
     85     }
     86     return processes;
     87   }
     88 
     89   /** Returns information seeded by {@link #setProcesses}. */
     90   @Implementation
     91   protected static void getMyMemoryState(ActivityManager.RunningAppProcessInfo inState) {
     92     fillInProcessInfo(inState);
     93     for (ActivityManager.RunningAppProcessInfo info : processes) {
     94       if (info.pid == Process.myPid()) {
     95         inState.importance = info.importance;
     96         inState.lru = info.lru;
     97         inState.importanceReasonCode = info.importanceReasonCode;
     98         inState.importanceReasonPid = info.importanceReasonPid;
     99         inState.lastTrimLevel = info.lastTrimLevel;
    100         inState.pkgList = info.pkgList;
    101         inState.processName = info.processName;
    102       }
    103     }
    104   }
    105 
    106   private static void fillInProcessInfo(ActivityManager.RunningAppProcessInfo processInfo) {
    107     processInfo.pid = Process.myPid();
    108     processInfo.uid = Process.myUid();
    109   }
    110 
    111   @HiddenApi
    112   @Implementation(minSdk = JELLY_BEAN_MR1)
    113   protected boolean switchUser(int userid) {
    114     ShadowUserManager shadowUserManager =
    115         Shadow.extract(RuntimeEnvironment.application.getSystemService(Context.USER_SERVICE));
    116     shadowUserManager.switchUser(userid);
    117     return true;
    118   }
    119 
    120   @Implementation
    121   protected void killBackgroundProcesses(String packageName) {
    122     backgroundPackage = packageName;
    123   }
    124 
    125   @Implementation
    126   protected void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
    127     if (memoryInfo != null) {
    128       outInfo.availMem = memoryInfo.availMem;
    129       outInfo.lowMemory = memoryInfo.lowMemory;
    130       outInfo.threshold = memoryInfo.threshold;
    131       outInfo.totalMem = memoryInfo.totalMem;
    132     }
    133   }
    134 
    135   @Implementation
    136   protected android.content.pm.ConfigurationInfo getDeviceConfigurationInfo() {
    137     return new ConfigurationInfo();
    138   }
    139 
    140   /**
    141    * @param tasks List of running tasks.
    142    */
    143   public void setTasks(List<ActivityManager.RunningTaskInfo> tasks) {
    144     this.tasks.clear();
    145     this.tasks.addAll(tasks);
    146   }
    147 
    148   /**
    149    * Sets the values to be returned by {@link #getAppTasks()}.
    150    *
    151    * @see #getAppTasks()
    152    * @param tasks List of app tasks.
    153    */
    154   public void setAppTasks(List<ActivityManager.AppTask> appTasks) {
    155     this.appTasks.clear();
    156     this.appTasks.addAll(appTasks);
    157   }
    158 
    159   /**
    160    * @param services List of running services.
    161    */
    162   public void setServices(List<ActivityManager.RunningServiceInfo> services) {
    163     this.services.clear();
    164     this.services.addAll(services);
    165   }
    166 
    167   /**
    168    * @param processes List of running processes.
    169    */
    170   public void setProcesses(List<ActivityManager.RunningAppProcessInfo> processes) {
    171     ShadowActivityManager.processes.clear();
    172     ShadowActivityManager.processes.addAll(processes);
    173   }
    174 
    175   /**
    176    * @return Get the package name of the last background processes killed.
    177    */
    178   public String getBackgroundPackage() {
    179     return backgroundPackage;
    180   }
    181 
    182   /**
    183    * @param memoryClass Set the application's memory class.
    184    */
    185   public void setMemoryClass(int memoryClass) {
    186     this.memoryClass = memoryClass;
    187   }
    188 
    189   /**
    190    * @param memoryInfo Set the application's memory info.
    191    */
    192   public void setMemoryInfo(ActivityManager.MemoryInfo memoryInfo) {
    193     this.memoryInfo = memoryInfo;
    194   }
    195 
    196   @Implementation(minSdk = O)
    197   protected static IActivityManager getService() {
    198     return ReflectionHelpers.createNullProxy(IActivityManager.class);
    199   }
    200 
    201   @Implementation(minSdk = KITKAT)
    202   protected boolean isLowRamDevice() {
    203     if (isLowRamDeviceOverride != null) {
    204       return isLowRamDeviceOverride;
    205     }
    206     return directlyOn(realObject, ActivityManager.class, "isLowRamDevice");
    207   }
    208 
    209   /**
    210    * Override the return value of isLowRamDevice().
    211    */
    212   public void setIsLowRamDevice(boolean isLowRamDevice) {
    213     isLowRamDeviceOverride = isLowRamDevice;
    214   }
    215 
    216   @Implementation(minSdk = VERSION_CODES.M)
    217   protected int getLockTaskModeState() {
    218     return lockTaskModeState;
    219   }
    220 
    221   @Implementation(minSdk = VERSION_CODES.LOLLIPOP)
    222   protected boolean isInLockTaskMode() {
    223     return getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE;
    224   }
    225 
    226   /**
    227    * Sets lock task mode state to be reported by {@link ActivityManager#getLockTaskModeState}, but
    228    * has no effect otherwise.
    229    */
    230   public void setLockTaskModeState(int lockTaskModeState) {
    231     this.lockTaskModeState = lockTaskModeState;
    232   }
    233 
    234   @Resetter
    235   public static void reset() {
    236     processes.clear();
    237   }
    238 }
    239