am a6a4c70a: am 403be115: teach monkey to flip permissions on apps

* commit 'a6a4c70af2a28a3d9308e3881ddae96a91df71fe':
  teach monkey to flip permissions on apps
This commit is contained in:
Guang Zhu
2015-06-21 20:34:29 +00:00
committed by Android Git Automerger
6 changed files with 363 additions and 59 deletions

View File

@@ -31,15 +31,12 @@ import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.StrictMode; import android.os.StrictMode;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle; import android.os.UserHandle;
import android.view.IWindowManager; import android.view.IWindowManager;
import android.view.Surface; import android.view.Surface;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
@@ -47,12 +44,12 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Writer; import java.io.Writer;
import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set;
/** /**
* Application that injects random key events and other actions into the system. * Application that injects random key events and other actions into the system.
@@ -181,12 +178,6 @@ public class Monkey {
/** Package whitelist file. */ /** Package whitelist file. */
private String mPkgWhitelistFile; private String mPkgWhitelistFile;
/** Packages we are allowed to run, or empty if no restriction. */
private HashSet<String> mValidPackages = new HashSet<String>();
/** Packages we are not allowed to run. */
private HashSet<String> mInvalidPackages = new HashSet<String>();
/** Categories we are allowed to launch **/ /** Categories we are allowed to launch **/
private ArrayList<String> mMainCategories = new ArrayList<String>(); private ArrayList<String> mMainCategories = new ArrayList<String>();
@@ -251,36 +242,20 @@ public class Monkey {
private MonkeyNetworkMonitor mNetworkMonitor = new MonkeyNetworkMonitor(); private MonkeyNetworkMonitor mNetworkMonitor = new MonkeyNetworkMonitor();
private boolean mPermissionTargetSystem = false;
// information on the current activity. // information on the current activity.
public static Intent currentIntent; public static Intent currentIntent;
public static String currentPackage; public static String currentPackage;
/**
* Check whether we should run against the givn package.
*
* @param pkg The package name.
* @return Returns true if we should run against pkg.
*/
private boolean checkEnteringPackage(String pkg) {
if (mInvalidPackages.size() > 0) {
if (mInvalidPackages.contains(pkg)) {
return false;
}
} else if (mValidPackages.size() > 0) {
if (!mValidPackages.contains(pkg)) {
return false;
}
}
return true;
}
/** /**
* Monitor operations happening in the system. * Monitor operations happening in the system.
*/ */
private class ActivityController extends IActivityController.Stub { private class ActivityController extends IActivityController.Stub {
public boolean activityStarting(Intent intent, String pkg) { public boolean activityStarting(Intent intent, String pkg) {
boolean allow = checkEnteringPackage(pkg) || (DEBUG_ALLOW_ANY_STARTS != 0); boolean allow = MonkeyUtils.getPackageFilter().checkEnteringPackage(pkg)
|| (DEBUG_ALLOW_ANY_STARTS != 0);
if (mVerbose > 0) { if (mVerbose > 0) {
// StrictMode's disk checks end up catching this on // StrictMode's disk checks end up catching this on
// userdebug/eng builds due to PrintStream going to a // userdebug/eng builds due to PrintStream going to a
@@ -301,7 +276,8 @@ public class Monkey {
public boolean activityResuming(String pkg) { public boolean activityResuming(String pkg) {
StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
System.out.println(" // activityResuming(" + pkg + ")"); System.out.println(" // activityResuming(" + pkg + ")");
boolean allow = checkEnteringPackage(pkg) || (DEBUG_ALLOW_ANY_RESTARTS != 0); boolean allow = MonkeyUtils.getPackageFilter().checkEnteringPackage(pkg)
|| (DEBUG_ALLOW_ANY_RESTARTS != 0);
if (!allow) { if (!allow) {
if (mVerbose > 0) { if (mVerbose > 0) {
System.out.println(" // " + (allow ? "Allowing" : "Rejecting") System.out.println(" // " + (allow ? "Allowing" : "Rejecting")
@@ -559,18 +535,7 @@ public class Monkey {
if (mVerbose > 0) { if (mVerbose > 0) {
System.out.println(":Monkey: seed=" + mSeed + " count=" + mCount); System.out.println(":Monkey: seed=" + mSeed + " count=" + mCount);
if (mValidPackages.size() > 0) { MonkeyUtils.getPackageFilter().dump();
Iterator<String> it = mValidPackages.iterator();
while (it.hasNext()) {
System.out.println(":AllowPackage: " + it.next());
}
}
if (mInvalidPackages.size() > 0) {
Iterator<String> it = mInvalidPackages.iterator();
while (it.hasNext()) {
System.out.println(":DisallowPackage: " + it.next());
}
}
if (mMainCategories.size() != 0) { if (mMainCategories.size() != 0) {
Iterator<String> it = mMainCategories.iterator(); Iterator<String> it = mMainCategories.iterator();
while (it.hasNext()) { while (it.hasNext()) {
@@ -626,7 +591,8 @@ public class Monkey {
if (mVerbose >= 2) { // check seeding performance if (mVerbose >= 2) { // check seeding performance
System.out.println("// Seeded: " + mSeed); System.out.println("// Seeded: " + mSeed);
} }
mEventSource = new MonkeySourceRandom(mRandom, mMainApps, mThrottle, mRandomizeThrottle); mEventSource = new MonkeySourceRandom(mRandom, mMainApps,
mThrottle, mRandomizeThrottle, mPermissionTargetSystem);
mEventSource.setVerbose(mVerbose); mEventSource.setVerbose(mVerbose);
// set any of the factors that has been set // set any of the factors that has been set
for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) { for (int i = 0; i < MonkeySourceRandom.FACTORZ_COUNT; i++) {
@@ -756,11 +722,12 @@ public class Monkey {
try { try {
String opt; String opt;
Set<String> validPackages = new HashSet<>();
while ((opt = nextOption()) != null) { while ((opt = nextOption()) != null) {
if (opt.equals("-s")) { if (opt.equals("-s")) {
mSeed = nextOptionLong("Seed"); mSeed = nextOptionLong("Seed");
} else if (opt.equals("-p")) { } else if (opt.equals("-p")) {
mValidPackages.add(nextOptionData()); validPackages.add(nextOptionData());
} else if (opt.equals("-c")) { } else if (opt.equals("-c")) {
mMainCategories.add(nextOptionData()); mMainCategories.add(nextOptionData());
} else if (opt.equals("-v")) { } else if (opt.equals("-v")) {
@@ -812,6 +779,9 @@ public class Monkey {
} else if (opt.equals("--pct-pinchzoom")) { } else if (opt.equals("--pct-pinchzoom")) {
int i = MonkeySourceRandom.FACTOR_PINCHZOOM; int i = MonkeySourceRandom.FACTOR_PINCHZOOM;
mFactors[i] = -nextOptionLong("pinch zoom events percentage"); mFactors[i] = -nextOptionLong("pinch zoom events percentage");
} else if (opt.equals("--pct-permission")) {
int i = MonkeySourceRandom.FACTOR_PERMISSION;
mFactors[i] = -nextOptionLong("runtime permission toggle events percentage");
} else if (opt.equals("--pkg-blacklist-file")) { } else if (opt.equals("--pkg-blacklist-file")) {
mPkgBlacklistFile = nextOptionData(); mPkgBlacklistFile = nextOptionData();
} else if (opt.equals("--pkg-whitelist-file")) { } else if (opt.equals("--pkg-whitelist-file")) {
@@ -845,6 +815,8 @@ public class Monkey {
} else if (opt.equals("--periodic-bugreport")){ } else if (opt.equals("--periodic-bugreport")){
mGetPeriodicBugreport = true; mGetPeriodicBugreport = true;
mBugreportFrequency = nextOptionLong("Number of iterations"); mBugreportFrequency = nextOptionLong("Number of iterations");
} else if (opt.equals("--permission-target-system")){
mPermissionTargetSystem = true;
} else if (opt.equals("-h")) { } else if (opt.equals("-h")) {
showUsage(); showUsage();
return false; return false;
@@ -854,6 +826,7 @@ public class Monkey {
return false; return false;
} }
} }
MonkeyUtils.getPackageFilter().addValidPackages(validPackages);
} catch (RuntimeException ex) { } catch (RuntimeException ex) {
System.err.println("** Error: " + ex.toString()); System.err.println("** Error: " + ex.toString());
showUsage(); showUsage();
@@ -889,7 +862,7 @@ public class Monkey {
* @param list The destination list. * @param list The destination list.
* @return Returns false if any error occurs. * @return Returns false if any error occurs.
*/ */
private static boolean loadPackageListFromFile(String fileName, HashSet<String> list) { private static boolean loadPackageListFromFile(String fileName, Set<String> list) {
BufferedReader reader = null; BufferedReader reader = null;
try { try {
reader = new BufferedReader(new FileReader(fileName)); reader = new BufferedReader(new FileReader(fileName));
@@ -921,20 +894,24 @@ public class Monkey {
* @return Returns false if any error occurs. * @return Returns false if any error occurs.
*/ */
private boolean loadPackageLists() { private boolean loadPackageLists() {
if (((mPkgWhitelistFile != null) || (mValidPackages.size() > 0)) if (((mPkgWhitelistFile != null) || (MonkeyUtils.getPackageFilter().hasValidPackages()))
&& (mPkgBlacklistFile != null)) { && (mPkgBlacklistFile != null)) {
System.err.println("** Error: you can not specify a package blacklist " System.err.println("** Error: you can not specify a package blacklist "
+ "together with a whitelist or individual packages (via -p)."); + "together with a whitelist or individual packages (via -p).");
return false; return false;
} }
Set<String> validPackages = new HashSet<>();
if ((mPkgWhitelistFile != null) if ((mPkgWhitelistFile != null)
&& (!loadPackageListFromFile(mPkgWhitelistFile, mValidPackages))) { && (!loadPackageListFromFile(mPkgWhitelistFile, validPackages))) {
return false; return false;
} }
MonkeyUtils.getPackageFilter().addValidPackages(validPackages);
Set<String> invalidPackages = new HashSet<>();
if ((mPkgBlacklistFile != null) if ((mPkgBlacklistFile != null)
&& (!loadPackageListFromFile(mPkgBlacklistFile, mInvalidPackages))) { && (!loadPackageListFromFile(mPkgBlacklistFile, invalidPackages))) {
return false; return false;
} }
MonkeyUtils.getPackageFilter().addInvalidPackages(invalidPackages);
return true; return true;
} }
@@ -1014,7 +991,7 @@ public class Monkey {
for (int a = 0; a < NA; a++) { for (int a = 0; a < NA; a++) {
ResolveInfo r = mainApps.get(a); ResolveInfo r = mainApps.get(a);
String packageName = r.activityInfo.applicationInfo.packageName; String packageName = r.activityInfo.applicationInfo.packageName;
if (checkEnteringPackage(packageName)) { if (MonkeyUtils.getPackageFilter().checkEnteringPackage(packageName)) {
if (mVerbose >= 2) { // very verbose if (mVerbose >= 2) { // very verbose
System.out.println("// + Using main activity " + r.activityInfo.name System.out.println("// + Using main activity " + r.activityInfo.name
+ " (from package " + packageName + ")"); + " (from package " + packageName + ")");
@@ -1352,6 +1329,7 @@ public class Monkey {
usage.append(" [--pct-nav PERCENT] [--pct-majornav PERCENT]\n"); usage.append(" [--pct-nav PERCENT] [--pct-majornav PERCENT]\n");
usage.append(" [--pct-appswitch PERCENT] [--pct-flip PERCENT]\n"); usage.append(" [--pct-appswitch PERCENT] [--pct-flip PERCENT]\n");
usage.append(" [--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT]\n"); usage.append(" [--pct-anyevent PERCENT] [--pct-pinchzoom PERCENT]\n");
usage.append(" [--pct-permission PERCENT]\n");
usage.append(" [--pkg-blacklist-file PACKAGE_BLACKLIST_FILE]\n"); usage.append(" [--pkg-blacklist-file PACKAGE_BLACKLIST_FILE]\n");
usage.append(" [--pkg-whitelist-file PACKAGE_WHITELIST_FILE]\n"); usage.append(" [--pkg-whitelist-file PACKAGE_WHITELIST_FILE]\n");
usage.append(" [--wait-dbg] [--dbg-no-events]\n"); usage.append(" [--wait-dbg] [--dbg-no-events]\n");
@@ -1365,6 +1343,7 @@ public class Monkey {
usage.append(" [--script-log]\n"); usage.append(" [--script-log]\n");
usage.append(" [--bugreport]\n"); usage.append(" [--bugreport]\n");
usage.append(" [--periodic-bugreport]\n"); usage.append(" [--periodic-bugreport]\n");
usage.append(" [--permission-target-system]\n");
usage.append(" COUNT\n"); usage.append(" COUNT\n");
System.err.println(usage.toString()); System.err.println(usage.toString());
} }

View File

@@ -31,7 +31,8 @@ public abstract class MonkeyEvent {
public static final int EVENT_TYPE_ACTIVITY = 4; public static final int EVENT_TYPE_ACTIVITY = 4;
public static final int EVENT_TYPE_FLIP = 5; // Keyboard flip public static final int EVENT_TYPE_FLIP = 5; // Keyboard flip
public static final int EVENT_TYPE_THROTTLE = 6; public static final int EVENT_TYPE_THROTTLE = 6;
public static final int EVENT_TYPE_NOOP = 7; public static final int EVENT_TYPE_PERMISSION = 7;
public static final int EVENT_TYPE_NOOP = 8;
public static final int INJECT_SUCCESS = 1; public static final int INJECT_SUCCESS = 1;
public static final int INJECT_FAIL = 0; public static final int INJECT_FAIL = 0;

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.commands.monkey;
import android.app.IActivityManager;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.view.IWindowManager;
public class MonkeyPermissionEvent extends MonkeyEvent {
private String mPkg;
private PermissionInfo mPermissionInfo;
public MonkeyPermissionEvent(String pkg, PermissionInfo permissionInfo) {
super(EVENT_TYPE_PERMISSION);
mPkg = pkg;
mPermissionInfo = permissionInfo;
}
@Override
public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
try {
// determine if we should grant or revoke permission
int perm = pm.checkPermission(mPermissionInfo.name, mPkg, UserHandle.myUserId());
boolean grant = perm == PackageManager.PERMISSION_DENIED;
// log before calling pm in case we hit an error
System.out.println(String.format(":Permission %s %s to package %s",
grant ? "grant" : "revoke", mPermissionInfo.name, mPkg));
if (grant) {
pm.grantRuntimePermission(mPkg, mPermissionInfo.name, UserHandle.myUserId());
} else {
pm.revokeRuntimePermission(mPkg, mPermissionInfo.name, UserHandle.myUserId());
}
return MonkeyEvent.INJECT_SUCCESS;
} catch (RemoteException re) {
return MonkeyEvent.INJECT_ERROR_REMOTE_EXCEPTION;
}
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.commands.monkey;
import android.Manifest;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.os.Build;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
* Utility class that encapsulates runtime permission related methods for monkey
*
*/
public class MonkeyPermissionUtil {
private static final String PERMISSION_PREFIX = "android.permission.";
private static final String PERMISSION_GROUP_PREFIX = "android.permission-group.";
// from com.android.packageinstaller.permission.utils
private static final String[] MODERN_PERMISSION_GROUPS = {
Manifest.permission_group.CALENDAR, Manifest.permission_group.CAMERA,
Manifest.permission_group.CONTACTS, Manifest.permission_group.LOCATION,
Manifest.permission_group.SENSORS, Manifest.permission_group.SMS,
Manifest.permission_group.PHONE, Manifest.permission_group.MICROPHONE,
Manifest.permission_group.STORAGE
};
// from com.android.packageinstaller.permission.utils
private static boolean isModernPermissionGroup(String name) {
for (String modernGroup : MODERN_PERMISSION_GROUPS) {
if (modernGroup.equals(name)) {
return true;
}
}
return false;
}
/**
* actual list of packages to target, with invalid packages excluded, and may optionally include
* system packages
*/
private List<String> mTargetedPackages;
/** if we should target system packages regardless if they are listed */
private boolean mTargetSystemPackages;
private IPackageManager mPm;
/** keep track of runtime permissions requested for each package targeted */
private Map<String, List<PermissionInfo>> mPermissionMap;
public MonkeyPermissionUtil() {
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
}
public void setTargetSystemPackages(boolean targetSystemPackages) {
mTargetSystemPackages = targetSystemPackages;
}
/**
* Decide if a package should be targeted by permission monkey
* @param info
* @return
*/
private boolean shouldTargetPackage(PackageInfo info) {
// target if permitted by white listing / black listing rules
if (MonkeyUtils.getPackageFilter().checkEnteringPackage(info.packageName)) {
return true;
}
if (mTargetSystemPackages
// not explicitly black listed
&& !MonkeyUtils.getPackageFilter().isPackageInvalid(info.packageName)
// is a system app
&& (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
return true;
}
return false;
}
private boolean shouldTargetPermission(String pkg, PermissionInfo pi) throws RemoteException {
int flags = mPm.getPermissionFlags(pi.name, pkg, UserHandle.myUserId());
int fixedPermFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
| PackageManager.FLAG_PERMISSION_POLICY_FIXED;
return pi.group != null && pi.protectionLevel == PermissionInfo.PROTECTION_DANGEROUS
&& ((flags & fixedPermFlags) == 0)
&& isModernPermissionGroup(pi.group);
}
public boolean populatePermissionsMapping() {
mPermissionMap = new HashMap<>();
try {
List<?> pkgInfos = mPm.getInstalledPackages(
PackageManager.GET_PERMISSIONS, UserHandle.myUserId()).getList();
for (Object o : pkgInfos) {
PackageInfo info = (PackageInfo)o;
if (!shouldTargetPackage(info)) {
continue;
}
List<PermissionInfo> permissions = new ArrayList<>();
if (info.applicationInfo.targetSdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1) {
// skip apps targetting lower API level
continue;
}
if (info.requestedPermissions == null) {
continue;
}
for (String perm : info.requestedPermissions) {
PermissionInfo pi = mPm.getPermissionInfo(perm, 0);
if (pi != null && shouldTargetPermission(info.packageName, pi)) {
permissions.add(pi);
}
}
if (!permissions.isEmpty()) {
mPermissionMap.put(info.packageName, permissions);
}
}
} catch (RemoteException re) {
System.err.println("** Failed talking with package manager!");
return false;
}
if (!mPermissionMap.isEmpty()) {
mTargetedPackages = new ArrayList<>(mPermissionMap.keySet());
}
return true;
}
public void dump() {
System.out.println("// Targeted packages and permissions:");
for (Map.Entry<String, List<PermissionInfo>> e : mPermissionMap.entrySet()) {
System.out.println(String.format("// + Using %s", e.getKey()));
for (PermissionInfo pi : e.getValue()) {
String name = pi.name;
if (name != null) {
if (name.startsWith(PERMISSION_PREFIX)) {
name = name.substring(PERMISSION_PREFIX.length());
}
}
String group = pi.group;
if (group != null) {
if (group.startsWith(PERMISSION_GROUP_PREFIX)) {
group = group.substring(PERMISSION_GROUP_PREFIX.length());
}
}
System.out.println(String.format("// Permission: %s [%s]", name, group));
}
}
}
public MonkeyPermissionEvent generateRandomPermissionEvent(Random random) {
String pkg = mTargetedPackages.get(random.nextInt(mTargetedPackages.size()));
List<PermissionInfo> infos = mPermissionMap.get(pkg);
return new MonkeyPermissionEvent(pkg, infos.get(random.nextInt(infos.size())));
}
}

View File

@@ -26,7 +26,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
import java.util.ArrayList; import java.util.List;
import java.util.Random; import java.util.Random;
/** /**
@@ -82,8 +82,9 @@ public class MonkeySourceRandom implements MonkeyEventSource {
public static final int FACTOR_SYSOPS = 7; public static final int FACTOR_SYSOPS = 7;
public static final int FACTOR_APPSWITCH = 8; public static final int FACTOR_APPSWITCH = 8;
public static final int FACTOR_FLIP = 9; public static final int FACTOR_FLIP = 9;
public static final int FACTOR_ANYTHING = 10; public static final int FACTOR_PERMISSION = 10;
public static final int FACTORZ_COUNT = 11; // should be last+1 public static final int FACTOR_ANYTHING = 11;
public static final int FACTORZ_COUNT = 12; // should be last+1
private static final int GESTURE_TAP = 0; private static final int GESTURE_TAP = 0;
private static final int GESTURE_DRAG = 1; private static final int GESTURE_DRAG = 1;
@@ -93,12 +94,13 @@ public class MonkeySourceRandom implements MonkeyEventSource {
* values after we read any optional values. * values after we read any optional values.
**/ **/
private float[] mFactors = new float[FACTORZ_COUNT]; private float[] mFactors = new float[FACTORZ_COUNT];
private ArrayList<ComponentName> mMainApps; private List<ComponentName> mMainApps;
private int mEventCount = 0; //total number of events generated so far private int mEventCount = 0; //total number of events generated so far
private MonkeyEventQueue mQ; private MonkeyEventQueue mQ;
private Random mRandom; private Random mRandom;
private int mVerbose = 0; private int mVerbose = 0;
private long mThrottle = 0; private long mThrottle = 0;
private MonkeyPermissionUtil mPermissionUtil;
private boolean mKeyboardOpen = false; private boolean mKeyboardOpen = false;
@@ -117,8 +119,8 @@ public class MonkeySourceRandom implements MonkeyEventSource {
return KeyEvent.keyCodeFromString(keyName); return KeyEvent.keyCodeFromString(keyName);
} }
public MonkeySourceRandom(Random random, ArrayList<ComponentName> MainApps, public MonkeySourceRandom(Random random, List<ComponentName> MainApps,
long throttle, boolean randomizeThrottle) { long throttle, boolean randomizeThrottle, boolean permissionTargetSystem) {
// default values for random distributions // default values for random distributions
// note, these are straight percentages, to match user input (cmd line args) // note, these are straight percentages, to match user input (cmd line args)
// but they will be converted to 0..1 values before the main loop runs. // but they will be converted to 0..1 values before the main loop runs.
@@ -132,12 +134,16 @@ public class MonkeySourceRandom implements MonkeyEventSource {
mFactors[FACTOR_SYSOPS] = 2.0f; mFactors[FACTOR_SYSOPS] = 2.0f;
mFactors[FACTOR_APPSWITCH] = 2.0f; mFactors[FACTOR_APPSWITCH] = 2.0f;
mFactors[FACTOR_FLIP] = 1.0f; mFactors[FACTOR_FLIP] = 1.0f;
// disbale permission by default
mFactors[FACTOR_PERMISSION] = 0.0f;
mFactors[FACTOR_ANYTHING] = 13.0f; mFactors[FACTOR_ANYTHING] = 13.0f;
mFactors[FACTOR_PINCHZOOM] = 2.0f; mFactors[FACTOR_PINCHZOOM] = 2.0f;
mRandom = random; mRandom = random;
mMainApps = MainApps; mMainApps = MainApps;
mQ = new MonkeyEventQueue(random, throttle, randomizeThrottle); mQ = new MonkeyEventQueue(random, throttle, randomizeThrottle);
mPermissionUtil = new MonkeyPermissionUtil();
mPermissionUtil.setTargetSystemPackages(permissionTargetSystem);
} }
/** /**
@@ -410,6 +416,9 @@ public class MonkeySourceRandom implements MonkeyEventSource {
} else if (cls < mFactors[FACTOR_ROTATION]) { } else if (cls < mFactors[FACTOR_ROTATION]) {
generateRotationEvent(mRandom); generateRotationEvent(mRandom);
return; return;
} else if (cls < mFactors[FACTOR_PERMISSION]) {
mQ.add(mPermissionUtil.generateRandomPermissionEvent(mRandom));
return;
} }
// The remaining event categories are injected as key events // The remaining event categories are injected as key events
@@ -450,8 +459,15 @@ public class MonkeySourceRandom implements MonkeyEventSource {
} }
public boolean validate() { public boolean validate() {
//check factors boolean ret = true;
return adjustEventFactors(); // only populate & dump permissions if enabled
if (mFactors[FACTOR_PERMISSION] != 0.0f) {
ret &= mPermissionUtil.populatePermissionsMapping();
if (ret && mVerbose >= 2) {
mPermissionUtil.dump();
}
}
return ret & adjustEventFactors();
} }
public void setVerbose(int verbose) { public void setVerbose(int verbose) {

View File

@@ -17,6 +17,9 @@
package com.android.commands.monkey; package com.android.commands.monkey;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/** /**
* Misc utilities. * Misc utilities.
@@ -26,6 +29,7 @@ public abstract class MonkeyUtils {
private static final java.util.Date DATE = new java.util.Date(); private static final java.util.Date DATE = new java.util.Date();
private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat( private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss.SSS "); "yyyy-MM-dd HH:mm:ss.SSS ");
private static PackageFilter sFilter;
private MonkeyUtils() { private MonkeyUtils() {
} }
@@ -38,4 +42,72 @@ public abstract class MonkeyUtils {
return DATE_FORMATTER.format(DATE); return DATE_FORMATTER.format(DATE);
} }
public static PackageFilter getPackageFilter() {
if (sFilter == null) {
sFilter = new PackageFilter();
}
return sFilter;
}
public static class PackageFilter {
private Set<String> mValidPackages = new HashSet<>();
private Set<String> mInvalidPackages = new HashSet<>();
private PackageFilter() {
}
public void addValidPackages(Set<String> validPackages) {
mValidPackages.addAll(validPackages);
}
public void addInvalidPackages(Set<String> invalidPackages) {
mInvalidPackages.addAll(invalidPackages);
}
public boolean hasValidPackages() {
return mValidPackages.size() > 0;
}
public boolean isPackageValid(String pkg) {
return mValidPackages.contains(pkg);
}
public boolean isPackageInvalid(String pkg) {
return mInvalidPackages.contains(pkg);
}
/**
* Check whether we should run against the given package.
*
* @param pkg The package name.
* @return Returns true if we should run against pkg.
*/
public boolean checkEnteringPackage(String pkg) {
if (mInvalidPackages.size() > 0) {
if (mInvalidPackages.contains(pkg)) {
return false;
}
} else if (mValidPackages.size() > 0) {
if (!mValidPackages.contains(pkg)) {
return false;
}
}
return true;
}
public void dump() {
if (mValidPackages.size() > 0) {
Iterator<String> it = mValidPackages.iterator();
while (it.hasNext()) {
System.out.println(":AllowPackage: " + it.next());
}
}
if (mInvalidPackages.size() > 0) {
Iterator<String> it = mInvalidPackages.iterator();
while (it.hasNext()) {
System.out.println(":DisallowPackage: " + it.next());
}
}
}
}
} }