Merge "Add more information to existing notification_* events."
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 01e7615..92cb52c 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -114,6 +114,8 @@
" am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am stack list\n" +
" am stack info <STACK_ID>\n" +
+ " am lock-task <TASK_ID>\n" +
+ " am lock-task stop\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
@@ -218,6 +220,8 @@
"\n" +
"am stack info: display the information about activity stack <STACK_ID>.\n" +
"\n" +
+ "am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
+ "\n" +
"<INTENT> specifications include these flags and arguments:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
@@ -309,6 +313,8 @@
runStopUser();
} else if (op.equals("stack")) {
runStack();
+ } else if (op.equals("lock-task")) {
+ runLockTask();
} else {
showError("Error: unknown command '" + op + "'");
}
@@ -1641,4 +1647,19 @@
} catch (RemoteException e) {
}
}
+
+ private void runLockTask() throws Exception {
+ String taskIdStr = nextArgRequired();
+ try {
+ if (taskIdStr.equals("stop")) {
+ mAm.stopLockTaskMode();
+ } else {
+ int taskId = Integer.valueOf(taskIdStr);
+ mAm.startLockTaskMode(taskId);
+ }
+ System.err.println("Activity manager is " + (mAm.isInLockTaskMode() ? "" : "not ") +
+ "in lockTaskMode");
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 287c463..606d803 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5606,6 +5606,22 @@
}
}
+ /** @hide */
+ public void startLockTask() {
+ try {
+ ActivityManagerNative.getDefault().startLockTaskMode(mToken);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /** @hide */
+ public void stopLockTask() {
+ try {
+ ActivityManagerNative.getDefault().stopLockTaskMode();
+ } catch (RemoteException e) {
+ }
+ }
+
/**
* Interface for informing a translucent {@link Activity} once all visible activities below it
* have completed drawing. This is necessary only after an {@link Activity} has been made
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7f7616f..a2183e6 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -155,6 +155,13 @@
public static final int START_SWITCHES_CANCELED = 4;
/**
+ * Result for IActivityManaqer.startActivity: a new activity was attempted to be started
+ * while in Lock Task Mode.
+ * @hide
+ */
+ public static final int START_RETURN_LOCK_TASK_MODE_VIOLATION = 5;
+
+ /**
* Flag for IActivityManaqer.startActivity: do special start mode where
* a new activity is launched only if it is needed.
* @hide
@@ -2232,4 +2239,35 @@
e.printStackTrace(pw);
}
}
+
+ /**
+ * @hide
+ */
+ public void startLockTaskMode(int taskId) {
+ try {
+ ActivityManagerNative.getDefault().startLockTaskMode(taskId);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void stopLockTaskMode() {
+ try {
+ ActivityManagerNative.getDefault().stopLockTaskMode();
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isInLockTaskMode() {
+ try {
+ return ActivityManagerNative.getDefault().isInLockTaskMode();
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index c7c81dd..373a8a3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2097,6 +2097,37 @@
reply.writeStrongBinder(homeActivityToken);
return true;
}
+
+ case START_LOCK_TASK_BY_TASK_ID_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final int taskId = data.readInt();
+ startLockTaskMode(taskId);
+ reply.writeNoException();
+ return true;
+ }
+
+ case START_LOCK_TASK_BY_TOKEN_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ startLockTaskMode(token);
+ reply.writeNoException();
+ return true;
+ }
+
+ case STOP_LOCK_TASK_MODE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ stopLockTaskMode();
+ reply.writeNoException();
+ return true;
+ }
+
+ case IS_IN_LOCK_TASK_MODE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final boolean isInLockTaskMode = isInLockTaskMode();
+ reply.writeNoException();
+ reply.writeInt(isInLockTaskMode ? 1 : 0);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -4820,5 +4851,53 @@
return res;
}
+ @Override
+ public void startLockTaskMode(int taskId) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(taskId);
+ mRemote.transact(START_LOCK_TASK_BY_TASK_ID_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
+ public void startLockTaskMode(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(START_LOCK_TASK_BY_TOKEN_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
+ public void stopLockTaskMode() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(STOP_LOCK_TASK_MODE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
+ public boolean isInLockTaskMode() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(IS_IN_LOCK_TASK_MODE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ boolean isInLockTaskMode = reply.readInt() == 1;
+ data.recycle();
+ reply.recycle();
+ return isInLockTaskMode;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index f2cabf4..cb06a42 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -424,6 +424,18 @@
public IBinder getHomeActivityToken() throws RemoteException;
+ /** @hide */
+ public void startLockTaskMode(int taskId) throws RemoteException;
+
+ /** @hide */
+ public void startLockTaskMode(IBinder token) throws RemoteException;
+
+ /** @hide */
+ public void stopLockTaskMode() throws RemoteException;
+
+ /** @hide */
+ public boolean isInLockTaskMode() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -719,4 +731,8 @@
int GET_TAG_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+210;
int START_USER_IN_BACKGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+211;
int IS_IN_HOME_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+212;
+ int START_LOCK_TASK_BY_TASK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+213;
+ int START_LOCK_TASK_BY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+214;
+ int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215;
+ int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216;
}
diff --git a/core/java/android/hardware/ICameraService.aidl b/core/java/android/hardware/ICameraService.aidl
index 542af6a..4c50dda 100644
--- a/core/java/android/hardware/ICameraService.aidl
+++ b/core/java/android/hardware/ICameraService.aidl
@@ -61,4 +61,12 @@
int removeListener(ICameraServiceListener listener);
int getCameraCharacteristics(int cameraId, out CameraMetadataNative info);
+
+ /**
+ * The java stubs for this method are not intended to be used. Please use
+ * the native stub in frameworks/av/include/camera/ICameraService.h instead.
+ * The BinderHolder output is being used as a placeholder, and will not be
+ * well-formatted in the generated java method.
+ */
+ int getCameraVendorTagDescriptor(out BinderHolder desc);
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 2ac50e4..78e7037 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -48,6 +48,8 @@
*/
public final class CameraManager {
+ private static final String TAG = "CameraManager";
+
/**
* This should match the ICameraService definition
*/
@@ -79,6 +81,19 @@
mCameraService = CameraBinderDecorator.newInstance(cameraServiceRaw);
try {
+ int err = CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor();
+ if (err == CameraBinderDecorator.EOPNOTSUPP) {
+ Log.w(TAG, "HAL version doesn't vendor tags.");
+ } else {
+ CameraBinderDecorator.throwOnError(CameraMetadataNative.
+ nativeSetupGlobalVendorTagDescriptor());
+ }
+ } catch(CameraRuntimeException e) {
+ throw new IllegalStateException("Failed to setup camera vendor tags",
+ e.asChecked());
+ }
+
+ try {
mCameraService.addListener(new CameraServiceListener());
} catch(CameraRuntimeException e) {
throw new IllegalStateException("Failed to register a camera service listener",
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 2ddcb14..0d4a4cb 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -105,6 +105,18 @@
}
/**
+ * Set the global client-side vendor tag descriptor to allow use of vendor
+ * tags in camera applications.
+ *
+ * @return int A native status_t value corresponding to one of the
+ * {@link CameraBinderDecorator} integer constants.
+ * @see CameraBinderDecorator#throwOnError
+ *
+ * @hide
+ */
+ public static native int nativeSetupGlobalVendorTagDescriptor();
+
+ /**
* Set a camera metadata field to a value. The field definitions can be
* found in {@link CameraCharacteristics}, {@link CaptureResult}, and
* {@link CaptureRequest}.
diff --git a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
index e535e00..328ccbe 100644
--- a/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
+++ b/core/java/android/hardware/camera2/utils/CameraBinderDecorator.java
@@ -64,47 +64,7 @@
// int return type => status_t => convert to exception
if (m.getReturnType() == Integer.TYPE) {
int returnValue = (Integer) result;
-
- switch (returnValue) {
- case NO_ERROR:
- return;
- case PERMISSION_DENIED:
- throw new SecurityException("Lacking privileges to access camera service");
- case ALREADY_EXISTS:
- // This should be handled at the call site. Typically this isn't bad,
- // just means we tried to do an operation that already completed.
- return;
- case BAD_VALUE:
- throw new IllegalArgumentException("Bad argument passed to camera service");
- case DEAD_OBJECT:
- UncheckedThrow.throwAnyException(new CameraRuntimeException(
- CAMERA_DISCONNECTED));
- case EACCES:
- UncheckedThrow.throwAnyException(new CameraRuntimeException(
- CAMERA_DISABLED));
- case EBUSY:
- UncheckedThrow.throwAnyException(new CameraRuntimeException(
- CAMERA_IN_USE));
- case EUSERS:
- UncheckedThrow.throwAnyException(new CameraRuntimeException(
- MAX_CAMERAS_IN_USE));
- case ENODEV:
- UncheckedThrow.throwAnyException(new CameraRuntimeException(
- CAMERA_DISCONNECTED));
- case EOPNOTSUPP:
- UncheckedThrow.throwAnyException(new CameraRuntimeException(
- CAMERA_DEPRECATED_HAL));
- }
-
- /**
- * Trap the rest of the negative return values. If we have known
- * error codes i.e. ALREADY_EXISTS that aren't really runtime
- * errors, then add them to the top switch statement
- */
- if (returnValue < 0) {
- throw new UnsupportedOperationException(String.format("Unknown error %d",
- returnValue));
- }
+ throwOnError(returnValue);
}
}
@@ -131,6 +91,54 @@
}
/**
+ * Throw error codes returned by the camera service as exceptions.
+ *
+ * @param errorFlag error to throw as an exception.
+ */
+ public static void throwOnError(int errorFlag) {
+ switch (errorFlag) {
+ case NO_ERROR:
+ return;
+ case PERMISSION_DENIED:
+ throw new SecurityException("Lacking privileges to access camera service");
+ case ALREADY_EXISTS:
+ // This should be handled at the call site. Typically this isn't bad,
+ // just means we tried to do an operation that already completed.
+ return;
+ case BAD_VALUE:
+ throw new IllegalArgumentException("Bad argument passed to camera service");
+ case DEAD_OBJECT:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISCONNECTED));
+ case EACCES:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISABLED));
+ case EBUSY:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_IN_USE));
+ case EUSERS:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ MAX_CAMERAS_IN_USE));
+ case ENODEV:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DISCONNECTED));
+ case EOPNOTSUPP:
+ UncheckedThrow.throwAnyException(new CameraRuntimeException(
+ CAMERA_DEPRECATED_HAL));
+ }
+
+ /**
+ * Trap the rest of the negative return values. If we have known
+ * error codes i.e. ALREADY_EXISTS that aren't really runtime
+ * errors, then add them to the top switch statement
+ */
+ if (errorFlag < 0) {
+ throw new UnsupportedOperationException(String.format("Unknown error %d",
+ errorFlag));
+ }
+ }
+
+ /**
* <p>
* Wraps the type T with a proxy that will check 'status_t' return codes
* from the native side of the camera service, and throw Java exceptions
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 10fd2f0..26d7f5f 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -270,7 +270,6 @@
boolean mWifiOn;
StopwatchTimer mWifiOnTimer;
- int mWifiOnUid = -1;
boolean mGlobalWifiRunning;
StopwatchTimer mGlobalWifiRunningTimer;
@@ -2912,10 +2911,6 @@
mWifiOn = false;
mWifiOnTimer.stopRunningLocked(elapsedRealtime);
}
- if (mWifiOnUid >= 0) {
- getUidStatsLocked(mWifiOnUid).noteWifiStoppedLocked(elapsedRealtime);
- mWifiOnUid = -1;
- }
}
public void noteAudioOnLocked(int uid) {
@@ -5973,7 +5968,7 @@
if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
- final Uid u = getUidStatsLocked(entry.uid);
+ final Uid u = getUidStatsLocked(mapUid(entry.uid));
u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
@@ -6040,7 +6035,7 @@
if (entry.rxBytes == 0 || entry.txBytes == 0) continue;
- final Uid u = getUidStatsLocked(entry.uid);
+ final Uid u = getUidStatsLocked(mapUid(entry.uid));
u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
entry.rxPackets);
u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
@@ -6240,6 +6235,7 @@
* if needed.
*/
public Uid.Proc getProcessStatsLocked(int uid, String name) {
+ uid = mapUid(uid);
Uid u = getUidStatsLocked(uid);
return u.getProcessStatsLocked(name);
}
@@ -6249,6 +6245,7 @@
* if needed.
*/
public Uid.Pkg getPackageStatsLocked(int uid, String pkg) {
+ uid = mapUid(uid);
Uid u = getUidStatsLocked(uid);
return u.getPackageStatsLocked(pkg);
}
@@ -6258,6 +6255,7 @@
* if needed.
*/
public Uid.Pkg.Serv getServiceStatsLocked(int uid, String pkg, String name) {
+ uid = mapUid(uid);
Uid u = getUidStatsLocked(uid);
return u.getServiceStatsLocked(pkg, name);
}
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 3c7da1e..8c15ac25 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -19,13 +19,18 @@
// #define LOG_NNDEBUG 0
#define LOG_TAG "CameraMetadata-JNI"
#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <string.h>
#include "jni.h"
#include "JNIHelp.h"
#include "android_os_Parcel.h"
#include "android_runtime/AndroidRuntime.h"
+#include <binder/IServiceManager.h>
#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/VendorTagDescriptor.h>
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>
@@ -112,6 +117,7 @@
static void CameraMetadata_classInit(JNIEnv *env, jobject thiz);
static jint CameraMetadata_getTagFromKey(JNIEnv *env, jobject thiz, jstring keyName);
static jint CameraMetadata_getTypeFromTag(JNIEnv *env, jobject thiz, jint tag);
+static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz);
// Less safe access to native pointer. Does NOT throw any Java exceptions if NULL.
static CameraMetadata* CameraMetadata_getPointerNoThrow(JNIEnv *env, jobject thiz) {
@@ -372,6 +378,9 @@
{ "nativeGetTypeFromTag",
"(I)I",
(void *)CameraMetadata_getTypeFromTag },
+ { "nativeSetupGlobalVendorTagDescriptor",
+ "()I",
+ (void*)CameraMetadata_setupGlobalVendorTagDescriptor },
// instance methods
{ "nativeAllocate",
"()J",
@@ -556,4 +565,29 @@
return tagType;
}
+static jint CameraMetadata_setupGlobalVendorTagDescriptor(JNIEnv *env, jobject thiz) {
+ const String16 NAME("media.camera");
+ sp<ICameraService> cameraService;
+ status_t err = getService(NAME, /*out*/&cameraService);
+
+ if (err != OK) {
+ ALOGE("%s: Failed to get camera service, received error %s (%d)", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ sp<VendorTagDescriptor> desc;
+ err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
+
+ if (err != OK) {
+ ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)", __FUNCTION__,
+ strerror(-err), err);
+ return err;
+ }
+
+ err = VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
+
+ return err;
+}
+
} // extern "C"
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cfd4a63..4656f32 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1212,6 +1212,10 @@
<!-- Whether UI for multi user should be shown -->
<bool name="config_enableMultiUserUI">false</bool>
+ <!-- If true, then we do not ask user for permission for apps to connect to USB devices.
+ Do not set this to true for production devices. Doing so will cause you to fail CTS. -->
+ <bool name="config_disableUsbPermissionDialogs">false</bool>
+
<!-- Minimum span needed to begin a touch scaling gesture.
If the span is equal to or greater than this size, a scaling gesture
will begin, where supported. (See android.view.ScaleGestureDetector)
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6624da4..efa873d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -290,6 +290,7 @@
<java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
<java-symbol type="bool" name="config_enableMultiUserUI"/>
+ <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 128f636..cd9c920 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7047,11 +7047,11 @@
* TODO: Add mController hook
*/
@Override
- public void moveTaskToFront(int task, int flags, Bundle options) {
+ public void moveTaskToFront(int taskId, int flags, Bundle options) {
enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
"moveTaskToFront()");
- if (DEBUG_STACK) Slog.d(TAG, "moveTaskToFront: moving task=" + task);
+ if (DEBUG_STACK) Slog.d(TAG, "moveTaskToFront: moving taskId=" + taskId);
synchronized(this) {
if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
Binder.getCallingUid(), "Task to front")) {
@@ -7060,6 +7060,14 @@
}
final long origId = Binder.clearCallingIdentity();
try {
+ final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ if (task == null) {
+ return;
+ }
+ if (mStackSupervisor.isLockTaskModeViolation(task)) {
+ Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
+ return;
+ }
mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options);
} finally {
Binder.restoreCallingIdentity(origId);
@@ -7269,6 +7277,85 @@
}
}
+ private boolean isLockTaskAuthorized(ComponentName name) {
+// enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
+// "startLockTaskMode()");
+// DevicePolicyManager dpm = (DevicePolicyManager)
+// mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+// return dpm != null && dpm.isLockTaskPermitted(name);
+ return true;
+ }
+
+ private void startLockTaskMode(TaskRecord task) {
+ if (!isLockTaskAuthorized(task.intent.getComponent())) {
+ return;
+ }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ // Since we lost lock on task, make sure it is still there.
+ task = mStackSupervisor.anyTaskForIdLocked(task.taskId);
+ if (task != null) {
+ mStackSupervisor.setLockTaskModeLocked(task);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public void startLockTaskMode(int taskId) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ final TaskRecord task;
+ synchronized (this) {
+ task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ }
+ if (task != null) {
+ startLockTaskMode(task);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public void startLockTaskMode(IBinder token) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ final TaskRecord task;
+ synchronized (this) {
+ final ActivityRecord r = ActivityRecord.forToken(token);
+ if (r == null) {
+ return;
+ }
+ task = r.task;
+ }
+ if (task != null) {
+ startLockTaskMode(task);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override
+ public void stopLockTaskMode() {
+// enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
+// "stopLockTaskMode()");
+ synchronized (this) {
+ mStackSupervisor.setLockTaskModeLocked(null);
+ }
+ }
+
+ @Override
+ public boolean isInLockTaskMode() {
+ synchronized (this) {
+ return mStackSupervisor.isInLockTaskMode();
+ }
+ }
+
// =========================================================
// THUMBNAILS
// =========================================================
@@ -16186,6 +16273,8 @@
return true;
}
+ mStackSupervisor.setLockTaskModeLocked(null);
+
final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId);
if (userInfo == null) {
Slog.w(TAG, "No user info for user #" + userId);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 087ad83c..34cc22a 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -36,8 +36,6 @@
import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
-import android.os.Trace;
-import android.util.Log;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -2478,13 +2476,14 @@
}
r.makeFinishing();
+ final TaskRecord task = r.task;
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
r.userId, System.identityHashCode(r),
- r.task.taskId, r.shortComponentName, reason);
- final ArrayList<ActivityRecord> activities = r.task.mActivities;
+ task.taskId, r.shortComponentName, reason);
+ final ArrayList<ActivityRecord> activities = task.mActivities;
final int index = activities.indexOf(r);
if (index < (activities.size() - 1)) {
- r.task.setFrontOfTask();
+ task.setFrontOfTask();
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
// If the caller asked that this activity (and all above it)
// be cleared when the task is reset, don't lose that information,
@@ -2524,6 +2523,9 @@
startPausingLocked(false, false);
}
+ if (endTask) {
+ mStackSupervisor.endLockTaskModeIfTaskEnding(task);
+ }
} else if (r.state != ActivityState.PAUSING) {
// If the activity is PAUSING, we will complete the finish once
// it is done pausing; else we can just directly finish it here.
@@ -3088,23 +3090,6 @@
}
}
- final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
- final TaskRecord task = taskForIdLocked(taskId);
- if (task != null) {
- if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
- mStackSupervisor.mUserLeaving = true;
- }
- if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
- // Caller wants the home activity moved with it. To accomplish this,
- // we'll just indicate that this task returns to the home task.
- task.mOnTopOfHome = true;
- }
- moveTaskToFrontLocked(task, null, options);
- return true;
- }
- return false;
- }
-
final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
@@ -3162,7 +3147,15 @@
* @return Returns true if the move completed, false if not.
*/
final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
- Slog.i(TAG, "moveTaskToBack: " + taskId);
+ final TaskRecord tr = taskForIdLocked(taskId);
+ if (tr == null) {
+ Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
+ return false;
+ }
+
+ Slog.i(TAG, "moveTaskToBack: " + tr);
+
+ mStackSupervisor.endLockTaskModeIfTaskEnding(tr);
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
@@ -3190,11 +3183,6 @@
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare to back transition: task=" + taskId);
- final TaskRecord tr = taskForIdLocked(taskId);
- if (tr == null) {
- return false;
- }
-
mTaskHistory.remove(tr);
mTaskHistory.add(0, tr);
@@ -3678,6 +3666,7 @@
}
void removeTask(TaskRecord task) {
+ mStackSupervisor.endLockTaskModeIfTaskEnding(task);
mWindowManager.removeTask(task.taskId);
final ActivityRecord r = mResumedActivity;
if (r != null && r.task == task) {
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b2cf846..9315648 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -231,6 +231,10 @@
InputManagerInternal mInputManagerInternal;
+ /** If non-null then the task specified remains in front and no other tasks may be started
+ * until the task exits or #stopLockTaskMode() is called. */
+ private TaskRecord mLockTaskModeTask;
+
public ActivityStackSupervisor(ActivityManagerService service) {
mService = service;
PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
@@ -1505,6 +1509,10 @@
? findTaskLocked(r)
: findActivityLocked(intent, r.info);
if (intentActivity != null) {
+ if (isLockTaskModeViolation(intentActivity.task)) {
+ Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
+ return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ }
if (r.task == null) {
r.task = intentActivity.task;
}
@@ -1715,6 +1723,10 @@
// Should this be considered a new task?
if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+ if (isLockTaskModeViolation(reuseTask)) {
+ Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
+ return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ }
targetStack = adjustStackFocus(r);
targetStack.moveToFront();
if (reuseTask == null) {
@@ -1739,6 +1751,10 @@
}
} else if (sourceRecord != null) {
TaskRecord sourceTask = sourceRecord.task;
+ if (isLockTaskModeViolation(sourceTask)) {
+ Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
+ return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ }
targetStack = sourceTask.stack;
targetStack.moveToFront();
if (!addingToTask &&
@@ -1782,6 +1798,10 @@
// An existing activity is starting this new activity, so we want
// to keep the new one in the same task as the one that is starting
// it.
+ if (isLockTaskModeViolation(sourceTask)) {
+ Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
+ return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ }
r.setTask(sourceTask, sourceRecord.thumbHolder, false);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in existing task " + r.task + " from source " + sourceRecord);
@@ -2098,17 +2118,18 @@
}
}
- void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- if (stacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
- if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
- + stacks.get(stackNdx));
- return;
- }
- }
+ void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options) {
+ if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
+ mUserLeaving = true;
}
+ if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
+ // Caller wants the home activity moved with it. To accomplish this,
+ // we'll just indicate that this task returns to the home task.
+ task.mOnTopOfHome = true;
+ }
+ task.stack.moveTaskToFrontLocked(task, null, options);
+ if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
+ + task.stack);
}
ActivityStack getStack(int stackId) {
@@ -2288,6 +2309,7 @@
}
}
checkReadyForSleepLocked();
+ setLockTaskModeLocked(null);
}
boolean shutdownLocked(int timeout) {
@@ -2872,6 +2894,35 @@
return list;
}
+ void setLockTaskModeLocked(TaskRecord task) {
+ if (task == null) {
+ // Take out of lock task mode.
+ mLockTaskModeTask = null;
+ return;
+ }
+ if (isLockTaskModeViolation(task)) {
+ Slog.e(TAG, "setLockTaskMode: Attempt to start a second Lock Task Mode task.");
+ return;
+ }
+ mLockTaskModeTask = task;
+ findTaskToMoveToFrontLocked(task, 0, null);
+ resumeTopActivitiesLocked();
+ }
+
+ boolean isLockTaskModeViolation(TaskRecord task) {
+ return mLockTaskModeTask != null && mLockTaskModeTask != task;
+ }
+
+ void endLockTaskModeIfTaskEnding(TaskRecord task) {
+ if (mLockTaskModeTask != null && mLockTaskModeTask == task) {
+ mLockTaskModeTask = null;
+ }
+ }
+
+ boolean isInLockTaskMode() {
+ return mLockTaskModeTask != null;
+ }
+
private final class ActivityStackSupervisorHandler extends Handler {
public ActivityStackSupervisorHandler(Looper looper) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index df06bae..81af636 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -165,11 +165,11 @@
int newFlags, String newTag, String newPackageName, int newOwnerUid,
int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) {
- final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
- final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
- boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
- && ownerUid == Process.SYSTEM_UID;
if (workSource != null && newWorkSource != null) {
+ final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
+ final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
+ boolean unimportantForLogging = (newFlags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
+ && newOwnerUid == Process.SYSTEM_UID;
if (DEBUG) {
Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
+ "\", packageName=" + newPackageName
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index ff4857b..37b5c51 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -27,6 +27,7 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
@@ -73,6 +74,7 @@
private final UserHandle mUser;
private final AtomicFile mSettingsFile;
+ private final boolean mDisablePermissionDialogs;
private final Context mContext;
private final Context mUserContext;
@@ -510,6 +512,9 @@
Environment.getUserSystemDirectory(user.getIdentifier()),
"usb_device_manager.xml"));
+ mDisablePermissionDialogs = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_disableUsbPermissionDialogs);
+
synchronized (mLock) {
if (UserHandle.OWNER.equals(user)) {
upgradeSingleUserLocked();
@@ -815,6 +820,14 @@
(rInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
defaultRI = rInfo;
}
+
+ if (mDisablePermissionDialogs) {
+ // bypass dialog and launch the only matching activity
+ rInfo = matches.get(0);
+ if (rInfo.activityInfo != null) {
+ defaultPackage = rInfo.activityInfo.packageName;
+ }
+ }
}
if (defaultRI == null && defaultPackage != null) {
@@ -970,7 +983,7 @@
public boolean hasPermission(UsbDevice device) {
synchronized (mLock) {
int uid = Binder.getCallingUid();
- if (uid == Process.SYSTEM_UID) {
+ if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
return true;
}
SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
@@ -984,7 +997,7 @@
public boolean hasPermission(UsbAccessory accessory) {
synchronized (mLock) {
int uid = Binder.getCallingUid();
- if (uid == Process.SYSTEM_UID) {
+ if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
return true;
}
SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);