diff options
Diffstat (limited to 'core/java')
33 files changed, 540 insertions, 272 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 9c2e208..d07238a 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -3723,6 +3723,12 @@ public class Activity extends ContextThemeWrapper * #checkSelfPermission(String)}. * </p> * <p> + * You cannot request a permission if your activity sets {@link + * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to + * <code>true</code> because in this case the activity would not receive + * result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}. + * </p> + * <p> * A sample permissions request looks like this: * </p> * <code><pre><p> @@ -3749,6 +3755,7 @@ public class Activity extends ContextThemeWrapper * @param permissions The requested permissions. * @param requestCode Application specific request code to match with a result * reported to {@link #onRequestPermissionsResult(int, String[], int[])}. + * Should be >= 0. * * @see #onRequestPermissionsResult(int, String[], int[]) * @see #checkSelfPermission(String) 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/Fragment.java b/core/java/android/app/Fragment.java index 95b3b8e..5490fe7 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -1166,6 +1166,12 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * android.content.Context#checkSelfPermission(String)}. * </p> * <p> + * You cannot request a permission if your activity sets {@link + * android.R.styleable#AndroidManifestActivity_noHistory noHistory} to + * <code>true</code> because in this case the activity would not receive + * result callbacks including {@link #onRequestPermissionsResult(int, String[], int[])}. + * </p> + * <p> * A sample permissions request looks like this: * </p> * <code><pre><p> @@ -1192,6 +1198,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene * @param permissions The requested permissions. * @param requestCode Application specific request code to match with a result * reported to {@link #onRequestPermissionsResult(int, String[], int[])}. + * Should be >= 0. * * @see #onRequestPermissionsResult(int, String[], int[]) * @see android.content.Context#checkSelfPermission(String) 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/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java index abb8244..bf7458c 100644 --- a/core/java/android/app/VoiceInteractor.java +++ b/core/java/android/app/VoiceInteractor.java @@ -253,7 +253,8 @@ public final class VoiceInteractor { /** * Report from voice interaction service: this operation has been canceled, typically - * as a completion of a previous call to {@link #cancel}. + * as a completion of a previous call to {@link #cancel} or when the user explicitly + * cancelled. */ public void onCancel() { } @@ -288,7 +289,8 @@ public final class VoiceInteractor { * would require the user to touch the screen when voice interaction mode is not enabled. * The result of the confirmation will be returned through an asynchronous call to * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or - * {@link #onCancel()}. + * {@link #onCancel()} - these methods should be overridden to define the application specific + * behavior. * * <p>In some cases this may be a simple yes / no confirmation or the confirmation could * include context information about how the action will be completed @@ -315,13 +317,19 @@ public final class VoiceInteractor { * @param prompt Optional confirmation to speak to the user or null if nothing * should be spoken. * @param extras Additional optional information or null. - * @deprecated Prefer the version that takes a {@link Prompt}. + * @hide */ public ConfirmationRequest(CharSequence prompt, Bundle extras) { mPrompt = (prompt != null ? new Prompt(prompt) : null); mExtras = extras; } + /** + * Handle the confirmation result. Override this method to define + * the behavior when the user confirms or rejects the operation. + * @param confirmed Whether the user confirmed or rejected the operation. + * @param result Additional result information or null. + */ public void onConfirmationResult(boolean confirmed, Bundle result) { } @@ -336,7 +344,8 @@ public final class VoiceInteractor { * VoiceInteractionService. Typically, the application would present this visually as * a list view to allow selecting the option by touch. * The result of the confirmation will be returned through an asynchronous call to - * either {@link #onPickOptionResult} or {@link #onCancel()}. + * either {@link #onPickOptionResult} or {@link #onCancel()} - these methods should + * be overridden to define the application specific behavior. */ public static class PickOptionRequest extends Request { final Prompt mPrompt; @@ -344,7 +353,9 @@ public final class VoiceInteractor { final Bundle mExtras; /** - * Represents a single option that the user may select using their voice. + * Represents a single option that the user may select using their voice. The + * {@link #getIndex()} method should be used as a unique ID to identify the option + * when it is returned from the voice interactor. */ public static final class Option implements Parcelable { final CharSequence mLabel; @@ -357,6 +368,7 @@ public final class VoiceInteractor { * or one of several synonyms. * @param label The label that will both be matched against what the user speaks * and displayed visually. + * @hide */ public Option(CharSequence label) { mLabel = label; @@ -481,7 +493,7 @@ public final class VoiceInteractor { * presented or null if nothing should be asked. * @param options The set of {@link Option}s the user is selecting from. * @param extras Additional optional information or null. - * @deprecated Prefer the version that takes a {@link Prompt}. + * @hide */ public PickOptionRequest(CharSequence prompt, Option[] options, Bundle extras) { mPrompt = (prompt != null ? new Prompt(prompt) : null); @@ -490,7 +502,9 @@ public final class VoiceInteractor { } /** - * Called when a single option is confirmed or narrowed to one of several options. + * Called when a single option is confirmed or narrowed to one of several options. Override + * this method to define the behavior when the user selects an option or narrows down the + * set of options. * @param finished True if the voice interaction has finished making a selection, in * which case {@code selections} contains the final result. If false, this request is * still active and you will continue to get calls on it. @@ -536,7 +550,7 @@ public final class VoiceInteractor { * @param message Optional message to speak to the user about the completion status of * the task or null if nothing should be spoken. * @param extras Additional optional information or null. - * @deprecated Prefer the version that takes a {@link Prompt}. + * @hide */ public CompleteVoiceRequest(CharSequence message, Bundle extras) { mPrompt = (message != null ? new Prompt(message) : null); @@ -583,7 +597,7 @@ public final class VoiceInteractor { * @param message Optional message to speak to the user indicating why the task could * not be completed by voice or null if nothing should be spoken. * @param extras Additional optional information or null. - * @deprecated Prefer the version that takes a {@link Prompt}. + * @hide */ public AbortVoiceRequest(CharSequence message, Bundle extras) { mPrompt = (message != null ? new Prompt(message) : null); 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/PackageManager.java b/core/java/android/content/pm/PackageManager.java index dd1c5c2..538007a 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1924,7 +1924,6 @@ public abstract class PackageManager { * * @hide */ - @SystemApi public static final int FLAG_PERMISSION_USER_SET = 1 << 0; /** @@ -1934,7 +1933,6 @@ public abstract class PackageManager { * * @hide */ - @SystemApi public static final int FLAG_PERMISSION_USER_FIXED = 1 << 1; /** @@ -1944,7 +1942,6 @@ public abstract class PackageManager { * * @hide */ - @SystemApi public static final int FLAG_PERMISSION_POLICY_FIXED = 1 << 2; /** @@ -1957,7 +1954,6 @@ public abstract class PackageManager { * * @hide */ - @SystemApi public static final int FLAG_PERMISSION_REVOKE_ON_UPGRADE = 1 << 3; /** @@ -1966,9 +1962,19 @@ public abstract class PackageManager { * * @hide */ - @SystemApi public static final int FLAG_PERMISSION_SYSTEM_FIXED = 1 << 4; + + /** + * Permission flag: The permission is granted by default because it + * enables app functionality that is expected to work out-of-the-box + * for providing a smooth user experience. For example, the phone app + * is expected to have the phone permission. + * + * @hide + */ + public static final int FLAG_PERMISSION_GRANTED_BY_DEFAULT = 1 << 5; + /** * Mask for all permission flags. * @@ -2474,7 +2480,8 @@ public abstract class PackageManager { FLAG_PERMISSION_USER_FIXED, FLAG_PERMISSION_POLICY_FIXED, FLAG_PERMISSION_REVOKE_ON_UPGRADE, - FLAG_PERMISSION_SYSTEM_FIXED}) + FLAG_PERMISSION_SYSTEM_FIXED, + FLAG_PERMISSION_GRANTED_BY_DEFAULT}) @Retention(RetentionPolicy.SOURCE) public @interface PermissionFlags {} @@ -4634,6 +4641,19 @@ public abstract class PackageManager { } /** {@hide} */ + public static String permissionFlagToString(int flag) { + switch (flag) { + case FLAG_PERMISSION_GRANTED_BY_DEFAULT: return "FLAG_PERMISSION_GRANTED_BY_DEFAULT"; + case FLAG_PERMISSION_POLICY_FIXED: return "FLAG_PERMISSION_POLICY_FIXED"; + case FLAG_PERMISSION_SYSTEM_FIXED: return "FLAG_PERMISSION_SYSTEM_FIXED"; + case FLAG_PERMISSION_USER_SET: return "FLAG_PERMISSION_USER_SET"; + case FLAG_PERMISSION_REVOKE_ON_UPGRADE: return "FLAG_PERMISSION_REVOKE_ON_UPGRADE"; + case FLAG_PERMISSION_USER_FIXED: return "FLAG_PERMISSION_USER_FIXED"; + default: return Integer.toString(flag); + } + } + + /** {@hide} */ public static class LegacyPackageInstallObserver extends PackageInstallObserver { private final IPackageInstallObserver mLegacy; 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/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/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/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index 76bd0ec..d619c0a 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -406,7 +406,7 @@ public final class NfcActivityManager extends IAppCallback.Stub Intent.FLAG_GRANT_READ_URI_PERMISSION); } } - return new BeamShareData(message, uris, UserHandle.CURRENT, flags); + return new BeamShareData(message, uris, new UserHandle(UserHandle.myUserId()), flags); } /** Callback from NFC service, usually on binder thread */ diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index 511bd5f..20bcf62 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -221,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/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/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 7eb936a..a7e0e08 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -1001,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() { diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index bbdb0e1..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); } @@ -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/text/Hyphenator.java b/core/java/android/text/Hyphenator.java index 67c36e3..1ee3827 100644 --- a/core/java/android/text/Hyphenator.java +++ b/core/java/android/text/Hyphenator.java @@ -21,9 +21,10 @@ import com.android.internal.annotations.GuardedBy; import android.annotation.Nullable; import android.util.Log; +import libcore.io.IoUtils; + import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; import java.util.HashMap; import java.util.Locale; @@ -42,9 +43,9 @@ public class Hyphenator { private final static Object sLock = new Object(); @GuardedBy("sLock") - static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>(); + final static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>(); - private long mNativePtr; + final private long mNativePtr; private Hyphenator(long nativePtr) { mNativePtr = nativePtr; @@ -90,17 +91,13 @@ public class Hyphenator { String patternFilename = "hyph-"+languageTag.toLowerCase(Locale.US)+".pat.txt"; File patternFile = new File(getSystemHyphenatorLocation(), patternFilename); try { - RandomAccessFile rf = new RandomAccessFile(patternFile, "r"); - byte[] buf = new byte[(int)rf.length()]; - rf.read(buf); - rf.close(); - String patternData = new String(buf); + String patternData = IoUtils.readFileAsString(patternFile.getAbsolutePath()); long nativePtr = StaticLayout.nLoadHyphenator(patternData); return new Hyphenator(nativePtr); } catch (IOException e) { Log.e(TAG, "error loading hyphenation " + patternFile, e); + return null; } - return null; } private static File getSystemHyphenatorLocation() { 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/ViewAnimationUtils.java b/core/java/android/view/ViewAnimationUtils.java index d44df31..4c75935 100644 --- a/core/java/android/view/ViewAnimationUtils.java +++ b/core/java/android/view/ViewAnimationUtils.java @@ -43,8 +43,10 @@ public final class ViewAnimationUtils { * on thread responsiveness. * * @param view The View will be clipped to the animating circle. - * @param centerX The x coordinate of the center of the animating circle. - * @param centerY The y coordinate of the center of the animating circle. + * @param centerX The x coordinate of the center of the animating circle, relative to + * <code>view</code>. + * @param centerY The y coordinate of the center of the animating circle, relative to + * <code>view</code>. * @param startRadius The starting radius of the animating circle. * @param endRadius The ending radius of the animating circle. */ 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/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/TextView.java b/core/java/android/widget/TextView.java index 422511f..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; @@ -8855,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. @@ -8879,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; @@ -8975,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/ExternalMediaFormatActivity.java b/core/java/com/android/internal/app/ExternalMediaFormatActivity.java deleted file mode 100644 index fc213c5..0000000 --- a/core/java/com/android/internal/app/ExternalMediaFormatActivity.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2007 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.app; - -import com.android.internal.os.storage.ExternalStorageFormatter; - -import android.app.AlertDialog; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Bundle; -import android.os.storage.StorageVolume; -import android.util.Log; - -/** - * This activity is shown to the user to confirm formatting of external media. - * It uses the alert dialog style. It will be launched from a notification, or from settings - */ -public class ExternalMediaFormatActivity extends AlertActivity implements DialogInterface.OnClickListener { - - private static final int POSITIVE_BUTTON = AlertDialog.BUTTON_POSITIVE; - - /** Used to detect when the media state changes, in case we need to call finish() */ - private BroadcastReceiver mStorageReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - Log.d("ExternalMediaFormatActivity", "got action " + action); - - if (action == Intent.ACTION_MEDIA_REMOVED || - action == Intent.ACTION_MEDIA_CHECKING || - action == Intent.ACTION_MEDIA_MOUNTED || - action == Intent.ACTION_MEDIA_SHARED) { - finish(); - } - } - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - Log.d("ExternalMediaFormatActivity", "onCreate!"); - // Set up the "dialog" - final AlertController.AlertParams p = mAlertParams; - p.mTitle = getString(com.android.internal.R.string.extmedia_format_title); - p.mMessage = getString(com.android.internal.R.string.extmedia_format_message); - p.mPositiveButtonText = getString(com.android.internal.R.string.extmedia_format_button_format); - p.mPositiveButtonListener = this; - p.mNegativeButtonText = getString(com.android.internal.R.string.cancel); - p.mNegativeButtonListener = this; - setupAlert(); - } - - @Override - protected void onResume() { - super.onResume(); - - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_MEDIA_REMOVED); - filter.addAction(Intent.ACTION_MEDIA_CHECKING); - filter.addAction(Intent.ACTION_MEDIA_MOUNTED); - filter.addAction(Intent.ACTION_MEDIA_SHARED); - registerReceiver(mStorageReceiver, filter); - } - - @Override - protected void onPause() { - super.onPause(); - - unregisterReceiver(mStorageReceiver); - } - - /** - * {@inheritDoc} - */ - public void onClick(DialogInterface dialog, int which) { - - if (which == POSITIVE_BUTTON) { - Intent intent = new Intent(ExternalStorageFormatter.FORMAT_ONLY); - intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME); - // Transfer the storage volume to the new intent - final StorageVolume storageVolume = getIntent().getParcelableExtra( - StorageVolume.EXTRA_STORAGE_VOLUME); - intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, storageVolume); - startService(intent); - } - - // No matter what, finish the activity - finish(); - } -} diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 86c1b2f..73c4833 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -31,6 +31,8 @@ interface IAppOpsService { void stopWatchingMode(IAppOpsCallback callback); IBinder getToken(IBinder clientToken); int permissionToOpCode(String permission); + int noteProxyOperation(int code, String proxyPackageName, + int callingUid, String callingPackageName); // Remaining methods are only used in Java. int checkPackage(int uid, String packageName); 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/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index e2d366a..45cc8b2 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -77,7 +77,12 @@ 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 = Long.parseLong(splitter.next(), 10) / 1000; + final long powerMaUs; + if (splitter.hasNext()) { + powerMaUs = Long.parseLong(splitter.next(), 10) / 1000; + } else { + powerMaUs = 0; + } if (callback != null) { long userTimeDeltaUs = userTimeUs; |