diff options
Diffstat (limited to 'core/java')
53 files changed, 877 insertions, 452 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 3001c2c..aa7692b 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -489,7 +489,8 @@ public class AccountManager { * <p>It is safe to call this method from the main thread. * * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#GET_ACCOUNTS}. + * {@link android.Manifest.permission#GET_ACCOUNTS} or share a uid with the + * authenticator that owns the account type. * * @param type The type of accounts to return, null to retrieve all accounts * @return An array of {@link Account}, one per matching account. Empty @@ -615,7 +616,8 @@ public class AccountManager { * {@link AccountManagerFuture} must not be used on the main thread. * * <p>This method requires the caller to hold the permission - * {@link android.Manifest.permission#GET_ACCOUNTS}. + * {@link android.Manifest.permission#GET_ACCOUNTS} or share a uid with the + * authenticator that owns the account type. * * @param type The type of accounts to return, must not be null * @param features An array of the account features to require, diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index e8ab109..9c2e208 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6473,20 +6473,22 @@ public class Activity extends ContextThemeWrapper } private void dispatchRequestPermissionsResult(int requestCode, Intent data) { - String[] permissions = data.getStringArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); - final int[] grantResults = data.getIntArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS); + // If the package installer crashed we may have not data - best effort. + String[] permissions = (data != null) ? data.getStringArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0]; + final int[] grantResults = (data != null) ? data.getIntArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0]; onRequestPermissionsResult(requestCode, permissions, grantResults); } private void dispatchRequestPermissionsResultToFragment(int requestCode, Intent data, - Fragment fragement) { - String[] permissions = data.getStringArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES); - final int[] grantResults = data.getIntArrayExtra( - PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS); - fragement.onRequestPermissionsResult(requestCode, permissions, grantResults); + Fragment fragment) { + // If the package installer crashed we may have not data - best effort. + String[] permissions = (data != null) ? data.getStringArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_NAMES) : new String[0]; + final int[] grantResults = (data != null) ? data.getIntArrayExtra( + PackageManager.EXTRA_REQUEST_PERMISSIONS_RESULTS) : new int[0]; + fragment.onRequestPermissionsResult(requestCode, permissions, grantResults); } class HostCallbacks extends FragmentHostCallback<Activity> { diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 2bb4e76..cc93ac9 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -921,8 +921,9 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IApplicationThread app = ApplicationThreadNative.asInterface(b); Intent service = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); + String callingPackage = data.readString(); int userId = data.readInt(); - ComponentName cn = startService(app, service, resolvedType, userId); + ComponentName cn = startService(app, service, resolvedType, callingPackage, userId); reply.writeNoException(); ComponentName.writeToParcel(cn, reply); return true; @@ -976,9 +977,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM String resolvedType = data.readString(); b = data.readStrongBinder(); int fl = data.readInt(); + String callingPackage = data.readString(); int userId = data.readInt(); IServiceConnection conn = IServiceConnection.Stub.asInterface(b); - int res = bindService(app, token, service, resolvedType, conn, fl, userId); + int res = bindService(app, token, service, resolvedType, conn, fl, + callingPackage, userId); reply.writeNoException(); reply.writeInt(res); return true; @@ -1568,7 +1571,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM data.enforceInterface(IActivityManager.descriptor); Intent service = Intent.CREATOR.createFromParcel(data); String resolvedType = data.readString(); - IBinder binder = peekService(service, resolvedType); + String callingPackage = data.readString(); + IBinder binder = peekService(service, resolvedType, callingPackage); reply.writeNoException(); reply.writeStrongBinder(binder); return true; @@ -3638,7 +3642,7 @@ class ActivityManagerProxy implements IActivityManager } public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, int userId) throws RemoteException + String resolvedType, String callingPackage, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); @@ -3646,6 +3650,7 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder(caller != null ? caller.asBinder() : null); service.writeToParcel(data, 0); data.writeString(resolvedType); + data.writeString(callingPackage); data.writeInt(userId); mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); @@ -3708,7 +3713,7 @@ class ActivityManagerProxy implements IActivityManager } public int bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, - int flags, int userId) throws RemoteException { + int flags, String callingPackage, int userId) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -3718,6 +3723,7 @@ class ActivityManagerProxy implements IActivityManager data.writeString(resolvedType); data.writeStrongBinder(connection.asBinder()); data.writeInt(flags); + data.writeString(callingPackage); data.writeInt(userId); mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); @@ -3783,12 +3789,14 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } - public IBinder peekService(Intent service, String resolvedType) throws RemoteException { + public IBinder peekService(Intent service, String resolvedType, String callingPackage) + throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); service.writeToParcel(data, 0); data.writeString(resolvedType); + data.writeString(callingPackage); mRemote.transact(PEEK_SERVICE_TRANSACTION, data, reply, 0); reply.readException(); IBinder binder = reply.readStrongBinder(); diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 9faadd3..bf3bfae 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1082,13 +1082,18 @@ public class AppOpsManager { private final long mTime; private final long mRejectTime; private final int mDuration; + private final int mProxyUid; + private final String mProxyPackageName; - public OpEntry(int op, int mode, long time, long rejectTime, int duration) { + public OpEntry(int op, int mode, long time, long rejectTime, int duration, + int proxyUid, String proxyPackage) { mOp = op; mMode = mode; mTime = time; mRejectTime = rejectTime; mDuration = duration; + mProxyUid = proxyUid; + mProxyPackageName = proxyPackage; } public int getOp() { @@ -1115,6 +1120,14 @@ public class AppOpsManager { return mDuration == -1 ? (int)(System.currentTimeMillis()-mTime) : mDuration; } + public int getProxyUid() { + return mProxyUid; + } + + public String getProxyPackageName() { + return mProxyPackageName; + } + @Override public int describeContents() { return 0; @@ -1127,6 +1140,8 @@ public class AppOpsManager { dest.writeLong(mTime); dest.writeLong(mRejectTime); dest.writeInt(mDuration); + dest.writeInt(mProxyUid); + dest.writeString(mProxyPackageName); } OpEntry(Parcel source) { @@ -1135,6 +1150,8 @@ public class AppOpsManager { mTime = source.readLong(); mRejectTime = source.readLong(); mDuration = source.readInt(); + mProxyUid = source.readInt(); + mProxyPackageName = source.readString(); } public static final Creator<OpEntry> CREATOR = new Creator<OpEntry>() { @@ -1379,6 +1396,33 @@ public class AppOpsManager { } /** + * Make note of an application performing an operation on behalf of another + * application when handling an IPC. Note that you must pass the package name + * of the application that is being proxied while its UID will be inferred from + * the IPC state; this function will verify that the calling uid and proxied + * package name match, and if not, return {@link #MODE_IGNORED}. If this call + * succeeds, the last execution time of the operation for the proxied app and + * your app will be updated to the current time. + * @param op The operation to note. One of the OPSTR_* constants. + * @param proxiedPackageName The name of the application calling into the proxy application. + * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or + * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without + * causing the app to crash). + * @throws SecurityException If the app has been configured to crash on this op. + */ + public int noteProxyOp(String op, String proxiedPackageName) { + return noteProxyOp(strOpToOp(op), proxiedPackageName); + } + + /** + * Like {@link #noteProxyOp(String, String)} but instead + * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + */ + public int noteProxyOpNoThrow(String op, String proxiedPackageName) { + return noteProxyOpNoThrow(strOpToOp(op), proxiedPackageName); + } + + /** * Report that an application has started executing a long-running operation. Note that you * must pass in both the uid and name of the application to be checked; this function will * verify that these two match, and if not, return {@link #MODE_IGNORED}. If this call @@ -1455,7 +1499,7 @@ public class AppOpsManager { return mService.checkOperation(op, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @@ -1501,7 +1545,7 @@ public class AppOpsManager { return mService.checkAudioOperation(op, stream, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @@ -1532,6 +1576,49 @@ public class AppOpsManager { } /** + * Make note of an application performing an operation on behalf of another + * application when handling an IPC. Note that you must pass the package name + * of the application that is being proxied while its UID will be inferred from + * the IPC state; this function will verify that the calling uid and proxied + * package name match, and if not, return {@link #MODE_IGNORED}. If this call + * succeeds, the last execution time of the operation for the proxied app and + * your app will be updated to the current time. + * @param op The operation to note. One of the OPSTR_* constants. + * @param proxiedPackageName The name of the application calling into the proxy application. + * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or + * {@link #MODE_IGNORED} if it is not allowed and should be silently ignored (without + * causing the app to crash). + * @throws SecurityException If the proxy or proxied app has been configured to + * crash on this op. + * + * @hide + */ + public int noteProxyOp(int op, String proxiedPackageName) { + int mode = noteProxyOpNoThrow(op, proxiedPackageName); + if (mode == MODE_ERRORED) { + throw new SecurityException("Proxy package " + mContext.getOpPackageName() + + " from uid " + Process.myUid() + " or calling package " + + proxiedPackageName + " from uid " + Binder.getCallingUid() + + " not allowed to perform " + sOpNames[op]); + } + return mode; + } + + /** + * Like {@link #noteProxyOp(int, String)} but instead + * of throwing a {@link SecurityException} it returns {@link #MODE_ERRORED}. + * @hide + */ + public int noteProxyOpNoThrow(int op, String proxiedPackageName) { + try { + return mService.noteProxyOperation(op, mContext.getOpPackageName(), + Binder.getCallingUid(), proxiedPackageName); + } catch (RemoteException e) { + } + return MODE_ERRORED; + } + + /** * Like {@link #noteOp} but instead of throwing a {@link SecurityException} it * returns {@link #MODE_ERRORED}. * @hide @@ -1541,7 +1628,7 @@ public class AppOpsManager { return mService.noteOperation(op, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @hide */ @@ -1603,7 +1690,7 @@ public class AppOpsManager { return mService.startOperation(getToken(mService), op, uid, packageName); } catch (RemoteException e) { } - return MODE_IGNORED; + return MODE_ERRORED; } /** @hide */ diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 0420fb6..6639486 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -1202,8 +1202,8 @@ class ContextImpl extends Context { validateServiceIntent(service); service.prepareToLeaveProcess(); ComponentName cn = ActivityManagerNative.getDefault().startService( - mMainThread.getApplicationThread(), service, - service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier()); + mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded( + getContentResolver()), getOpPackageName(), user.getIdentifier()); if (cn != null) { if (cn.getPackageName().equals("!")) { throw new SecurityException( @@ -1279,9 +1279,9 @@ class ContextImpl extends Context { } service.prepareToLeaveProcess(); int res = ActivityManagerNative.getDefault().bindService( - mMainThread.getApplicationThread(), getActivityToken(), - service, service.resolveTypeIfNeeded(getContentResolver()), - sd, flags, user.getIdentifier()); + mMainThread.getApplicationThread(), getActivityToken(), service, + service.resolveTypeIfNeeded(getContentResolver()), + sd, flags, getOpPackageName(), user.getIdentifier()); if (res < 0) { throw new SecurityException( "Not allowed to bind to service " + service); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 1423e4b..acce81c 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -160,16 +160,16 @@ public interface IActivityManager extends IInterface { public PendingIntent getRunningServiceControlPanel(ComponentName service) throws RemoteException; public ComponentName startService(IApplicationThread caller, Intent service, - String resolvedType, int userId) throws RemoteException; + String resolvedType, String callingPackage, int userId) throws RemoteException; public int stopService(IApplicationThread caller, Intent service, String resolvedType, int userId) throws RemoteException; public boolean stopServiceToken(ComponentName className, IBinder token, int startId) throws RemoteException; public void setServiceForeground(ComponentName className, IBinder token, int id, Notification notification, boolean keepNotification) throws RemoteException; - public int bindService(IApplicationThread caller, IBinder token, - Intent service, String resolvedType, - IServiceConnection connection, int flags, int userId) throws RemoteException; + public int bindService(IApplicationThread caller, IBinder token, Intent service, + String resolvedType, IServiceConnection connection, int flags, + String callingPackage, int userId) throws RemoteException; public boolean unbindService(IServiceConnection connection) throws RemoteException; public void publishService(IBinder token, Intent intent, IBinder service) throws RemoteException; @@ -178,7 +178,8 @@ public interface IActivityManager extends IInterface { /* oneway */ public void serviceDoneExecuting(IBinder token, int type, int startId, int res) throws RemoteException; - public IBinder peekService(Intent service, String resolvedType) throws RemoteException; + public IBinder peekService(Intent service, String resolvedType, String callingPackage) + throws RemoteException; public boolean bindBackupAgent(ApplicationInfo appInfo, int backupRestoreMode) throws RemoteException; diff --git a/core/java/android/app/assist/AssistContent.java b/core/java/android/app/assist/AssistContent.java index 07b2d57..cddf47a 100644 --- a/core/java/android/app/assist/AssistContent.java +++ b/core/java/android/app/assist/AssistContent.java @@ -12,7 +12,6 @@ import android.os.Parcelable; * assistant at the user's request. This is filled in by * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. */ -@Deprecated public class AssistContent implements Parcelable { private boolean mIsAppProvidedIntent = false; private Intent mIntent; diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java index af74e73..2260d7e 100644 --- a/core/java/android/content/BroadcastReceiver.java +++ b/core/java/android/content/BroadcastReceiver.java @@ -524,7 +524,7 @@ public abstract class BroadcastReceiver { try { service.prepareToLeaveProcess(); binder = am.peekService(service, service.resolveTypeIfNeeded( - myContext.getContentResolver())); + myContext.getContentResolver()), myContext.getOpPackageName()); } catch (RemoteException e) { } return binder; diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index d4c4437..3cc7684 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -475,18 +475,38 @@ public abstract class ContentProvider implements ComponentCallbacks2 { private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceReadPermissionInner(uri, callerToken); + + final int permOp = AppOpsManager.permissionToOpCode(mReadPermission); + if (permOp != AppOpsManager.OP_NONE) { + final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); + if (mode != AppOpsManager.MODE_ALLOWED) { + return mode; + } + } + if (mReadOp != AppOpsManager.OP_NONE) { - return mAppOpsManager.noteOp(mReadOp, Binder.getCallingUid(), callingPkg); + return mAppOpsManager.noteProxyOp(mReadOp, callingPkg); } + return AppOpsManager.MODE_ALLOWED; } private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken) throws SecurityException { enforceWritePermissionInner(uri, callerToken); + + final int permOp = AppOpsManager.permissionToOpCode(mWritePermission); + if (permOp != AppOpsManager.OP_NONE) { + final int mode = mAppOpsManager.noteProxyOp(permOp, callingPkg); + if (mode != AppOpsManager.MODE_ALLOWED) { + return mode; + } + } + if (mWriteOp != AppOpsManager.OP_NONE) { - return mAppOpsManager.noteOp(mWriteOp, Binder.getCallingUid(), callingPkg); + return mAppOpsManager.noteProxyOp(mWriteOp, callingPkg); } + return AppOpsManager.MODE_ALLOWED; } } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index b1d80f0..c9f9b56 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -6181,8 +6181,12 @@ public class Intent implements Parcelable, Cloneable { * who sent the intent. * @hide */ - public void setContentUserHint(int contentUserHint) { - mContentUserHint = contentUserHint; + public void prepareToLeaveUser(int userId) { + // If mContentUserHint is not UserHandle.USER_CURRENT, the intent has already left a user. + // We want mContentUserHint to refer to the original user, so don't do anything. + if (mContentUserHint == UserHandle.USER_CURRENT) { + mContentUserHint = userId; + } } /** diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index dbaba49..ea08956 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -39,6 +39,20 @@ public abstract class PackageManagerInternal { } /** + * Provider for package names. + */ + public interface SyncAdapterPackagesProvider { + + /** + * Gets the sync adapter packages for given authority and user. + * @param authority The authority. + * @param userId The user id. + * @return The package names. + */ + public String[] getPackages(String authority, int userId); + } + + /** * Sets the location provider packages provider. * @param provider The packages provider. */ @@ -69,6 +83,12 @@ public abstract class PackageManagerInternal { public abstract void setDialerAppPackagesProvider(PackagesProvider provider); /** + * Sets the sync adapter packages provider. + * @param provider The provider. + */ + public abstract void setSyncAdapterPackagesprovider(SyncAdapterPackagesProvider provider); + + /** * Requests granting of the default permissions to the current default SMS app. * @param packageName The default SMS package name. * @param userId The user for which to grant the permissions. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index faf71ee..64376c1 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1505,7 +1505,8 @@ public class PackageParser { if (!parseUsesPermission(pkg, res, parser, attrs)) { return null; } - } else if (tagName.equals("uses-permission-sdk-m")) { + } else if (tagName.equals("uses-permission-sdk-m") + || tagName.equals("uses-permission-sdk-23")) { if (!parseUsesPermission(pkg, res, parser, attrs)) { return null; } diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 04dbff2..0a1f148 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -76,6 +76,13 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { public static final int PROTECTION_FLAG_APPOP = 0x40; /** + * Additional flag for {@link #protectionLevel}, corresponding + * to the <code>pre23</code> value of + * {@link android.R.attr#protectionLevel}. + */ + public static final int PROTECTION_FLAG_PRE23 = 0x80; + + /** * Mask for {@link #protectionLevel}: the basic protection type. */ public static final int PROTECTION_MASK_BASE = 0xf; @@ -171,6 +178,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable { if ((level&PermissionInfo.PROTECTION_FLAG_APPOP) != 0) { protLevel += "|appop"; } + if ((level&PermissionInfo.PROTECTION_FLAG_PRE23) != 0) { + protLevel += "|pre23"; + } return protLevel; } diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index d6b1142..d456b5e 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -1568,47 +1568,41 @@ public abstract class SensorManager { /** * For testing purposes only. Not for third party applications. * - * Enable data injection mode in sensor service. This mode is - * expected to be used only for testing purposes. If the HAL is - * set to data injection mode, it will ignore the input from - * physical sensors and read sensor data that is injected from - * the test application. This mode is used for testing vendor - * implementations for various algorithms like Rotation Vector, - * Significant Motion, Step Counter etc. - * - * The tests which call this API need to have {@code - * android.permission.LOCATION_HADWARE} permission which isn't - * available for third party applications. - * - * @param enable True to set the HAL in DATA_INJECTION mode. - * False to reset the HAL back to NORMAL mode. + * Initialize data injection mode and create a client for data injection. SensorService should + * already be operating in DATA_INJECTION mode for this call succeed. To set SensorService into + * DATA_INJECTION mode "adb shell dumpsys sensorservice data_injection" needs to be called + * through adb. Typically this is done using a host side test. This mode is expected to be used + * only for testing purposes. If the HAL is set to data injection mode, it will ignore the input + * from physical sensors and read sensor data that is injected from the test application. This + * mode is used for testing vendor implementations for various algorithms like Rotation Vector, + * Significant Motion, Step Counter etc. Not all HALs support DATA_INJECTION. This method will + * fail in those cases. Once this method succeeds, the test can call + * {@link injectSensorData(Sensor, float[], int, long)} to inject sensor data into the HAL. + * + * @param enable True to initialize a client in DATA_INJECTION mode. + * False to clean up the native resources. * * @return true if the HAL supports data injection and false * otherwise. * @hide */ @SystemApi - public boolean enableDataInjectionMode(boolean enable) { - return enableDataInjectionImpl(enable); + public boolean initDataInjection(boolean enable) { + return initDataInjectionImpl(enable); } /** * @hide */ - protected abstract boolean enableDataInjectionImpl(boolean enable); + protected abstract boolean initDataInjectionImpl(boolean enable); /** * For testing purposes only. Not for third party applications. * - * This method is used to inject raw sensor data into the HAL. - * Call enableDataInjection before this method to set the HAL in - * data injection mode. This method should be called only if a - * previous call to enableDataInjection has been successful and - * the HAL is already in data injection mode. - * - * The tests which call this API need to have {@code - * android.permission.LOCATION_HARDWARE} permission which isn't - * available for third party applications. + * This method is used to inject raw sensor data into the HAL. Call {@link + * initDataInjection(boolean)} before this method to set the HAL in data injection mode. This + * method should be called only if a previous call to initDataInjection has been successful and + * the HAL and SensorService are already opreating in data injection mode. * * @param sensor The sensor to inject. * @param values Sensor values to inject. The length of this @@ -1650,9 +1644,6 @@ public abstract class SensorManager { if (timestamp <= 0) { throw new IllegalArgumentException("Negative or zero sensor timestamp"); } - if (timestamp > SystemClock.elapsedRealtimeNanos()) { - throw new IllegalArgumentException("Sensor timestamp into the future"); - } return injectSensorDataImpl(sensor, values, accuracy, timestamp); } diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java index d7960af..50e1a68 100644 --- a/core/java/android/hardware/SystemSensorManager.java +++ b/core/java/android/hardware/SystemSensorManager.java @@ -43,7 +43,7 @@ public class SystemSensorManager extends SensorManager { private static native void nativeClassInit(); private static native long nativeCreate(String opPackageName); private static native int nativeGetNextSensor(long nativeInstance, Sensor sensor, int next); - private static native int nativeEnableDataInjection(long nativeInstance, boolean enable); + private static native boolean nativeIsDataInjectionEnabled(long nativeInstance); private static boolean sSensorModuleInitialized = false; private static InjectEventQueue mInjectEventQueue = null; @@ -64,7 +64,6 @@ public class SystemSensorManager extends SensorManager { private final Looper mMainLooper; private final int mTargetSdkLevel; private final Context mContext; - private final boolean mHasDataInjectionPermissions; private final long mNativeInstance; /** {@hide} */ @@ -79,21 +78,18 @@ public class SystemSensorManager extends SensorManager { sSensorModuleInitialized = true; nativeClassInit(); } - mHasDataInjectionPermissions = context.checkSelfPermission( - Manifest.permission.LOCATION_HARDWARE) == PackageManager.PERMISSION_GRANTED; } // initialize the sensor list int i = 0; - while(true) { + do { Sensor sensor = new Sensor(); i = nativeGetNextSensor(mNativeInstance, sensor, i); - if (i <= 0) { - break; + if (i >= 0) { + mFullSensorsList.add(sensor); + mHandleToSensor.append(sensor.getHandle(), sensor); } - mFullSensorsList.add(sensor); - mHandleToSensor.append(sensor.getHandle(), sensor); - } + } while (i > 0); } @@ -230,23 +226,26 @@ public class SystemSensorManager extends SensorManager { } } - protected boolean enableDataInjectionImpl(boolean enable) { - if (!mHasDataInjectionPermissions) { - throw new SecurityException("Permission denial. Calling enableDataInjection without " - + Manifest.permission.LOCATION_HARDWARE); - } + protected boolean initDataInjectionImpl(boolean enable) { synchronized (mLock) { - int ret = nativeEnableDataInjection(mNativeInstance, enable); - // The HAL does not support injection. Ignore. - if (ret != 0) { - Log.e(TAG, "HAL does not support data injection"); - return false; - } - mDataInjectionMode = enable; - // If data injection is being disabled clean up the native resources. - if (!enable && mInjectEventQueue != null) { - mInjectEventQueue.dispose(); - mInjectEventQueue = null; + if (enable) { + boolean isDataInjectionModeEnabled = nativeIsDataInjectionEnabled(mNativeInstance); + // The HAL does not support injection OR SensorService hasn't been set in DI mode. + if (!isDataInjectionModeEnabled) { + Log.e(TAG, "Data Injection mode not enabled"); + return false; + } + mDataInjectionMode = true; + // Initialize a client for data_injection. + if (mInjectEventQueue == null) { + mInjectEventQueue = new InjectEventQueue(mMainLooper, this); + } + } else { + // If data injection is being disabled clean up the native resources. + if (mInjectEventQueue != null) { + mInjectEventQueue.dispose(); + mInjectEventQueue = null; + } } return true; } @@ -254,18 +253,11 @@ public class SystemSensorManager extends SensorManager { protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy, long timestamp) { - if (!mHasDataInjectionPermissions) { - throw new SecurityException("Permission denial. Calling injectSensorData without " - + Manifest.permission.LOCATION_HARDWARE); - } synchronized (mLock) { if (!mDataInjectionMode) { Log.e(TAG, "Data injection mode not activated before calling injectSensorData"); return false; } - if (mInjectEventQueue == null) { - mInjectEventQueue = new InjectEventQueue(mMainLooper, this); - } int ret = mInjectEventQueue.injectSensorData(sensor.getHandle(), values, accuracy, timestamp); // If there are any errors in data injection clean up the native resources. diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index c47498d..4f9055b 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -2000,70 +2000,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri new Key<android.graphics.Rect>("android.sensor.info.activeArraySize", android.graphics.Rect.class); /** - * <p>The area of the image sensor which corresponds to active pixels prior to the - * application of any geometric distortion correction.</p> - * <p>This is the rectangle representing the size of the active region of the sensor (i.e. - * the region that actually receives light from the scene) before any geometric correction - * has been applied, and should be treated as the active region rectangle for any of the - * raw formats. All metadata associated with raw processing (e.g. the lens shading - * correction map, and radial distortion fields) treats the top, left of this rectangle as - * the origin, (0,0).</p> - * <p>The size of this region determines the maximum field of view and the maximum number of - * pixels that an image from this sensor can contain, prior to the application of - * geometric distortion correction. The effective maximum pixel dimensions of a - * post-distortion-corrected image is given by the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} - * field, and the effective maximum field of view for a post-distortion-corrected image - * can be calculated by applying the geometric distortion correction fields to this - * rectangle, and cropping to the rectangle given in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> - * <p>E.g. to calculate position of a pixel, (x,y), in a processed YUV output image with the - * dimensions in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} given the position of a pixel, - * (x', y'), in the raw pixel array with dimensions give in - * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}:</p> - * <ol> - * <li>Choose a pixel (x', y') within the active array region of the raw buffer given in - * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, otherwise this pixel is considered - * to be outside of the FOV, and will not be shown in the processed output image.</li> - * <li>Apply geometric distortion correction to get the post-distortion pixel coordinate, - * (x_i, y_i). When applying geometric correction metadata, note that metadata for raw - * buffers is defined relative to the top, left of the - * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} rectangle.</li> - * <li>If the resulting corrected pixel coordinate is within the region given in - * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, then the position of this pixel in the - * processed output image buffer is <code>(x_i - activeArray.left, y_i - activeArray.top)</code>, - * when the top, left coordinate of that buffer is treated as (0, 0).</li> - * </ol> - * <p>Thus, for pixel x',y' = (25, 25) on a sensor where {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} - * is (100,100), {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is (10, 10, 100, 100), - * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is (20, 20, 80, 80), and the geometric distortion - * correction doesn't change the pixel coordinate, the resulting pixel selected in - * pixel coordinates would be x,y = (25, 25) relative to the top,left of the raw buffer - * with dimensions given in {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}, and would be (5, 5) - * relative to the top,left of post-processed YUV output buffer with dimensions given in - * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> - * <p>The currently supported fields that correct for geometric distortion are:</p> - * <ol> - * <li>android.lens.radialDistortion.</li> - * </ol> - * <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same - * as the post-distortion-corrected rectangle given in - * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> - * <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of - * the full pixel array, and the size of the full pixel array is given by - * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p> - * <p>The pre-correction active array may be smaller than the full pixel array, since the - * full array may include black calibration pixels or other inactive regions.</p> - * <p><b>Units</b>: Pixel coordinates on the image sensor</p> - * <p>This key is available on all devices.</p> - * - * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE - * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE - * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE - */ - @PublicKey - public static final Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE = - new Key<android.graphics.Rect>("android.sensor.info.preCorrectionActiveArraySize", android.graphics.Rect.class); - - /** * <p>Range of sensitivities for {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} supported by this * camera device.</p> * <p>The values are the standard ISO sensitivity values, @@ -2252,6 +2188,70 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri new Key<Boolean>("android.sensor.info.lensShadingApplied", boolean.class); /** + * <p>The area of the image sensor which corresponds to active pixels prior to the + * application of any geometric distortion correction.</p> + * <p>This is the rectangle representing the size of the active region of the sensor (i.e. + * the region that actually receives light from the scene) before any geometric correction + * has been applied, and should be treated as the active region rectangle for any of the + * raw formats. All metadata associated with raw processing (e.g. the lens shading + * correction map, and radial distortion fields) treats the top, left of this rectangle as + * the origin, (0,0).</p> + * <p>The size of this region determines the maximum field of view and the maximum number of + * pixels that an image from this sensor can contain, prior to the application of + * geometric distortion correction. The effective maximum pixel dimensions of a + * post-distortion-corrected image is given by the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} + * field, and the effective maximum field of view for a post-distortion-corrected image + * can be calculated by applying the geometric distortion correction fields to this + * rectangle, and cropping to the rectangle given in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> + * <p>E.g. to calculate position of a pixel, (x,y), in a processed YUV output image with the + * dimensions in {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} given the position of a pixel, + * (x', y'), in the raw pixel array with dimensions give in + * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}:</p> + * <ol> + * <li>Choose a pixel (x', y') within the active array region of the raw buffer given in + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize}, otherwise this pixel is considered + * to be outside of the FOV, and will not be shown in the processed output image.</li> + * <li>Apply geometric distortion correction to get the post-distortion pixel coordinate, + * (x_i, y_i). When applying geometric correction metadata, note that metadata for raw + * buffers is defined relative to the top, left of the + * {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} rectangle.</li> + * <li>If the resulting corrected pixel coordinate is within the region given in + * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, then the position of this pixel in the + * processed output image buffer is <code>(x_i - activeArray.left, y_i - activeArray.top)</code>, + * when the top, left coordinate of that buffer is treated as (0, 0).</li> + * </ol> + * <p>Thus, for pixel x',y' = (25, 25) on a sensor where {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} + * is (100,100), {@link CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE android.sensor.info.preCorrectionActiveArraySize} is (10, 10, 100, 100), + * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} is (20, 20, 80, 80), and the geometric distortion + * correction doesn't change the pixel coordinate, the resulting pixel selected in + * pixel coordinates would be x,y = (25, 25) relative to the top,left of the raw buffer + * with dimensions given in {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}, and would be (5, 5) + * relative to the top,left of post-processed YUV output buffer with dimensions given in + * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> + * <p>The currently supported fields that correct for geometric distortion are:</p> + * <ol> + * <li>android.lens.radialDistortion.</li> + * </ol> + * <p>If all of the geometric distortion fields are no-ops, this rectangle will be the same + * as the post-distortion-corrected rectangle given in + * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</p> + * <p>This rectangle is defined relative to the full pixel array; (0,0) is the top-left of + * the full pixel array, and the size of the full pixel array is given by + * {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize}.</p> + * <p>The pre-correction active array may be smaller than the full pixel array, since the + * full array may include black calibration pixels or other inactive regions.</p> + * <p><b>Units</b>: Pixel coordinates on the image sensor</p> + * <p>This key is available on all devices.</p> + * + * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE + * @see CameraCharacteristics#SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE + */ + @PublicKey + public static final Key<android.graphics.Rect> SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE = + new Key<android.graphics.Rect>("android.sensor.info.preCorrectionActiveArraySize", android.graphics.Rect.class); + + /** * <p>The standard reference illuminant used as the scene light source when * calculating the {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM1 android.sensor.colorTransform1}, * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM1 android.sensor.calibrationTransform1}, and diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 80476ea..12cd5f1 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -2565,7 +2565,7 @@ public class ConnectivityManager { * replaced by this one, effectively releasing the previous {@link NetworkRequest}. * <p> * The request may be released normally by calling - * {@link #releaseNetworkRequest(android.app.PendingIntent)}. + * {@link #unregisterNetworkCallback(android.app.PendingIntent)}. * <p>This method requires the caller to hold the permission * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}. * @param request {@link NetworkRequest} describing this request. @@ -2619,6 +2619,19 @@ public class ConnectivityManager { } /** + * Unregisters a callback previously registered via + * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. + * + * @param operation A PendingIntent equal (as defined by {@link Intent#filterEquals}) to the + * PendingIntent passed to + * {@link #registerNetworkCallback(NetworkRequest, android.app.PendingIntent)}. + * Cannot be null. + */ + public void unregisterNetworkCallback(PendingIntent operation) { + releaseNetworkRequest(operation); + } + + /** * Informs the system whether it should switch to {@code network} regardless of whether it is * validated or not. If {@code accept} is true, and the network was explicitly selected by the * user (e.g., by selecting a Wi-Fi network in the Settings app), then the network will become diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java index 64c2bc2..23d05bd 100644 --- a/core/java/android/nfc/cardemulation/CardEmulation.java +++ b/core/java/android/nfc/cardemulation/CardEmulation.java @@ -40,7 +40,7 @@ import java.util.List; * NFC card emulation services. * * For a general introduction into NFC card emulation, - * please read the <a href="{@docRoot}guide/topics/nfc/ce.html"> + * please read the <a href="{@docRoot}guide/topics/connectivity/nfc/hce.html"> * NFC card emulation developer guide</a>.</p> * * <p class="note">Use of this class requires the diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 7fda30a..fe323f3 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -184,6 +184,7 @@ public abstract class BatteryStats implements Parcelable { private static final String UID_DATA = "uid"; private static final String APK_DATA = "apk"; private static final String PROCESS_DATA = "pr"; + private static final String CPU_DATA = "cpu"; private static final String SENSOR_DATA = "sr"; private static final String VIBRATOR_DATA = "vib"; private static final String FOREGROUND_DATA = "fg"; @@ -457,8 +458,13 @@ public abstract class BatteryStats implements Parcelable { public abstract long getSystemCpuTimeUs(int which); /** + * Get the total cpu power consumed (in milli-ampere-microseconds). + */ + public abstract long getCpuPowerMaUs(int which); + + /** * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed. - * @param speedStep the index of the CPU speed. This is not the actual speed of the CPU. + * @param step the index of the CPU speed. This is not the actual speed of the CPU. * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. * @see BatteryStats#getCpuSpeedSteps() */ @@ -2905,6 +2911,14 @@ public abstract class BatteryStats implements Parcelable { dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes); } + final long userCpuTimeUs = u.getUserCpuTimeUs(which); + final long systemCpuTimeUs = u.getSystemCpuTimeUs(which); + final long powerCpuMaUs = u.getCpuPowerMaUs(which); + if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) { + dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000, + powerCpuMaUs / 1000); + } + final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); for (int ipr=processStats.size()-1; ipr>=0; ipr--) { @@ -2970,6 +2984,10 @@ public abstract class BatteryStats implements Parcelable { printer.print(BatteryStatsHelper.makemAh(power)); } + private void printmAh(StringBuilder sb, double power) { + sb.append(BatteryStatsHelper.makemAh(power)); + } + /** * Temporary for settings. */ @@ -4028,13 +4046,17 @@ public abstract class BatteryStats implements Parcelable { final long userCpuTimeUs = u.getUserCpuTimeUs(which); final long systemCpuTimeUs = u.getSystemCpuTimeUs(which); - if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) { + final long powerCpuMaUs = u.getCpuPowerMaUs(which); + if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) { sb.setLength(0); sb.append(prefix); sb.append(" Total cpu time: u="); formatTimeMs(sb, userCpuTimeUs / 1000); sb.append("s="); formatTimeMs(sb, systemCpuTimeUs / 1000); + sb.append("p="); + printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0)); + sb.append("mAh"); pw.println(sb.toString()); } diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 6874e77..20bcf62 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -179,6 +179,19 @@ public final class UserHandle implements Parcelable { } /** + * Returns the app id for a given shared app gid. + * @hide + */ + public static final int getAppIdFromSharedAppGid(int gid) { + final int noUserGid = getAppId(gid); + if (noUserGid < Process.FIRST_SHARED_APPLICATION_GID || + noUserGid > Process.LAST_SHARED_APPLICATION_GID) { + throw new IllegalArgumentException(Integer.toString(gid) + " is not a shared app gid"); + } + return (noUserGid + Process.FIRST_APPLICATION_UID) - Process.FIRST_SHARED_APPLICATION_GID; + } + + /** * Generate a text representation of the uid, breaking out its individual * components -- user, app, isolated, etc. * @hide @@ -208,6 +221,17 @@ public final class UserHandle implements Parcelable { * components -- user, app, isolated, etc. * @hide */ + public static String formatUid(int uid) { + StringBuilder sb = new StringBuilder(); + formatUid(sb, uid); + return sb.toString(); + } + + /** + * Generate a text representation of the uid, breaking out its individual + * components -- user, app, isolated, etc. + * @hide + */ public static void formatUid(PrintWriter pw, int uid) { if (uid < Process.FIRST_APPLICATION_UID) { pw.print(uid); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 6384af3..b104135 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -572,6 +572,16 @@ public class UserManager { } /** + * @hide + * Returns whether the caller is running as an admin user. There can be more than one admin + * user. + */ + public boolean isAdminUser() { + UserInfo user = getUserInfo(UserHandle.myUserId()); + return user != null ? user.isAdmin() : false; + } + + /** * Used to check if the user making this call is linked to another user. Linked users may have * a reduced number of available apps, app restrictions and account restrictions. * @return whether the user making this call is a linked user diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java index 397d87e..9114107 100644 --- a/core/java/android/os/storage/DiskInfo.java +++ b/core/java/android/os/storage/DiskInfo.java @@ -54,6 +54,7 @@ public class DiskInfo implements Parcelable { public String label; /** Hacky; don't rely on this count */ public int volumeCount; + public String sysPath; public DiskInfo(String id, int flags) { this.id = Preconditions.checkNotNull(id); @@ -66,6 +67,7 @@ public class DiskInfo implements Parcelable { size = parcel.readLong(); label = parcel.readString(); volumeCount = parcel.readInt(); + sysPath = parcel.readString(); } public @NonNull String getId() { @@ -139,6 +141,8 @@ public class DiskInfo implements Parcelable { pw.printPair("flags", DebugUtils.flagsToString(getClass(), "FLAG_", flags)); pw.printPair("size", size); pw.printPair("label", label); + pw.println(); + pw.printPair("sysPath", sysPath); pw.decreaseIndent(); pw.println(); } @@ -193,5 +197,6 @@ public class DiskInfo implements Parcelable { parcel.writeLong(size); parcel.writeString(label); parcel.writeInt(volumeCount); + parcel.writeString(sysPath); } } diff --git a/core/java/android/os/storage/VolumeRecord.java b/core/java/android/os/storage/VolumeRecord.java index cb16305..7b20223 100644 --- a/core/java/android/os/storage/VolumeRecord.java +++ b/core/java/android/os/storage/VolumeRecord.java @@ -19,6 +19,7 @@ package android.os.storage; import android.os.Parcel; import android.os.Parcelable; import android.util.DebugUtils; +import android.util.TimeUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.Preconditions; @@ -42,6 +43,9 @@ public class VolumeRecord implements Parcelable { public String partGuid; public String nickname; public int userFlags; + public long createdMillis; + public long lastTrimMillis; + public long lastBenchMillis; public VolumeRecord(int type, String fsUuid) { this.type = type; @@ -54,6 +58,9 @@ public class VolumeRecord implements Parcelable { partGuid = parcel.readString(); nickname = parcel.readString(); userFlags = parcel.readInt(); + createdMillis = parcel.readLong(); + lastTrimMillis = parcel.readLong(); + lastBenchMillis = parcel.readLong(); } public int getType() { @@ -86,6 +93,10 @@ public class VolumeRecord implements Parcelable { pw.printPair("nickname", nickname); pw.printPair("userFlags", DebugUtils.flagsToString(VolumeRecord.class, "USER_FLAG_", userFlags)); + pw.println(); + pw.printPair("createdMillis", TimeUtils.formatForLogging(createdMillis)); + pw.printPair("lastTrimMillis", TimeUtils.formatForLogging(lastTrimMillis)); + pw.printPair("lastBenchMillis", TimeUtils.formatForLogging(lastBenchMillis)); pw.decreaseIndent(); pw.println(); } @@ -140,5 +151,8 @@ public class VolumeRecord implements Parcelable { parcel.writeString(partGuid); parcel.writeString(nickname); parcel.writeInt(userFlags); + parcel.writeLong(createdMillis); + parcel.writeLong(lastTrimMillis); + parcel.writeLong(lastBenchMillis); } } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index e5afdde..4e13758 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6324,6 +6324,9 @@ public final class Settings { /** Timeout in milliseconds to wait for NTP server. {@hide} */ public static final String NTP_TIMEOUT = "ntp_timeout"; + /** {@hide} */ + public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval"; + /** * Whether the package manager should send package verification broadcasts for verifiers to * review apps prior to installation. diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index 8119049..549c93e 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -172,15 +172,6 @@ public class VoiceInteractionService extends Service { } } - /** @hide */ - public void startSession(Bundle args, int flags) { - showSession(args, flags); - } - /** @hide */ - public void startSession(Bundle args) { - startSession(args, 0); - } - @Override public void onCreate() { super.onCreate(); diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index f9e216a..a7e0e08 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -71,7 +71,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; */ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCallbacks2 { static final String TAG = "VoiceInteractionSession"; - static final boolean DEBUG = true; + static final boolean DEBUG = false; /** * Flag received in {@link #onShow}: originator requested that the session be started with @@ -175,6 +175,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall CommandRequest request = new CommandRequest(callingPackage, Binder.getCallingUid(), callback, VoiceInteractionSession.this, command, extras); + addRequest(request); mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_START_COMMAND, request)); return request.mInterface; @@ -249,16 +250,12 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } }; - /** @hide */ - public static class Caller { - } - /** * Base class representing a request from a voice-driver app to perform a particular * voice operation with the user. See related subclasses for the types of requests * that are possible. */ - public static class Request extends Caller { + public static class Request { final IVoiceInteractorRequest mInterface = new IVoiceInteractorRequest.Stub() { @Override public void cancel() throws RemoteException { @@ -319,74 +316,8 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - /** @hide */ - public void sendConfirmResult(boolean confirmed, Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface - + " confirmed=" + confirmed + " result=" + result); - finishRequest(); - mCallback.deliverConfirmationResult(mInterface, confirmed, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendPickOptionResult(boolean finished, - VoiceInteractor.PickOptionRequest.Option[] selections, Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendPickOptionResult: req=" + mInterface - + " finished=" + finished + " selections=" + selections - + " result=" + result); - if (finished) { - finishRequest(); - } - mCallback.deliverPickOptionResult(mInterface, finished, selections, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendCompleteVoiceResult(Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendCompleteVoiceResult: req=" + mInterface - + " result=" + result); - finishRequest(); - mCallback.deliverCompleteVoiceResult(mInterface, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendAbortVoiceResult(Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface - + " result=" + result); - finishRequest(); - mCallback.deliverAbortVoiceResult(mInterface, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendCommandResult(boolean finished, Bundle result) { - try { - if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface - + " result=" + result); - if (finished) { - finishRequest(); - } - mCallback.deliverCommandResult(mInterface, finished, result); - } catch (RemoteException e) { - } - } - - /** @hide */ - public void sendCancelResult() { - cancel(); - } - /** - * ASk the app to cancelLocked this current request. + * Ask the app to cancel this current request. */ public void cancel() { try { @@ -440,7 +371,13 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * VoiceInteractor.ConfirmationRequest.onConfirmationResult}. */ public void sendConfirmationResult(boolean confirmed, Bundle result) { - sendConfirmResult(confirmed, result); + try { + if (DEBUG) Log.d(TAG, "sendConfirmationResult: req=" + mInterface + + " confirmed=" + confirmed + " result=" + result); + finishRequest(); + mCallback.deliverConfirmationResult(mInterface, confirmed, result); + } catch (RemoteException e) { + } } } @@ -487,6 +424,20 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall return mOptions; } + void sendPickOptionResult(boolean finished, + VoiceInteractor.PickOptionRequest.Option[] selections, Bundle result) { + try { + if (DEBUG) Log.d(TAG, "sendPickOptionResult: req=" + mInterface + + " finished=" + finished + " selections=" + selections + + " result=" + result); + if (finished) { + finishRequest(); + } + mCallback.deliverPickOptionResult(mInterface, finished, selections, result); + } catch (RemoteException e) { + } + } + /** * Report an intermediate option selection from the request, without completing it (the * request is still active and the app is waiting for the final option selection), @@ -553,7 +504,13 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * VoiceInteractor.CompleteVoiceRequest.onCompleteResult}. */ public void sendCompleteResult(Bundle result) { - sendCompleteVoiceResult(result); + try { + if (DEBUG) Log.d(TAG, "sendCompleteVoiceResult: req=" + mInterface + + " result=" + result); + finishRequest(); + mCallback.deliverCompleteVoiceResult(mInterface, result); + } catch (RemoteException e) { + } } } @@ -596,7 +553,13 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * VoiceInteractor.AbortVoiceRequest.onAbortResult}. */ public void sendAbortResult(Bundle result) { - sendAbortVoiceResult(result); + try { + if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface + + " result=" + result); + finishRequest(); + mCallback.deliverAbortVoiceResult(mInterface, result); + } catch (RemoteException e) { + } } } @@ -621,6 +584,18 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall return mCommand; } + void sendCommandResult(boolean finished, Bundle result) { + try { + if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface + + " result=" + result); + if (finished) { + finishRequest(); + } + mCallback.deliverCommandResult(mInterface, finished, result); + } catch (RemoteException e) { + } + } + /** * Report an intermediate result of the request, without completing it (the request * is still active and the app is waiting for the final result), resulting in a call to @@ -829,11 +804,10 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - void doCreate(IVoiceInteractionManagerService service, IBinder token, Bundle args, - int startFlags) { + void doCreate(IVoiceInteractionManagerService service, IBinder token) { mSystemService = service; mToken = token; - onCreate(args, startFlags); + onCreate(); } void doShow(Bundle args, int flags, final IVoiceInteractionSessionShowCallback showCallback) { @@ -919,11 +893,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall mContentFrame = (FrameLayout)mRootView.findViewById(android.R.id.content); } - /** @hide */ - public void show() { - show(null, 0); - } - /** * Show the UI for this session. This asks the system to go through the process of showing * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling @@ -958,14 +927,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } } - /** @hide */ - public void showWindow() { - } - - /** @hide */ - public void hideWindow() { - } - /** * You can call this to customize the theme used by your IME's window. * This must be set before {@link #onCreate}, so you @@ -1040,6 +1001,21 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall } /** + * Request that all system dialogs (and status bar shade etc) be closed, allowing + * access to the session's UI. This will <em>not</em> cause the lock screen to be + * dismissed. + */ + public void closeSystemDialogs() { + if (mToken == null) { + throw new IllegalStateException("Can't call before onCreate()"); + } + try { + mSystemService.closeSystemDialogs(mToken); + } catch (RemoteException e) { + } + } + + /** * Convenience for inflating views. */ public LayoutInflater getLayoutInflater() { @@ -1062,7 +1038,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall if (mToken == null) { throw new IllegalStateException("Can't call before onCreate()"); } - hideWindow(); try { mSystemService.finish(mToken); } catch (RemoteException e) { @@ -1077,16 +1052,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall doOnCreate(); } - /** @hide */ - public void onCreate(Bundle args) { - doOnCreate(); - } - - /** @hide */ - public void onCreate(Bundle args, int showFlags) { - doOnCreate(); - } - private void doOnCreate() { mTheme = mTheme != 0 ? mTheme : com.android.internal.R.style.Theme_DeviceDefault_VoiceInteractionSession; @@ -1244,34 +1209,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall hide(); } - /** @hide */ - public boolean[] onGetSupportedCommands(Caller caller, String[] commands) { - return new boolean[commands.length]; - } - /** @hide */ - public void onConfirm(Caller caller, Request request, CharSequence prompt, - Bundle extras) { - } - /** @hide */ - public void onPickOption(Caller caller, Request request, CharSequence prompt, - VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) { - } - /** @hide */ - public void onCompleteVoice(Caller caller, Request request, CharSequence message, - Bundle extras) { - request.sendCompleteVoiceResult(null); - } - /** @hide */ - public void onAbortVoice(Caller caller, Request request, CharSequence message, Bundle extras) { - request.sendAbortVoiceResult(null); - } - /** @hide */ - public void onCommand(Caller caller, Request request, String command, Bundle extras) { - } - /** @hide */ - public void onCancel(Request request) { - } - /** * Request to query for what extended commands the session supports. * @@ -1282,7 +1219,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * an array of all false entries. */ public boolean[] onGetSupportedCommands(String[] commands) { - return onGetSupportedCommands(new Caller(), commands); + return new boolean[commands.length]; } /** @@ -1293,7 +1230,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestConfirmation(ConfirmationRequest request) { - onConfirm(request, request, request.getPrompt(), request.getExtras()); } /** @@ -1303,8 +1239,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestPickOption(PickOptionRequest request) { - onPickOption(request, request, request.getPrompt(), request.getOptions(), - request.getExtras()); } /** @@ -1317,7 +1251,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestCompleteVoice(CompleteVoiceRequest request) { - onCompleteVoice(request, request, request.getMessage(), request.getExtras()); } /** @@ -1330,7 +1263,6 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestAbortVoice(AbortVoiceRequest request) { - onAbortVoice(request, request, request.getMessage(), request.getExtras()); } /** @@ -1341,11 +1273,10 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The active request. */ public void onRequestCommand(CommandRequest request) { - onCommand(request, request, request.getCommand(), request.getExtras()); } /** - * Called when the {@link android.app.VoiceInteractor} has asked to cancelLocked a {@link Request} + * Called when the {@link android.app.VoiceInteractor} has asked to cancel a {@link Request} * that was previously delivered to {@link #onRequestConfirmation}, * {@link #onRequestPickOption}, {@link #onRequestCompleteVoice}, {@link #onRequestAbortVoice}, * or {@link #onRequestCommand}. @@ -1353,6 +1284,5 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * @param request The request that is being canceled. */ public void onCancelRequest(Request request) { - onCancel(request); } } diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java index 8f988f3..fb9f973 100644 --- a/core/java/android/service/voice/VoiceInteractionSessionService.java +++ b/core/java/android/service/voice/VoiceInteractionSessionService.java @@ -109,7 +109,7 @@ public abstract class VoiceInteractionSessionService extends Service { mSession = onNewSession(args); try { mSystemService.deliverNewSession(token, mSession.mSession, mSession.mInteractor); - mSession.doCreate(mSystemService, token, args, startFlags); + mSession.doCreate(mSystemService, token); } catch (RemoteException e) { } } diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 8952807..d598291 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -271,8 +271,8 @@ public abstract class WallpaperService extends Service { public void resized(Rect frame, Rect overscanInsets, Rect contentInsets, Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw, Configuration newConfig) { - Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, - reportDraw ? 1 : 0); + Message msg = mCaller.obtainMessageIO(MSG_WINDOW_RESIZED, + reportDraw ? 1 : 0, outsets); mCaller.sendMessage(msg); } @@ -649,7 +649,7 @@ public abstract class WallpaperService extends Service { com.android.internal.R.style.Animation_Wallpaper; mInputChannel = new InputChannel(); if (mSession.addToDisplay(mWindow, mWindow.mSeq, mLayout, View.VISIBLE, - Display.DEFAULT_DISPLAY, mContentInsets, mStableInsets, + Display.DEFAULT_DISPLAY, mContentInsets, mStableInsets, mOutsets, mInputChannel) < 0) { Log.w(TAG, "Failed to add window while updating wallpaper surface."); return; @@ -1192,6 +1192,7 @@ public abstract class WallpaperService extends Service { } break; case MSG_WINDOW_RESIZED: { final boolean reportDraw = message.arg1 != 0; + mEngine.mOutsets.set((Rect) message.obj); mEngine.updateSurface(true, false, reportDraw); mEngine.doOffsetsChanged(true); } break; diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 585fc4e..f9dd7eb 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -452,6 +452,7 @@ public abstract class Visibility extends Transition { DisappearListener disappearListener = new DisappearListener(viewToKeep, finalVisibility, isForcedVisibility); animator.addListener(disappearListener); + animator.addPauseListener(disappearListener); addListener(disappearListener); } else if (!isForcedVisibility) { viewToKeep.setTransitionVisibility(originalVisibility); diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index 353388d..c1eb80d 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -28,6 +28,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.io.PrintWriter; +import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; @@ -54,6 +55,8 @@ public class TimeUtils { private static ArrayList<TimeZone> sLastUniqueZoneOffsets = null; private static String sLastUniqueCountry = null; + /** {@hide} */ + private static SimpleDateFormat sLoggingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** * Tries to return a time zone that would have had the specified offset @@ -441,4 +444,13 @@ public class TimeUtils { return Long.toString(millis); } } + + /** {@hide} */ + public static String formatForLogging(long millis) { + if (millis <= 0) { + return "unknown"; + } else { + return sLoggingFormat.format(new Date(millis)); + } + } } diff --git a/core/java/android/view/ActionProvider.java b/core/java/android/view/ActionProvider.java index c3aafde..752240f 100644 --- a/core/java/android/view/ActionProvider.java +++ b/core/java/android/view/ActionProvider.java @@ -237,6 +237,14 @@ public abstract class ActionProvider { } /** + * @hide + */ + public void reset() { + mVisibilityListener = null; + mSubUiVisibilityListener = null; + } + + /** * @hide Internal use only */ public interface SubUiVisibilityListener { diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 19253dd..73b4a6e 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -40,7 +40,7 @@ interface IWindowSession { out InputChannel outInputChannel); int addToDisplay(IWindow window, int seq, in WindowManager.LayoutParams attrs, in int viewVisibility, in int layerStackId, out Rect outContentInsets, - out Rect outStableInsets, out InputChannel outInputChannel); + out Rect outStableInsets, out Rect outOutsets, out InputChannel outInputChannel); int addWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs, in int viewVisibility, out Rect outContentInsets, out Rect outStableInsets); int addToDisplayWithoutInputChannel(IWindow window, int seq, in WindowManager.LayoutParams attrs, diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index e044f1e..f6119e2 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -434,7 +434,6 @@ public class ThreadedRenderer extends HardwareRenderer { private static class ProcessInitializer { static ProcessInitializer sInstance = new ProcessInitializer(); - static IGraphicsStats sGraphicsStatsService; private static IBinder sProcToken; private boolean mInitialized = false; @@ -449,19 +448,19 @@ public class ThreadedRenderer extends HardwareRenderer { } private static void initGraphicsStats(Context context, long renderProxy) { - IBinder binder = ServiceManager.getService("graphicsstats"); - if (binder == null) return; - - sGraphicsStatsService = IGraphicsStats.Stub.asInterface(binder); - sProcToken = new Binder(); try { + IBinder binder = ServiceManager.getService("graphicsstats"); + if (binder == null) return; + IGraphicsStats graphicsStatsService = IGraphicsStats.Stub + .asInterface(binder); + sProcToken = new Binder(); final String pkg = context.getApplicationInfo().packageName; - ParcelFileDescriptor pfd = sGraphicsStatsService. + ParcelFileDescriptor pfd = graphicsStatsService. requestBufferForProcess(pkg, sProcToken); nSetProcessStatsBuffer(renderProxy, pfd.getFd()); pfd.close(); - } catch (Exception e) { - Log.w(LOG_TAG, "Could not acquire gfx stats buffer", e); + } catch (Throwable t) { + Log.w(LOG_TAG, "Could not acquire gfx stats buffer", t); } } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 23da6d2..63dd492 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -12288,6 +12288,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mRenderNode.offsetTopAndBottom(offset); if (isHardwareAccelerated()) { invalidateViewProperty(false, false); + invalidateParentIfNeededAndWasQuickRejected(); } else { if (!matrixIsIdentity) { invalidateViewProperty(false, true); @@ -12335,6 +12336,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mRenderNode.offsetLeftAndRight(offset); if (isHardwareAccelerated()) { invalidateViewProperty(false, false); + invalidateParentIfNeededAndWasQuickRejected(); } else { if (!matrixIsIdentity) { invalidateViewProperty(false, true); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index b53d93c..6dca26b 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3236,13 +3236,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager for (int i = 0; i < getChildCount(); i++) { View c = getChildAt(i); - Insets insets = c.getOpticalInsets(); - - drawRect(canvas, paint, - c.getLeft() + insets.left, - c.getTop() + insets.top, - c.getRight() - insets.right - 1, - c.getBottom() - insets.bottom - 1); + if (c.getVisibility() != View.GONE) { + Insets insets = c.getOpticalInsets(); + + drawRect(canvas, paint, + c.getLeft() + insets.left, + c.getTop() + insets.top, + c.getRight() - insets.right - 1, + c.getBottom() - insets.bottom - 1); + } } } @@ -3263,8 +3265,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager int lineWidth = dipsToPixels(1); for (int i = 0; i < getChildCount(); i++) { View c = getChildAt(i); - drawRectCorners(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(), - paint, lineLength, lineWidth); + if (c.getVisibility() != View.GONE) { + drawRectCorners(canvas, c.getLeft(), c.getTop(), c.getRight(), c.getBottom(), + paint, lineLength, lineWidth); + } } } } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 8b57d96..6d0d788 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -531,7 +531,8 @@ public final class ViewRootImpl implements ViewParent, collectViewAttributes(); res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, getHostVisibility(), mDisplay.getDisplayId(), - mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mInputChannel); + mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, + mAttachInfo.mOutsets, mInputChannel); } catch (RemoteException e) { mAdded = false; mView = null; @@ -1590,6 +1591,7 @@ public final class ViewRootImpl implements ViewParent, + " content=" + mPendingContentInsets.toShortString() + " visible=" + mPendingVisibleInsets.toShortString() + " visible=" + mPendingStableInsets.toShortString() + + " outsets=" + mPendingOutsets.toShortString() + " surface=" + mSurface); if (mPendingConfiguration.seq != 0) { diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index ca5f5ad..64210ea 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -879,13 +879,15 @@ public interface WindowManagerPolicy { * be correct. * * @param attrs The LayoutParams of the window. + * @param rotation Rotation of the display. * @param outContentInsets The areas covered by system windows, expressed as positive insets. * @param outStableInsets The areas covered by stable system windows irrespective of their * current visibility. Expressed as positive insets. + * @param outOutsets The areas that are not real display, but we would like to treat as such. * */ - public void getInsetHintLw(WindowManager.LayoutParams attrs, Rect outContentInsets, - Rect outStableInsets); + public void getInsetHintLw(WindowManager.LayoutParams attrs, int rotation, + Rect outContentInsets, Rect outStableInsets, Rect outOutsets); /** * Called when layout of the windows is finished. After this function has @@ -913,12 +915,13 @@ public interface WindowManagerPolicy { /** * Called following layout of all window to apply policy to each window. - * + * * @param win The window being positioned. - * @param attrs The LayoutParams of the window. + * @param attrs The LayoutParams of the window. + * @param attached For sub-windows, the window it is attached to. Otherwise null. */ public void applyPostLayoutPolicyLw(WindowState win, - WindowManager.LayoutParams attrs); + WindowManager.LayoutParams attrs, WindowState attached); /** * Called following layout of all windows and after policy has been applied diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index bb4a948..c54b28d 100644 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -553,7 +553,8 @@ public class AppSecurityPermissions { int existingReqFlags) { final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE; final boolean isNormal = (base == PermissionInfo.PROTECTION_NORMAL); - final boolean isDangerous = (base == PermissionInfo.PROTECTION_DANGEROUS); + final boolean isDangerous = (base == PermissionInfo.PROTECTION_DANGEROUS) + || ((pInfo.protectionLevel&PermissionInfo.PROTECTION_FLAG_PRE23) != 0); final boolean isRequired = ((newReqFlags&PackageInfo.REQUESTED_PERMISSION_REQUIRED) != 0); final boolean isDevelopment = diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java index 770077d..602e1ab 100644 --- a/core/java/android/widget/CompoundButton.java +++ b/core/java/android/widget/CompoundButton.java @@ -245,6 +245,17 @@ public abstract class CompoundButton extends Button implements Checkable { } /** + * @hide + */ + @Override + public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) { + super.onResolveDrawables(layoutDirection); + if (mButtonDrawable != null) { + mButtonDrawable.setLayoutDirection(layoutDirection); + } + } + + /** * @return the drawable used as the compound button image * @see #setButtonDrawable(Drawable) * @see #setButtonDrawable(int) diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 84e7db4..1158d1e 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -38,7 +38,6 @@ import android.graphics.Path; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; -import android.inputmethodservice.ExtractEditText; import android.os.Bundle; import android.os.Handler; import android.os.Parcel; @@ -70,6 +69,7 @@ import android.text.style.TextAppearanceSpan; import android.text.style.URLSpan; import android.util.DisplayMetrics; import android.util.Log; +import android.util.SparseArray; import android.view.ActionMode; import android.view.ActionMode.Callback; import android.view.DisplayListCanvas; @@ -89,6 +89,7 @@ import android.view.ViewGroup.LayoutParams; import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.WindowManager; +import android.view.accessibility.AccessibilityNodeInfo; import android.view.inputmethod.CorrectionInfo; import android.view.inputmethod.CursorAnchorInfo; import android.view.inputmethod.EditorInfo; @@ -102,6 +103,7 @@ import android.widget.TextView.OnEditorActionListener; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; +import com.android.internal.util.Preconditions; import com.android.internal.widget.EditableInputConnection; import java.text.BreakIterator; @@ -110,6 +112,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; + /** * Helper class used by TextView to handle editable text views. * @@ -244,6 +247,8 @@ public class Editor { private TextView mTextView; + final ProcessTextIntentActionsHandler mProcessTextIntentActionsHandler; + final CursorAnchorInfoNotifier mCursorAnchorInfoNotifier = new CursorAnchorInfoNotifier(); private final Runnable mShowFloatingToolbar = new Runnable() { @@ -261,6 +266,7 @@ public class Editor { mTextView = textView; // Synchronize the filter list, which places the undo input filter at the end. mTextView.setFilters(mTextView.getFilters()); + mProcessTextIntentActionsHandler = new ProcessTextIntentActionsHandler(this); } ParcelableParcel saveInstanceState() { @@ -1186,7 +1192,7 @@ public class Editor { final InputMethodManager imm = InputMethodManager.peekInstance(); final boolean immFullScreen = (imm != null && imm.isFullscreenMode()); if (mSelectionModifierCursorController != null && mTextView.hasSelection() - && !immFullScreen) { + && !immFullScreen && mTextActionMode != null) { mSelectionModifierCursorController.show(); } } else { @@ -3157,7 +3163,9 @@ public class Editor { } } - addIntentMenuItemsForTextProcessing(menu); + if (mTextView.canProcessText()) { + mProcessTextIntentActionsHandler.onInitializeMenu(menu); + } if (menu.hasVisibleItems() || mode.getCustomView() != null) { mTextView.setHasTransientState(true); @@ -3205,34 +3213,6 @@ public class Editor { updateReplaceItem(menu); } - private void addIntentMenuItemsForTextProcessing(Menu menu) { - if (mTextView.canProcessText()) { - PackageManager packageManager = mTextView.getContext().getPackageManager(); - List<ResolveInfo> supportedActivities = - packageManager.queryIntentActivities(createProcessTextIntent(), 0); - for (int i = 0; i < supportedActivities.size(); ++i) { - ResolveInfo info = supportedActivities.get(i); - menu.add(Menu.NONE, Menu.NONE, - MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i, - info.loadLabel(packageManager)) - .setIntent(createProcessTextIntentForResolveInfo(info)) - .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - } - } - } - - private Intent createProcessTextIntent() { - return new Intent() - .setAction(Intent.ACTION_PROCESS_TEXT) - .setType("text/plain"); - } - - private Intent createProcessTextIntentForResolveInfo(ResolveInfo info) { - return createProcessTextIntent() - .putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, !mTextView.isTextEditable()) - .setClassName(info.activityInfo.packageName, info.activityInfo.name); - } - @Override public boolean onPrepareActionMode(ActionMode mode, Menu menu) { updateSelectAllItem(menu); @@ -3271,12 +3251,7 @@ public class Editor { @Override public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - if (item.getIntent() != null - && item.getIntent().getAction().equals(Intent.ACTION_PROCESS_TEXT)) { - item.getIntent().putExtra(Intent.EXTRA_PROCESS_TEXT, mTextView.getSelectedText()); - mPreserveDetachedSelection = true; - mTextView.startActivityForResult( - item.getIntent(), TextView.PROCESS_TEXT_REQUEST_CODE); + if (mProcessTextIntentActionsHandler.performMenuItemAction(item)) { return true; } Callback customCallback = getCustomCallback(); @@ -5466,4 +5441,119 @@ public class Editor { } }; } + + /** + * A helper for enabling and handling "PROCESS_TEXT" menu actions. + * These allow external applications to plug into currently selected text. + */ + static final class ProcessTextIntentActionsHandler { + + private final Editor mEditor; + private final TextView mTextView; + private final PackageManager mPackageManager; + private final SparseArray<Intent> mAccessibilityIntents = new SparseArray<Intent>(); + private final SparseArray<AccessibilityNodeInfo.AccessibilityAction> mAccessibilityActions + = new SparseArray<AccessibilityNodeInfo.AccessibilityAction>(); + + private ProcessTextIntentActionsHandler(Editor editor) { + mEditor = Preconditions.checkNotNull(editor); + mTextView = Preconditions.checkNotNull(mEditor.mTextView); + mPackageManager = Preconditions.checkNotNull( + mTextView.getContext().getPackageManager()); + } + + /** + * Adds "PROCESS_TEXT" menu items to the specified menu. + */ + public void onInitializeMenu(Menu menu) { + int i = 0; + for (ResolveInfo resolveInfo : getSupportedActivities()) { + menu.add(Menu.NONE, Menu.NONE, + Editor.MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i++, + getLabel(resolveInfo)) + .setIntent(createProcessTextIntentForResolveInfo(resolveInfo)) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } + } + + /** + * Performs a "PROCESS_TEXT" action if there is one associated with the specified + * menu item. + * + * @return True if the action was performed, false otherwise. + */ + public boolean performMenuItemAction(MenuItem item) { + return fireIntent(item.getIntent()); + } + + /** + * Initializes and caches "PROCESS_TEXT" accessibility actions. + */ + public void initializeAccessibilityActions() { + mAccessibilityIntents.clear(); + mAccessibilityActions.clear(); + int i = 0; + for (ResolveInfo resolveInfo : getSupportedActivities()) { + int actionId = TextView.ACCESSIBILITY_ACTION_PROCESS_TEXT_START_ID + i++; + mAccessibilityActions.put( + actionId, + new AccessibilityNodeInfo.AccessibilityAction( + actionId, getLabel(resolveInfo))); + mAccessibilityIntents.put( + actionId, createProcessTextIntentForResolveInfo(resolveInfo)); + } + } + + /** + * Adds "PROCESS_TEXT" accessibility actions to the specified accessibility node info. + * NOTE: This needs a prior call to {@link #initializeAccessibilityActions()} to make the + * latest accessibility actions available for this call. + */ + public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo nodeInfo) { + for (int i = 0; i < mAccessibilityActions.size(); i++) { + nodeInfo.addAction(mAccessibilityActions.valueAt(i)); + } + } + + /** + * Performs a "PROCESS_TEXT" action if there is one associated with the specified + * accessibility action id. + * + * @return True if the action was performed, false otherwise. + */ + public boolean performAccessibilityAction(int actionId) { + return fireIntent(mAccessibilityIntents.get(actionId)); + } + + private boolean fireIntent(Intent intent) { + if (intent != null && Intent.ACTION_PROCESS_TEXT.equals(intent.getAction())) { + intent.putExtra(Intent.EXTRA_PROCESS_TEXT, mTextView.getSelectedText()); + mEditor.mPreserveDetachedSelection = true; + mTextView.startActivityForResult(intent, TextView.PROCESS_TEXT_REQUEST_CODE); + return true; + } + return false; + } + + private List<ResolveInfo> getSupportedActivities() { + PackageManager packageManager = mTextView.getContext().getPackageManager(); + return packageManager.queryIntentActivities(createProcessTextIntent(), 0); + } + + private Intent createProcessTextIntentForResolveInfo(ResolveInfo info) { + return createProcessTextIntent() + .putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, !mTextView.isTextEditable()) + .setClassName(info.activityInfo.packageName, info.activityInfo.name); + } + + private Intent createProcessTextIntent() { + return new Intent() + .setAction(Intent.ACTION_PROCESS_TEXT) + .setType("text/plain"); + } + + private CharSequence getLabel(ResolveInfo resolveInfo) { + return resolveInfo.loadLabel(mPackageManager); + } + } } diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java index e0b2395..a1582f2 100644 --- a/core/java/android/widget/ImageView.java +++ b/core/java/android/widget/ImageView.java @@ -423,14 +423,14 @@ public class ImageView extends View { * * <p class="note">This does Bitmap reading and decoding on the UI * thread, which can cause a latency hiccup. If that's a concern, - * consider using {@link #setImageDrawable(android.graphics.drawable.Drawable)} or + * consider using {@link #setImageDrawable(Drawable)} or * {@link #setImageBitmap(android.graphics.Bitmap)} and * {@link android.graphics.BitmapFactory} instead.</p> * - * @param uri The Uri of an image + * @param uri the Uri of an image, or {@code null} to clear the content */ @android.view.RemotableViewMethod - public void setImageURI(Uri uri) { + public void setImageURI(@Nullable Uri uri) { if (mResource != 0 || (mUri != uri && (uri == null || mUri == null || !uri.equals(mUri)))) { @@ -453,9 +453,10 @@ public class ImageView extends View { /** * Sets a drawable as the content of this ImageView. * - * @param drawable The drawable to set + * @param drawable the Drawable to set, or {@code null} to clear the + * content */ - public void setImageDrawable(Drawable drawable) { + public void setImageDrawable(@Nullable Drawable drawable) { if (mDrawable != drawable) { mResource = 0; mUri = null; @@ -475,16 +476,19 @@ public class ImageView extends View { /** * Sets the content of this ImageView to the specified Icon. * - * <p class="note">Depending on the Icon type, this may do Bitmap reading and decoding - * on the UI thread, which can cause UI jank. If that's a concern, consider using + * <p class="note">Depending on the Icon type, this may do Bitmap reading + * and decoding on the UI thread, which can cause UI jank. If that's a + * concern, consider using * {@link Icon#loadDrawableAsync(Context, Icon.OnDrawableLoadedListener, Handler)} - * and then {@link #setImageDrawable(android.graphics.drawable.Drawable)} instead.</p> + * and then {@link #setImageDrawable(android.graphics.drawable.Drawable)} + * instead.</p> * - * @param icon an Icon holding the desired image + * @param icon an Icon holding the desired image, or {@code null} to clear + * the content */ @android.view.RemotableViewMethod - public void setImageIcon(Icon icon) { - setImageDrawable(icon.loadDrawable(mContext)); + public void setImageIcon(@Nullable Icon icon) { + setImageDrawable(icon == null ? null : icon.loadDrawable(mContext)); } /** diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java index 4dcc242..b5e08ca 100644 --- a/core/java/android/widget/LinearLayout.java +++ b/core/java/android/widget/LinearLayout.java @@ -659,7 +659,8 @@ public class LinearLayout extends ViewGroup { */ private boolean allViewsAreGoneBefore(int childIndex) { for (int i = childIndex - 1; i >= 0; i--) { - if (getVirtualChildAt(i).getVisibility() != GONE) { + View child = getVirtualChildAt(i); + if (child != null && child.getVisibility() != GONE) { return false; } } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 7b58b5b..6b8abab 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -295,14 +295,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Accessibility action to share selected text. private static final int ACCESSIBILITY_ACTION_SHARE = 0x10000000; - // System wide time for last cut, copy or text changed action. - static long sLastCutCopyOrTextChangedTime; + /** + * @hide + */ + // Accessibility action start id for "process text" actions. + static final int ACCESSIBILITY_ACTION_PROCESS_TEXT_START_ID = 0x10000100; /** * @hide */ static final int PROCESS_TEXT_REQUEST_CODE = 100; + // System wide time for last cut, copy or text changed action. + static long sLastCutCopyOrTextChangedTime; + private ColorStateList mTextColor; private ColorStateList mHintTextColor; private ColorStateList mLinkTextColor; @@ -8837,12 +8843,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE); + info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); } if (isFocused()) { - if (canSelectText()) { - info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION); - } if (canCopy()) { info.addAction(AccessibilityNodeInfo.ACTION_COPY); } @@ -8857,6 +8861,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener ACCESSIBILITY_ACTION_SHARE, getResources().getString(com.android.internal.R.string.share))); } + if (canProcessText()) { // also implies mEditor is not null. + mEditor.mProcessTextIntentActionsHandler.onInitializeAccessibilityNodeInfo(info); + } } // Check for known input filter types. @@ -8881,6 +8888,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ @Override public boolean performAccessibilityActionInternal(int action, Bundle arguments) { + if (mEditor != null + && mEditor.mProcessTextIntentActionsHandler.performAccessibilityAction(action)) { + return true; + } switch (action) { case AccessibilityNodeInfo.ACTION_CLICK: { boolean handled = false; @@ -8931,30 +8942,28 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } } return false; case AccessibilityNodeInfo.ACTION_SET_SELECTION: { - if (isFocused() && canSelectText()) { - ensureIterableTextForAccessibilitySelectable(); - CharSequence text = getIterableTextForAccessibility(); - if (text == null) { - return false; + ensureIterableTextForAccessibilitySelectable(); + CharSequence text = getIterableTextForAccessibility(); + if (text == null) { + return false; + } + final int start = (arguments != null) ? arguments.getInt( + AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; + final int end = (arguments != null) ? arguments.getInt( + AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; + if ((getSelectionStart() != start || getSelectionEnd() != end)) { + // No arguments clears the selection. + if (start == end && end == -1) { + Selection.removeSelection((Spannable) text); + return true; } - final int start = (arguments != null) ? arguments.getInt( - AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1; - final int end = (arguments != null) ? arguments.getInt( - AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1; - if ((getSelectionStart() != start || getSelectionEnd() != end)) { - // No arguments clears the selection. - if (start == end && end == -1) { - Selection.removeSelection((Spannable) text); - return true; - } - if (start >= 0 && start <= end && end <= text.length()) { - Selection.setSelection((Spannable) text, start, end); - // Make sure selection mode is engaged. - if (mEditor != null) { - mEditor.startSelectionActionMode(); - } - return true; + if (start >= 0 && start <= end && end <= text.length()) { + Selection.setSelection((Spannable) text, start, end); + // Make sure selection mode is engaged. + if (mEditor != null) { + mEditor.startSelectionActionMode(); } + return true; } } } return false; @@ -8979,6 +8988,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** @hide */ @Override public void sendAccessibilityEventInternal(int eventType) { + if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED && mEditor != null) { + mEditor.mProcessTextIntentActionsHandler.initializeAccessibilityActions(); + } + // Do not send scroll events since first they are not interesting for // accessibility and second such events a generated too frequently. // For details see the implementation of bringTextIntoView(). diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 86c1b2f..201a124 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -25,6 +25,8 @@ interface IAppOpsService { // be kept in sync with frameworks/native/include/binder/IAppOpsService.h int checkOperation(int code, int uid, String packageName); int noteOperation(int code, int uid, String packageName); + int noteProxyOperation(int code, String proxyPackageName, + int callingUid, String callingPackageName); int startOperation(IBinder token, int code, int uid, String packageName); void finishOperation(IBinder token, int code, int uid, String packageName); void startWatchingMode(int op, String packageName, IAppOpsCallback callback); diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index a2bd700..8cd9bab 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -35,6 +35,7 @@ interface IVoiceInteractionManagerService { boolean hideSessionFromSession(IBinder token); int startVoiceActivity(IBinder token, in Intent intent, String resolvedType); void setKeepAwake(IBinder token, boolean keepAwake); + void closeSystemDialogs(IBinder token); void finish(IBinder token); /** diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index f598828..233bee3 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -87,9 +87,9 @@ public class IntentForwarderActivity extends Activity { if (canForward(newIntent, targetUserId)) { if (newIntent.getAction().equals(Intent.ACTION_CHOOSER)) { Intent innerIntent = (Intent) newIntent.getParcelableExtra(Intent.EXTRA_INTENT); - innerIntent.setContentUserHint(callingUserId); + innerIntent.prepareToLeaveUser(callingUserId); } else { - newIntent.setContentUserHint(callingUserId); + newIntent.prepareToLeaveUser(callingUserId); } final android.content.pm.ResolveInfo ri = getPackageManager().resolveActivityAsUser( diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java index 6dc66ea..263e522 100644 --- a/core/java/com/android/internal/logging/MetricsLogger.java +++ b/core/java/com/android/internal/logging/MetricsLogger.java @@ -41,6 +41,9 @@ public class MetricsLogger implements MetricsConstants { public static final int ACTION_BRIGHTNESS_AUTO = 219; public static final int BRIGHTNESS_DIALOG = 220; public static final int SYSTEM_ALERT_WINDOW_APPS = 221; + public static final int DREAMING = 222; + public static final int DOZING = 223; + // Temporary constants go here, to await migration to MetricsConstants. public static void visible(Context context, int category) throws IllegalArgumentException { diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index 6a85afb..264b8c1 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -480,6 +480,7 @@ public final class BatteryStatsHelper { final boolean forAllUsers = (asUsers.get(UserHandle.USER_ALL) != null); mStatsPeriod = mTypeBatteryRealtime; + BatterySipper osSipper = null; final SparseArray<? extends Uid> uidStats = mStats.getUidStats(); final int NU = uidStats.size(); for (int iu = 0; iu < NU; iu++) { @@ -526,15 +527,19 @@ public final class BatteryStatsHelper { } if (uid == 0) { - // The device has probably been awake for longer than the screen on - // time and application wake lock time would account for. Assign - // this remainder to the OS, if possible. - mWakelockPowerCalculator.calculateRemaining(app, mStats, mRawRealtime, - mRawUptime, mStatsType); - app.sumPower(); + osSipper = app; } } } + + if (osSipper != null) { + // The device has probably been awake for longer than the screen on + // time and application wake lock time would account for. Assign + // this remainder to the OS, if possible. + mWakelockPowerCalculator.calculateRemaining(osSipper, mStats, mRawRealtime, + mRawUptime, mStatsType); + osSipper.sumPower(); + } } private void addPhoneUsage() { diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 1bd821d..8b4b994 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -106,7 +106,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 129 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 130 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -4386,6 +4386,7 @@ public final class BatteryStatsImpl extends BatteryStats { LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase); LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase); + LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase); LongSamplingCounter[] mSpeedBins; /** @@ -4978,6 +4979,11 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override + public long getCpuPowerMaUs(int which) { + return mCpuPower.getCountLocked(which); + } + + @Override public long getTimeAtCpuSpeed(int step, int which) { if (step >= 0 && step < mSpeedBins.length) { if (mSpeedBins[step] != null) { @@ -5097,6 +5103,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.reset(false); mSystemCpuTime.reset(false); + mCpuPower.reset(false); for (int i = 0; i < mSpeedBins.length; i++) { LongSamplingCounter c = mSpeedBins[i]; if (c != null) { @@ -5248,6 +5255,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.detach(); mSystemCpuTime.detach(); + mCpuPower.detach(); for (int i = 0; i < mSpeedBins.length; i++) { LongSamplingCounter c = mSpeedBins[i]; if (c != null) { @@ -5427,6 +5435,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.writeToParcel(out); mSystemCpuTime.writeToParcel(out); + mCpuPower.writeToParcel(out); out.writeInt(mSpeedBins.length); for (int i = 0; i < mSpeedBins.length; i++) { @@ -5618,6 +5627,7 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in); mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in); + mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in); int bins = in.readInt(); int steps = getCpuSpeedSteps(); @@ -7964,7 +7974,8 @@ public final class BatteryStatsImpl extends BatteryStats { mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null : new KernelUidCpuTimeReader.Callback() { @Override - public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) { + public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, + long powerMaUs) { final Uid u = getUidStatsLocked(mapUid(uid)); // Accumulate the total system and user time. @@ -7978,7 +7989,7 @@ public final class BatteryStatsImpl extends BatteryStats { TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); - sb.append("\n"); + sb.append(" p=").append(powerMaUs / 1000).append("mAms\n"); } if (numWakelocksF > 0) { @@ -7994,11 +8005,13 @@ public final class BatteryStatsImpl extends BatteryStats { TimeUtils.formatDuration(userTimeUs / 1000, sb); sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); + sb.append(" p=").append(powerMaUs / 1000).append("mAms"); Slog.d(TAG, sb.toString()); } u.mUserCpuTime.addCountLocked(userTimeUs); u.mSystemCpuTime.addCountLocked(systemTimeUs); + u.mCpuPower.addCountLocked(powerMaUs); // Add the cpu speeds to this UID. These are used as a ratio // for computing the power this UID used. @@ -9229,6 +9242,7 @@ public final class BatteryStatsImpl extends BatteryStats { u.mUserCpuTime.readSummaryFromParcelLocked(in); u.mSystemCpuTime.readSummaryFromParcelLocked(in); + u.mCpuPower.readSummaryFromParcelLocked(in); int NSB = in.readInt(); if (NSB > 100) { @@ -9575,6 +9589,7 @@ public final class BatteryStatsImpl extends BatteryStats { u.mUserCpuTime.writeSummaryFromParcelLocked(out); u.mSystemCpuTime.writeSummaryFromParcelLocked(out); + u.mCpuPower.writeSummaryFromParcelLocked(out); out.writeInt(u.mSpeedBins.length); for (int i = 0; i < u.mSpeedBins.length; i++) { diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index 41efd2c..45cc8b2 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -30,7 +30,7 @@ import java.io.IOException; /** * Reads /proc/uid_cputime/show_uid_stat which has the line format: * - * uid: user_time_micro_seconds system_time_micro_seconds + * uid: user_time_micro_seconds system_time_micro_seconds power_in_milli-amp-micro_seconds * * This provides the time a UID's processes spent executing in user-space and kernel-space. * The file contains a monotonically increasing count of time for a single boot. This class @@ -46,11 +46,18 @@ public class KernelUidCpuTimeReader { * Callback interface for processing each line of the proc file. */ public interface Callback { - void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs); + /** + * @param uid UID of the app + * @param userTimeUs time spent executing in user space in microseconds + * @param systemTimeUs time spent executing in kernel space in microseconds + * @param powerMaUs power consumed executing, in milli-ampere microseconds + */ + void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, long powerMaUs); } private SparseLongArray mLastUserTimeUs = new SparseLongArray(); private SparseLongArray mLastSystemTimeUs = new SparseLongArray(); + private SparseLongArray mLastPowerMaUs = new SparseLongArray(); private long mLastTimeReadUs = 0; /** @@ -70,50 +77,65 @@ public class KernelUidCpuTimeReader { final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10); final long userTimeUs = Long.parseLong(splitter.next(), 10); final long systemTimeUs = Long.parseLong(splitter.next(), 10); + final long powerMaUs; + if (splitter.hasNext()) { + powerMaUs = Long.parseLong(splitter.next(), 10) / 1000; + } else { + powerMaUs = 0; + } if (callback != null) { long userTimeDeltaUs = userTimeUs; long systemTimeDeltaUs = systemTimeUs; + long powerDeltaMaUs = powerMaUs; int index = mLastUserTimeUs.indexOfKey(uid); if (index >= 0) { userTimeDeltaUs -= mLastUserTimeUs.valueAt(index); systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index); + powerDeltaMaUs -= mLastPowerMaUs.valueAt(index); final long timeDiffUs = nowUs - mLastTimeReadUs; - if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || + if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0 || userTimeDeltaUs > timeDiffUs || systemTimeDeltaUs > timeDiffUs) { - StringBuilder sb = new StringBuilder("Malformed cpu data!\n"); + StringBuilder sb = new StringBuilder("Malformed cpu data for UID="); + sb.append(uid).append("!\n"); sb.append("Time between reads: "); TimeUtils.formatDuration(timeDiffUs / 1000, sb); - sb.append("ms\n"); + sb.append("\n"); sb.append("Previous times: u="); TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb); - sb.append("ms s="); + sb.append(" s="); TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb); - sb.append("ms\n"); + sb.append(" p=").append(mLastPowerMaUs.valueAt(index) / 1000); + sb.append("mAms\n"); + sb.append("Current times: u="); TimeUtils.formatDuration(userTimeUs / 1000, sb); - sb.append("ms s="); + sb.append(" s="); TimeUtils.formatDuration(systemTimeUs / 1000, sb); - sb.append("ms\n"); - sb.append("Delta for UID=").append(uid).append(": u="); + sb.append(" p=").append(powerMaUs / 1000); + sb.append("mAms\n"); + sb.append("Delta: u="); TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb); - sb.append("ms s="); + sb.append(" s="); TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb); - sb.append("ms"); + sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms"); Slog.wtf(TAG, sb.toString()); userTimeDeltaUs = 0; systemTimeDeltaUs = 0; + powerDeltaMaUs = 0; } } - if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) { - callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs); + if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0 || powerDeltaMaUs != 0) { + callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs, + powerDeltaMaUs); } } mLastUserTimeUs.put(uid, userTimeUs); mLastSystemTimeUs.put(uid, systemTimeUs); + mLastPowerMaUs.put(uid, powerMaUs); } } catch (IOException e) { Slog.e(TAG, "Failed to read uid_cputime", e); diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl index aea1585..63bfbe5 100644 --- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl @@ -44,7 +44,7 @@ interface IStatusBarService // You need the STATUS_BAR_SERVICE permission void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList, out int[] switches, out List<IBinder> binders); - void onPanelRevealed(boolean clearNotificationEffects); + void onPanelRevealed(boolean clearNotificationEffects, int numItems); void onPanelHidden(); // Mark current notifications as "seen" and stop ringing, vibrating, blinking. void clearNotificationEffects(); diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java index 3b1f20d..08d4e86 100644 --- a/core/java/com/android/internal/view/menu/MenuItemImpl.java +++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java @@ -593,7 +593,7 @@ public final class MenuItemImpl implements MenuItem { public MenuItem setActionProvider(ActionProvider actionProvider) { if (mActionProvider != null) { - mActionProvider.setVisibilityListener(null); + mActionProvider.reset(); } mActionView = null; mActionProvider = actionProvider; diff --git a/core/java/com/android/internal/widget/DrawingSpace.java b/core/java/com/android/internal/widget/DrawingSpace.java new file mode 100644 index 0000000..b8222db --- /dev/null +++ b/core/java/com/android/internal/widget/DrawingSpace.java @@ -0,0 +1,76 @@ +/* + * 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.internal.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +/** + * Implementation of {@link android.widget.Space} that uses normal View drawing + * rather than a no-op. Useful for dialogs and other places where the base View + * class is too greedy when measured with AT_MOST. + */ +public final class DrawingSpace extends View { + public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public DrawingSpace(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DrawingSpace(Context context) { + this(context, null); + } + + /** + * Compare to: {@link View#getDefaultSize(int, int)} + * <p> + * If mode is AT_MOST, return the child size instead of the parent size + * (unless it is too big). + */ + private static int getDefaultSizeNonGreedy(int size, int measureSpec) { + int result = size; + int specMode = MeasureSpec.getMode(measureSpec); + int specSize = MeasureSpec.getSize(measureSpec); + + switch (specMode) { + case MeasureSpec.UNSPECIFIED: + result = size; + break; + case MeasureSpec.AT_MOST: + result = Math.min(size, specSize); + break; + case MeasureSpec.EXACTLY: + result = specSize; + break; + } + return result; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + setMeasuredDimension( + getDefaultSizeNonGreedy(getSuggestedMinimumWidth(), widthMeasureSpec), + getDefaultSizeNonGreedy(getSuggestedMinimumHeight(), heightMeasureSpec)); + } +} |