blob: bab7fa94533f61fc631a3afeaf34764b8df5857c [file] [log] [blame]
package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import static android.os.Build.VERSION_CODES.KITKAT;
import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.O;
import static org.robolectric.shadow.api.Shadow.directlyOn;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
import android.os.Build.VERSION_CODES;
import android.os.Process;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.HiddenApi;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.RealObject;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.util.ReflectionHelpers;
@Implements(ActivityManager.class)
public class ShadowActivityManager {
private int memoryClass = 16;
private String backgroundPackage;
private ActivityManager.MemoryInfo memoryInfo;
private final List<ActivityManager.AppTask> appTasks = new CopyOnWriteArrayList<>();
private final List<ActivityManager.RunningTaskInfo> tasks = new CopyOnWriteArrayList<>();
private final List<ActivityManager.RunningServiceInfo> services = new CopyOnWriteArrayList<>();
private static List<ActivityManager.RunningAppProcessInfo> processes =
new CopyOnWriteArrayList<>();
@RealObject private ActivityManager realObject;
private Boolean isLowRamDeviceOverride = null;
private int lockTaskModeState = ActivityManager.LOCK_TASK_MODE_NONE;
public ShadowActivityManager() {
ActivityManager.RunningAppProcessInfo processInfo = new ActivityManager.RunningAppProcessInfo();
fillInProcessInfo(processInfo);
processInfo.processName = RuntimeEnvironment.application.getPackageName();
processInfo.pkgList = new String[] {RuntimeEnvironment.application.getPackageName()};
processes.add(processInfo);
}
@Implementation
protected int getMemoryClass() {
return memoryClass;
}
@Implementation
protected static boolean isUserAMonkey() {
return false;
}
@Implementation
protected List<ActivityManager.RunningTaskInfo> getRunningTasks(int maxNum) {
return tasks;
}
/**
* For tests, returns the list of {@link android.app.ActivityManager.AppTask} set using {@link
* #setAppTasks(List)}. Returns empty list if nothing is set.
*
* @see #setAppTasks(List)
* @return List of current AppTask.
*/
@Implementation(minSdk = LOLLIPOP)
protected List<ActivityManager.AppTask> getAppTasks() {
return appTasks;
}
@Implementation
protected List<ActivityManager.RunningServiceInfo> getRunningServices(int maxNum) {
return services;
}
@Implementation
protected List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
// This method is explicitly documented not to return an empty list
if (processes.isEmpty()) {
return null;
}
return processes;
}
/** Returns information seeded by {@link #setProcesses}. */
@Implementation
protected static void getMyMemoryState(ActivityManager.RunningAppProcessInfo inState) {
fillInProcessInfo(inState);
for (ActivityManager.RunningAppProcessInfo info : processes) {
if (info.pid == Process.myPid()) {
inState.importance = info.importance;
inState.lru = info.lru;
inState.importanceReasonCode = info.importanceReasonCode;
inState.importanceReasonPid = info.importanceReasonPid;
inState.lastTrimLevel = info.lastTrimLevel;
inState.pkgList = info.pkgList;
inState.processName = info.processName;
}
}
}
private static void fillInProcessInfo(ActivityManager.RunningAppProcessInfo processInfo) {
processInfo.pid = Process.myPid();
processInfo.uid = Process.myUid();
}
@HiddenApi
@Implementation(minSdk = JELLY_BEAN_MR1)
protected boolean switchUser(int userid) {
ShadowUserManager shadowUserManager =
Shadow.extract(RuntimeEnvironment.application.getSystemService(Context.USER_SERVICE));
shadowUserManager.switchUser(userid);
return true;
}
@Implementation
protected void killBackgroundProcesses(String packageName) {
backgroundPackage = packageName;
}
@Implementation
protected void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
if (memoryInfo != null) {
outInfo.availMem = memoryInfo.availMem;
outInfo.lowMemory = memoryInfo.lowMemory;
outInfo.threshold = memoryInfo.threshold;
outInfo.totalMem = memoryInfo.totalMem;
}
}
@Implementation
protected android.content.pm.ConfigurationInfo getDeviceConfigurationInfo() {
return new ConfigurationInfo();
}
/**
* @param tasks List of running tasks.
*/
public void setTasks(List<ActivityManager.RunningTaskInfo> tasks) {
this.tasks.clear();
this.tasks.addAll(tasks);
}
/**
* Sets the values to be returned by {@link #getAppTasks()}.
*
* @see #getAppTasks()
* @param tasks List of app tasks.
*/
public void setAppTasks(List<ActivityManager.AppTask> appTasks) {
this.appTasks.clear();
this.appTasks.addAll(appTasks);
}
/**
* @param services List of running services.
*/
public void setServices(List<ActivityManager.RunningServiceInfo> services) {
this.services.clear();
this.services.addAll(services);
}
/**
* @param processes List of running processes.
*/
public void setProcesses(List<ActivityManager.RunningAppProcessInfo> processes) {
ShadowActivityManager.processes.clear();
ShadowActivityManager.processes.addAll(processes);
}
/**
* @return Get the package name of the last background processes killed.
*/
public String getBackgroundPackage() {
return backgroundPackage;
}
/**
* @param memoryClass Set the application's memory class.
*/
public void setMemoryClass(int memoryClass) {
this.memoryClass = memoryClass;
}
/**
* @param memoryInfo Set the application's memory info.
*/
public void setMemoryInfo(ActivityManager.MemoryInfo memoryInfo) {
this.memoryInfo = memoryInfo;
}
@Implementation(minSdk = O)
protected static IActivityManager getService() {
return ReflectionHelpers.createNullProxy(IActivityManager.class);
}
@Implementation(minSdk = KITKAT)
protected boolean isLowRamDevice() {
if (isLowRamDeviceOverride != null) {
return isLowRamDeviceOverride;
}
return directlyOn(realObject, ActivityManager.class, "isLowRamDevice");
}
/**
* Override the return value of isLowRamDevice().
*/
public void setIsLowRamDevice(boolean isLowRamDevice) {
isLowRamDeviceOverride = isLowRamDevice;
}
@Implementation(minSdk = VERSION_CODES.M)
protected int getLockTaskModeState() {
return lockTaskModeState;
}
@Implementation(minSdk = VERSION_CODES.LOLLIPOP)
protected boolean isInLockTaskMode() {
return getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE;
}
/**
* Sets lock task mode state to be reported by {@link ActivityManager#getLockTaskModeState}, but
* has no effect otherwise.
*/
public void setLockTaskModeState(int lockTaskModeState) {
this.lockTaskModeState = lockTaskModeState;
}
@Resetter
public static void reset() {
processes.clear();
}
}