upload android base code part6
This commit is contained in:
parent
421e214c7d
commit
4e516ec6ed
35396 changed files with 9188716 additions and 0 deletions
35
android/platform_testing/utils/crashcollector/Android.mk
Normal file
35
android/platform_testing/utils/crashcollector/Android.mk
Normal file
|
@ -0,0 +1,35 @@
|
|||
#
|
||||
# Copyright (C) 2016 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := crashcollector
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp/crashcollector
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
LOCAL_COMPATIBILITY_SUITE := device-tests
|
||||
|
||||
include $(BUILD_JAVA_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := crashcollector
|
||||
LOCAL_MODULE_CLASS := EXECUTABLES
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/local/tmp/crashcollector
|
||||
LOCAL_SRC_FILES := crashcollector
|
||||
|
||||
include $(BUILD_PREBUILT)
|
19
android/platform_testing/utils/crashcollector/crashcollector
Executable file
19
android/platform_testing/utils/crashcollector/crashcollector
Executable file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (C) 2016 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.
|
||||
#
|
||||
|
||||
base=/data/local/tmp/crashcollector
|
||||
export CLASSPATH=$base/crashcollector.jar
|
||||
exec app_process $base android.test.crashcollector.Collector $*
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright 2016, 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 android.test.crashcollector;
|
||||
|
||||
import android.app.IActivityController;
|
||||
import android.app.IActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.os.IBinder.DeathRecipient;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* Main class for the crash collector that installs an activity controller to monitor app errors
|
||||
*/
|
||||
public class Collector {
|
||||
|
||||
private static final String LOG_TAG = "CrashCollector";
|
||||
private static final long CHECK_AM_INTERVAL_MS = 5 * 1000;
|
||||
private static final long MAX_CHECK_AM_TIMEOUT_MS = 30 * 1000;
|
||||
private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
|
||||
private static final File TOMBSTONES_PATH = new File("/data/tombstones");
|
||||
private HashSet<String> mTombstones = null;
|
||||
|
||||
/**
|
||||
* Command-line entry point.
|
||||
*
|
||||
* @param args The command-line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
// Set the process name showing in "ps" or "top"
|
||||
Process.setArgV0("android.test.crashcollector");
|
||||
|
||||
int resultCode = (new Collector()).run(args);
|
||||
System.exit(resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Command execution entry point
|
||||
* @param args
|
||||
* @return
|
||||
* @throws RemoteException
|
||||
*/
|
||||
public int run(String[] args) {
|
||||
// recipient for activity manager death so that command can survive runtime restart
|
||||
final IBinder.DeathRecipient death = new DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
};
|
||||
IBinder am = blockUntilSystemRunning(MAX_CHECK_AM_TIMEOUT_MS);
|
||||
if (am == null) {
|
||||
print("FATAL: Cannot get activity manager, is system running?");
|
||||
return -1;
|
||||
}
|
||||
IActivityController controller = new CrashCollector();
|
||||
do {
|
||||
try {
|
||||
// set activity controller
|
||||
IActivityManager iam = IActivityManager.Stub.asInterface(am);
|
||||
iam.setActivityController(controller, false);
|
||||
// register death recipient for activity manager
|
||||
am.linkToDeath(death, 0);
|
||||
} catch (RemoteException re) {
|
||||
print("FATAL: cannot set activity controller, is system running?");
|
||||
re.printStackTrace();
|
||||
return -1;
|
||||
}
|
||||
// monitor runtime restart (crash/kill of system server)
|
||||
synchronized (death) {
|
||||
while (am.isBinderAlive()) {
|
||||
try {
|
||||
Log.d(LOG_TAG, "Monitoring death of system server.");
|
||||
death.wait();
|
||||
} catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
Log.w(LOG_TAG, "Detected crash of system server.");
|
||||
am = blockUntilSystemRunning(MAX_CHECK_AM_TIMEOUT_MS);
|
||||
}
|
||||
} while (true);
|
||||
// for now running indefinitely, until a better mechanism is found to signal shutdown
|
||||
}
|
||||
|
||||
private void print(String line) {
|
||||
System.err.println(String.format("%s %s", TIME_FORMAT.format(new Date()), line));
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks until system server is running, or timeout has reached
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
private IBinder blockUntilSystemRunning(long timeout) {
|
||||
// waiting for activity manager to come back
|
||||
long start = SystemClock.uptimeMillis();
|
||||
IBinder am = null;
|
||||
while (SystemClock.uptimeMillis() - start < MAX_CHECK_AM_TIMEOUT_MS) {
|
||||
am = ServiceManager.checkService(Context.ACTIVITY_SERVICE);
|
||||
if (am != null) {
|
||||
break;
|
||||
} else {
|
||||
Log.d(LOG_TAG, "activity manager not ready yet, continue waiting.");
|
||||
try {
|
||||
Thread.sleep(CHECK_AM_INTERVAL_MS);
|
||||
} catch (InterruptedException e) {
|
||||
// break out of current loop upon interruption
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return am;
|
||||
}
|
||||
|
||||
private boolean checkNativeCrashes() {
|
||||
String[] tombstones = TOMBSTONES_PATH.list();
|
||||
|
||||
// shortcut path for usually empty directory, so we don't waste even
|
||||
// more objects
|
||||
if ((tombstones == null) || (tombstones.length == 0)) {
|
||||
mTombstones = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// use set logic to look for new files
|
||||
HashSet<String> newStones = new HashSet<String>();
|
||||
for (String x : tombstones) {
|
||||
newStones.add(x);
|
||||
}
|
||||
|
||||
boolean result = (mTombstones == null) || !mTombstones.containsAll(newStones);
|
||||
|
||||
// keep the new list for the next time
|
||||
mTombstones = newStones;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private class CrashCollector extends IActivityController.Stub {
|
||||
|
||||
@Override
|
||||
public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
|
||||
// check native crashes when we have a chance
|
||||
if (checkNativeCrashes()) {
|
||||
print("NATIVE: new tombstones");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean activityResuming(String pkg) throws RemoteException {
|
||||
// check native crashes when we have a chance
|
||||
if (checkNativeCrashes()) {
|
||||
print("NATIVE: new tombstones");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
|
||||
long timeMillis, String stackTrace) throws RemoteException {
|
||||
if (processName == null) {
|
||||
print("CRASH: null process name, assuming system");
|
||||
} else {
|
||||
print("CRASH: " + processName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int appEarlyNotResponding(String processName, int pid, String annotation)
|
||||
throws RemoteException {
|
||||
// ignore
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int appNotResponding(String processName, int pid, String processStats)
|
||||
throws RemoteException {
|
||||
print("ANR: " + processName);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int systemNotResponding(String msg) throws RemoteException {
|
||||
print("WATCHDOG: " + msg);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
27
android/platform_testing/utils/dpad/Android.mk
Normal file
27
android/platform_testing/utils/dpad/Android.mk
Normal file
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# Copyright (C) 2016 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# The static library that platform/app helpers can link against
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := dpad-util
|
||||
LOCAL_JAVA_LIBRARIES := ub-uiautomator android-support-test
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
include $(BUILD_STATIC_JAVA_LIBRARY)
|
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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 android.platform.test.utils;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.os.SystemClock;
|
||||
import android.support.test.uiautomator.Direction;
|
||||
import android.support.test.uiautomator.EventCondition;
|
||||
import android.support.test.uiautomator.UiDevice;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
public class DPadUtil {
|
||||
|
||||
private static final String TAG = DPadUtil.class.getSimpleName();
|
||||
private static final long DPAD_DEFAULT_WAIT_TIME_MS = 1000; // 1 sec
|
||||
private UiDevice mDevice;
|
||||
|
||||
|
||||
public DPadUtil(Instrumentation instrumentation) {
|
||||
mDevice = UiDevice.getInstance(instrumentation);
|
||||
}
|
||||
|
||||
public DPadUtil(UiDevice uiDevice) {
|
||||
mDevice = uiDevice;
|
||||
}
|
||||
|
||||
public void setUiDevice(UiDevice uiDevice) {
|
||||
mDevice = uiDevice;
|
||||
}
|
||||
|
||||
public boolean pressDPad(Direction direction) {
|
||||
return pressDPad(direction, 1, DPAD_DEFAULT_WAIT_TIME_MS);
|
||||
}
|
||||
|
||||
public void pressDPad(Direction direction, long repeat) {
|
||||
pressDPad(direction, repeat, DPAD_DEFAULT_WAIT_TIME_MS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Presses DPad button of the same direction for the count times.
|
||||
* It sleeps between each press for DPAD_DEFAULT_WAIT_TIME_MS.
|
||||
*
|
||||
* @param direction the direction of the button to press.
|
||||
* @param repeat the number of times to press the button.
|
||||
* @param timeout the timeout for the wait.
|
||||
* @return true if the last key simulation is successful, else return false
|
||||
*/
|
||||
public boolean pressDPad(Direction direction, long repeat, long timeout) {
|
||||
int iteration = 0;
|
||||
boolean result = false;
|
||||
while (iteration++ < repeat) {
|
||||
switch (direction) {
|
||||
case LEFT:
|
||||
result = mDevice.pressDPadLeft();
|
||||
break;
|
||||
case RIGHT:
|
||||
result = mDevice.pressDPadRight();
|
||||
break;
|
||||
case UP:
|
||||
result = mDevice.pressDPadUp();
|
||||
break;
|
||||
case DOWN:
|
||||
result = mDevice.pressDPadDown();
|
||||
break;
|
||||
}
|
||||
SystemClock.sleep(timeout);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean pressDPadLeft() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_DPAD_LEFT);
|
||||
}
|
||||
|
||||
public boolean pressDPadRight() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_DPAD_RIGHT);
|
||||
}
|
||||
|
||||
public boolean pressDPadUp() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_DPAD_UP);
|
||||
}
|
||||
|
||||
public boolean pressDPadDown() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_DPAD_DOWN);
|
||||
}
|
||||
|
||||
public boolean pressDPadCenter() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_DPAD_CENTER);
|
||||
}
|
||||
|
||||
public boolean pressEnter() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_ENTER);
|
||||
}
|
||||
|
||||
public boolean pressPipKey() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_WINDOW);
|
||||
}
|
||||
|
||||
public boolean pressSearch() {
|
||||
return pressKeyCodeAndWait(KeyEvent.KEYCODE_SEARCH);
|
||||
}
|
||||
|
||||
public boolean pressKeyCode(int keyCode) {
|
||||
return pressKeyCodeAndWait(keyCode);
|
||||
}
|
||||
public boolean pressKeyCodeAndWait(int keyCode) {
|
||||
boolean retVal = mDevice.pressKeyCode(keyCode);
|
||||
// Dpad key presses will cause some UI change to occur.
|
||||
// Wait for the accessibility event stream to become idle.
|
||||
mDevice.waitForIdle();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
public boolean pressHome() {
|
||||
return mDevice.pressHome();
|
||||
}
|
||||
|
||||
public boolean pressBack() {
|
||||
return mDevice.pressBack();
|
||||
}
|
||||
|
||||
public boolean longPressKeyCode(int keyCode) {
|
||||
try {
|
||||
mDevice.executeShellCommand(String.format("input keyevent --longpress %d", keyCode));
|
||||
mDevice.waitForIdle();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
Log.w(TAG, String.format("Failed to long press the key code: %d", keyCode));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Press the key code, and waits for the given condition to become true.
|
||||
* @param keyCode
|
||||
* @param condition
|
||||
* @param longpress
|
||||
* @param timeout
|
||||
* @param <R>
|
||||
* @return
|
||||
*/
|
||||
public <R> R pressKeyCodeAndWait(int keyCode, EventCondition<R> condition, boolean longpress,
|
||||
long timeout) {
|
||||
return mDevice.performActionAndWait(new KeyEventRunnable(keyCode, longpress), condition,
|
||||
timeout);
|
||||
}
|
||||
|
||||
public <R> R pressKeyCodeAndWait(int keyCode, EventCondition<R> condition, long timeout) {
|
||||
return pressKeyCodeAndWait(keyCode, condition, false, timeout);
|
||||
}
|
||||
|
||||
public <R> R pressDPadCenterAndWait(EventCondition<R> condition, long timeout) {
|
||||
return mDevice.performActionAndWait(new KeyEventRunnable(KeyEvent.KEYCODE_DPAD_CENTER),
|
||||
condition, timeout);
|
||||
}
|
||||
|
||||
public <R> R pressEnterAndWait(EventCondition<R> condition, long timeout) {
|
||||
return mDevice.performActionAndWait(new KeyEventRunnable(KeyEvent.KEYCODE_ENTER),
|
||||
condition, timeout);
|
||||
}
|
||||
|
||||
private class KeyEventRunnable implements Runnable {
|
||||
private int mKeyCode;
|
||||
private boolean mLongPress = false;
|
||||
public KeyEventRunnable(int keyCode) {
|
||||
mKeyCode = keyCode;
|
||||
}
|
||||
public KeyEventRunnable(int keyCode, boolean longpress) {
|
||||
mKeyCode = keyCode;
|
||||
mLongPress = longpress;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
if (mLongPress) {
|
||||
longPressKeyCode(mKeyCode);
|
||||
} else {
|
||||
pressKeyCode(mKeyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
36
android/platform_testing/utils/permissions/Android.mk
Normal file
36
android/platform_testing/utils/permissions/Android.mk
Normal file
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := permission-utils-lib
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_JAVA_LIBRARIES := android.test.runner
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||
|
||||
######################################
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_PACKAGE_NAME := PermissionUtils
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
LOCAL_CERTIFICATE := platform
|
||||
|
||||
include $(BUILD_PACKAGE)
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (c) 2015 Google Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.permissionutils">
|
||||
|
||||
<uses-sdk android:minSdkVersion="23"
|
||||
android:targetSdkVersion="23" />
|
||||
|
||||
<uses-permission android:name="android.permission.GRANT_REVOKE_PERMISSIONS" />
|
||||
<uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS" />
|
||||
<uses-permission android:name="android.permission.REVOKE_RUNTIME_PERMISSIONS" />
|
||||
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner" />
|
||||
</application>
|
||||
|
||||
<instrumentation android:name=".PermissionInstrumentation"
|
||||
android:targetPackage="com.android.permissionutils"
|
||||
android:label="Permission Utils">
|
||||
</instrumentation>
|
||||
</manifest>
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* 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.permissionutils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A utility to dump or grant all revoked runtime permissions
|
||||
*/
|
||||
public class GrantPermissionUtil {
|
||||
private static final String LOG_TAG = GrantPermissionUtil.class.getSimpleName();
|
||||
|
||||
public static void grantAllPermissions (Context context) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
for (PackageInfo pkgInfo : getPackageInfos(context)) {
|
||||
List<String> missingPermissions = getMissingPermissions(context, pkgInfo);
|
||||
if (!missingPermissions.isEmpty()) {
|
||||
for (String permission : missingPermissions) {
|
||||
pm.grantRuntimePermission(pkgInfo.packageName, permission, UserHandle.OWNER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void dumpMissingPermissions (Context context) {
|
||||
for (PackageInfo pkgInfo : getPackageInfos(context)) {
|
||||
List<String> missingPermissions = getMissingPermissions(context, pkgInfo);
|
||||
if (!missingPermissions.isEmpty()) {
|
||||
Log.e(LOG_TAG, String.format("Missing permissions for %s", pkgInfo.packageName));
|
||||
for (String permission : missingPermissions) {
|
||||
Log.e(LOG_TAG, " " + permission);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<PackageInfo> getPackageInfos(Context context) {
|
||||
return context.getPackageManager().getInstalledPackages(PackageManager.GET_PERMISSIONS);
|
||||
}
|
||||
|
||||
private static List<String> getMissingPermissions(Context context, PackageInfo info) {
|
||||
// No requested permissions
|
||||
if (info.requestedPermissions == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
List<String> result = new ArrayList<>();
|
||||
PackageManager pm = context.getPackageManager();
|
||||
// Iterate through requested permissions for denied ones
|
||||
for (String permission : info.requestedPermissions) {
|
||||
PermissionInfo pi = null;
|
||||
try {
|
||||
pi = pm.getPermissionInfo(permission, 0);
|
||||
} catch (NameNotFoundException nnfe) {
|
||||
// ignore
|
||||
}
|
||||
if (pi == null) {
|
||||
continue;
|
||||
}
|
||||
if (!isRuntime(pi)) {
|
||||
continue;
|
||||
}
|
||||
int flag = pm.checkPermission(permission, info.packageName);
|
||||
if (flag == PackageManager.PERMISSION_DENIED) {
|
||||
result.add(permission);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean isRuntime(PermissionInfo pi) {
|
||||
return (pi.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
|
||||
== PermissionInfo.PROTECTION_DANGEROUS;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.permissionutils;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.os.Bundle;
|
||||
import com.android.permissionutils.GrantPermissionUtil;
|
||||
|
||||
/**
|
||||
* A utility to dump or grant all revoked runtime permissions
|
||||
*/
|
||||
public class PermissionInstrumentation extends Instrumentation {
|
||||
private static final String PARAM_COMMAND = "command";
|
||||
private static final String COMMAND_DUMP = "dump";
|
||||
private static final String COMMAND_GRANTALL = "grant-all";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle arguments) {
|
||||
super.onCreate(arguments);
|
||||
String command = arguments.getString(PARAM_COMMAND);
|
||||
if (command == null) {
|
||||
throw new IllegalArgumentException("missing command parameter");
|
||||
}
|
||||
if (COMMAND_DUMP.equals(command)) {
|
||||
GrantPermissionUtil.dumpMissingPermissions(getContext());
|
||||
} else if (COMMAND_GRANTALL.equals(command)) {
|
||||
GrantPermissionUtil.grantAllPermissions(getContext());
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("unrecognized command \"%s\"", command));
|
||||
}
|
||||
finish(Activity.RESULT_OK, new Bundle());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# Copyright (C) 2016 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_PACKAGE_NAME := WifiStrengthScannerUtil
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
LOCAL_SDK_VERSION := 23
|
||||
|
||||
include $(BUILD_PACKAGE)
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (c) 2016 Google Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.test.util.wifistrengthscanner">
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-sdk android:minSdkVersion="23"
|
||||
android:targetSdkVersion="23" />
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner" />
|
||||
</application>
|
||||
|
||||
<instrumentation android:name=".WifiStrengthScannerInstrumentation"
|
||||
android:targetPackage="com.android.test.util.wifistrengthscanner"
|
||||
android:label="Dismiss Dialog Util">
|
||||
</instrumentation>
|
||||
</manifest>
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (C) 2016 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.test.util.wifistrengthscanner;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Instrumentation;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.wifi.ScanResult;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class WifiStrengthScannerInstrumentation extends Instrumentation {
|
||||
private static final String TAG = WifiStrengthScannerInstrumentation.class.getCanonicalName();
|
||||
private final static String SD_CARD_PATH =
|
||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
|
||||
private final int NUMBER_OF_WIFI_LEVELS = 101;
|
||||
private final int INVALID_RSSI = -127;
|
||||
private Bundle mArguments;
|
||||
private CountDownLatch mLatch;
|
||||
private boolean scanReceived;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle arguments) {
|
||||
super.onCreate(arguments);
|
||||
mArguments = arguments;
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
try {
|
||||
mLatch = new CountDownLatch(1);
|
||||
getContext().registerReceiver(new WifiScanReceiver(),
|
||||
new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
|
||||
WifiManager wifiManager =
|
||||
(WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
|
||||
scanReceived = false;
|
||||
wifiManager.startScan();
|
||||
mLatch.await(10000, TimeUnit.MILLISECONDS);
|
||||
|
||||
if (!scanReceived) {
|
||||
sendFailureStatus("no_scan_received");
|
||||
finish(Activity.RESULT_CANCELED, new Bundle());
|
||||
return;
|
||||
}
|
||||
|
||||
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("suplicant_state", wifiInfo.getSupplicantState().name());
|
||||
|
||||
String bssid = wifiInfo.getBSSID();
|
||||
bundle.putString("bssid", bssid);
|
||||
// zero counts as a level, so the max level is one less that the number of levels.
|
||||
bundle.putInt("wifi_max_level", NUMBER_OF_WIFI_LEVELS - 1);
|
||||
|
||||
bundle.putInt("wifi_info_wifi_level",
|
||||
WifiManager.calculateSignalLevel(wifiInfo.getRssi(), NUMBER_OF_WIFI_LEVELS));
|
||||
bundle.putInt("wifi_info_rssi", wifiInfo.getRssi());
|
||||
bundle.putInt("wifi_info_frequency", wifiInfo.getFrequency());
|
||||
|
||||
ScanResult result = getScanResult(wifiManager, bssid);
|
||||
if (result != null) {
|
||||
bundle.putInt("scan_result_wifi_level", wifiManager.calculateSignalLevel(result
|
||||
.level, NUMBER_OF_WIFI_LEVELS));
|
||||
bundle.putInt("scan_result_rssi", result.level);
|
||||
bundle.putInt("scan_result_frequency", result.frequency);
|
||||
}
|
||||
|
||||
int dumpsysRssi = getRssiFromDumpsys(bssid);
|
||||
bundle.putInt("dumpsys_rssi", dumpsysRssi);
|
||||
bundle.putInt("dumpsys_wifi_level",
|
||||
WifiManager.calculateSignalLevel(dumpsysRssi, NUMBER_OF_WIFI_LEVELS));
|
||||
sendStatus(Activity.RESULT_OK, bundle);
|
||||
finish(Activity.RESULT_OK, new Bundle());
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
sendFailureStatus("io_exception");
|
||||
finish(Activity.RESULT_CANCELED, new Bundle());
|
||||
} catch (InterruptedException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
sendFailureStatus("interrupted_exception");
|
||||
finish(Activity.RESULT_CANCELED, new Bundle());
|
||||
}
|
||||
}
|
||||
|
||||
private ScanResult getScanResult(WifiManager wifiManager, String bssid) {
|
||||
List<ScanResult> scanResults = wifiManager.getScanResults();
|
||||
for (ScanResult scanResult : scanResults) {
|
||||
if (scanResult.BSSID.equals(bssid)) {
|
||||
return scanResult;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendFailureStatus(String update) {
|
||||
Bundle result = new Bundle();
|
||||
result.putString("wifi_strength_scanner_failure", update);
|
||||
sendStatus(Activity.RESULT_CANCELED, result);
|
||||
}
|
||||
|
||||
private Integer getRssiFromDumpsys(String bssid) throws IOException, InterruptedException {
|
||||
List<String> dumpsysLines = getDumpsysWifiLastScanResults();
|
||||
|
||||
for (int i = 2; i < dumpsysLines.size(); i++) {
|
||||
String line = dumpsysLines.get(i);
|
||||
if (line != null && line.contains(bssid)) {
|
||||
String[] tokens = line.trim().split("\\s\\s+");
|
||||
return Integer.parseInt(tokens[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return INVALID_RSSI;
|
||||
}
|
||||
|
||||
private List<String> getDumpsysWifiLastScanResults() throws IOException, InterruptedException {
|
||||
String dumpsysWifi = executeCommand("dumpsys wifi");
|
||||
String[] lines = dumpsysWifi.split("\n");
|
||||
List<String> scanResults = new ArrayList<>();
|
||||
|
||||
boolean scansStarted = false;
|
||||
for (String line : lines) {
|
||||
if (line.startsWith("Latest scan results:")) {
|
||||
scansStarted = true;
|
||||
}
|
||||
|
||||
if (scansStarted) {
|
||||
if ("".equals(line.trim())) {
|
||||
break;
|
||||
}
|
||||
|
||||
scanResults.add(line);
|
||||
}
|
||||
}
|
||||
|
||||
return scanResults;
|
||||
}
|
||||
|
||||
private String executeCommand(String cmd) throws IOException, InterruptedException {
|
||||
StringBuilder result = new StringBuilder();
|
||||
try {
|
||||
ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(cmd);
|
||||
byte[] buf = new byte[1024];
|
||||
int bytesRead;
|
||||
FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
|
||||
while ((bytesRead = fis.read(buf)) != -1) {
|
||||
result.append(new String(buf, 0, bytesRead));
|
||||
}
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
throw new IOException(String.format("Fails to execute command: %s ", cmd), e);
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private class WifiScanReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d(TAG, "scan results received.");
|
||||
scanReceived = true;
|
||||
mLatch.countDown();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue