diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/accounts/AccountManagerService.java | 13 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 43 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 14 | ||||
| -rw-r--r-- | core/java/android/app/ActivityOptions.java | 141 | ||||
| -rw-r--r-- | core/java/android/app/Fragment.java | 7 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
| -rw-r--r-- | core/java/android/app/PendingIntent.java | 86 | ||||
| -rw-r--r-- | core/java/android/content/ContentProvider.java | 87 | ||||
| -rw-r--r-- | core/java/android/content/Context.java | 12 | ||||
| -rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 3 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManager.java | 5 | ||||
| -rw-r--r-- | core/java/android/os/Process.java | 6 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 2 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 4 | ||||
| -rw-r--r-- | core/java/android/webkit/HTML5VideoViewProxy.java | 6 |
15 files changed, 358 insertions, 73 deletions
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index adc7d35..cf1e8f3 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -1780,7 +1780,7 @@ public class AccountManagerService if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "performing bindService to " + authenticatorInfo.componentName); } - if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { + if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE, mAccounts.userId)) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "bindService to " + authenticatorInfo.componentName + " failed"); } @@ -1817,7 +1817,16 @@ public class AccountManagerService // Migrate old file, if it exists, to the new location File oldFile = new File(systemDir, DATABASE_NAME); if (oldFile.exists()) { - oldFile.renameTo(databaseFile); + // Check for use directory; create if it doesn't exist, else renameTo will fail + File userDir = new File(systemDir, "users/" + userId); + if (!userDir.exists()) { + if (!userDir.mkdirs()) { + throw new IllegalStateException("User dir cannot be created: " + userDir); + } + } + if (!oldFile.renameTo(databaseFile)) { + throw new IllegalStateException("User dir cannot be migrated: " + databaseFile); + } } } return databaseFile.getPath(); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index dc12acd..ea32745 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -32,7 +32,6 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; -import android.content.res.Resources.Theme; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Canvas; @@ -55,7 +54,6 @@ import android.util.AttributeSet; import android.util.EventLog; import android.util.Log; import android.util.SparseArray; -import android.util.TypedValue; import android.view.ActionMode; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; @@ -3208,7 +3206,8 @@ public class Activity extends ContextThemeWrapper * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * @@ -3288,7 +3287,10 @@ public class Activity extends ContextThemeWrapper * <var>flagsMask</var> * @param extraFlags Always set to 0. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. If options + * have also been supplied by the IntentSender, options given here will + * override any that conflict with those given by the IntentSender. */ public void startIntentSenderForResult(IntentSender intent, int requestCode, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, @@ -3369,7 +3371,8 @@ public class Activity extends ContextThemeWrapper * * @param intent The intent to start. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * @@ -3417,7 +3420,8 @@ public class Activity extends ContextThemeWrapper * * @param intents The intents to start. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * @@ -3465,7 +3469,10 @@ public class Activity extends ContextThemeWrapper * <var>flagsMask</var> * @param extraFlags Always set to 0. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. If options + * have also been supplied by the IntentSender, options given here will + * override any that conflict with those given by the IntentSender. */ public void startIntentSender(IntentSender intent, Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, @@ -3521,7 +3528,8 @@ public class Activity extends ContextThemeWrapper * onActivityResult() when the activity exits, as described in * {@link #startActivityForResult}. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @return If a new activity was launched then true is returned; otherwise * false is returned and you must handle the Intent yourself. @@ -3592,7 +3600,8 @@ public class Activity extends ContextThemeWrapper * your own activity; the only changes you can make are to the extras * inside of it. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @return Returns a boolean indicating whether there was another Activity * to start: true if there was a next activity to start, false if there @@ -3644,7 +3653,8 @@ public class Activity extends ContextThemeWrapper * @param intent The intent to start. * @param requestCode Reply request code. < 0 if reply is not requested. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * @@ -3694,7 +3704,8 @@ public class Activity extends ContextThemeWrapper * @param intent The intent to start. * @param requestCode Reply request code. < 0 if reply is not requested. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @throws android.content.ActivityNotFoundException * @@ -3744,6 +3755,14 @@ public class Activity extends ContextThemeWrapper * Call immediately after one of the flavors of {@link #startActivity(Intent)} * or {@link #finish} to specify an explicit transition animation to * perform next. + * + * <p>As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN} an alternative + * to using this with starting activities is to supply the desired animation + * information through a {@link ActivityOptions} bundle to + * {@link #startActivity(Intent, Bundle) or a related function. This allows + * you to specify a custom animation even when starting an activity from + * outside the context of the current top activity. + * * @param enterAnim A resource ID of the animation resource to use for * the incoming activity. Use 0 for no animation. * @param exitAnim A resource ID of the animation resource to use for @@ -4065,7 +4084,7 @@ public class Activity extends ContextThemeWrapper ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName, mParent == null ? mToken : mParent.mToken, - mEmbeddedID, requestCode, new Intent[] { data }, null, flags); + mEmbeddedID, requestCode, new Intent[] { data }, null, flags, null); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { // Empty diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 732d211..a3cc352 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -835,9 +835,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM requestResolvedTypes = null; } int fl = data.readInt(); + Bundle options = data.readInt() != 0 + ? Bundle.CREATOR.createFromParcel(data) : null; IIntentSender res = getIntentSender(type, packageName, token, resultWho, requestCode, requestIntents, - requestResolvedTypes, fl); + requestResolvedTypes, fl, options); reply.writeNoException(); reply.writeStrongBinder(res != null ? res.asBinder() : null); return true; @@ -2607,8 +2609,8 @@ class ActivityManagerProxy implements IActivityManager } public IIntentSender getIntentSender(int type, String packageName, IBinder token, String resultWho, - int requestCode, Intent[] intents, String[] resolvedTypes, int flags) - throws RemoteException { + int requestCode, Intent[] intents, String[] resolvedTypes, int flags, + Bundle options) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); @@ -2625,6 +2627,12 @@ class ActivityManagerProxy implements IActivityManager data.writeInt(0); } data.writeInt(flags); + if (options != null) { + data.writeInt(1); + options.writeToParcel(data, 0); + } else { + data.writeInt(0); + } mRemote.transact(GET_INTENT_SENDER_TRANSACTION, data, reply, 0); reply.readException(); IIntentSender res = IIntentSender.Stub.asInterface( diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java new file mode 100644 index 0000000..03bc338 --- /dev/null +++ b/core/java/android/app/ActivityOptions.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.content.Context; +import android.os.Bundle; + +/** + * Helper class for building an options Bundle that can be used with + * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle) + * Context.startActivity(Intent, Bundle)} and related methods. + */ +public class ActivityOptions { + /** + * The package name that created the options. + * @hide + */ + public static final String KEY_PACKAGE_NAME = "android:packageName"; + + /** + * Custom enter animation resource ID. + * @hide + */ + public static final String KEY_ANIM_ENTER_RES_ID = "android:animEnterRes"; + + /** + * Custom exit animation resource ID. + * @hide + */ + public static final String KEY_ANIM_EXIT_RES_ID = "android:animExitRes"; + + private String mPackageName; + private boolean mIsCustomAnimation; + private int mCustomEnterResId; + private int mCustomExitResId; + + /** + * Create an ActivityOptions specifying a custom animation to run when + * the activity is displayed. + * + * @param context Who is defining this. This is the application that the + * animation resources will be loaded from. + * @param enterResId A resource ID of the animation resource to use for + * the incoming activity. Use 0 for no animation. + * @param exitResId A resource ID of the animation resource to use for + * the outgoing activity. Use 0 for no animation. + * @return Returns a new ActivityOptions object that you can use to + * supply these options as the options Bundle when starting an activity. + */ + public static ActivityOptions makeCustomAnimation(Context context, + int enterResId, int exitResId) { + ActivityOptions opts = new ActivityOptions(); + opts.mPackageName = context.getPackageName(); + opts.mIsCustomAnimation = true; + opts.mCustomEnterResId = enterResId; + opts.mCustomExitResId = exitResId; + return opts; + } + + private ActivityOptions() { + } + + /** @hide */ + public ActivityOptions(Bundle opts) { + mPackageName = opts.getString(KEY_PACKAGE_NAME); + if (opts.containsKey(KEY_ANIM_ENTER_RES_ID)) { + mIsCustomAnimation = true; + mCustomEnterResId = opts.getInt(KEY_ANIM_ENTER_RES_ID, 0); + mCustomExitResId = opts.getInt(KEY_ANIM_EXIT_RES_ID, 0); + } + } + + /** @hide */ + public String getPackageName() { + return mPackageName; + } + + /** @hide */ + public boolean isCustomAnimation() { + return mIsCustomAnimation; + } + + /** @hide */ + public int getCustomEnterResId() { + return mCustomEnterResId; + } + + /** @hide */ + public int getCustomExitResId() { + return mCustomExitResId; + } + + /** + * Join the values in <var>otherOptions</var> in to this one. Any values + * defined in <var>otherOptions</var> replace those in the base options. + */ + public void join(ActivityOptions otherOptions) { + if (otherOptions.mPackageName != null) { + mPackageName = otherOptions.mPackageName; + } + if (otherOptions.mIsCustomAnimation) { + mIsCustomAnimation = true; + mCustomEnterResId = otherOptions.mCustomEnterResId; + mCustomExitResId = otherOptions.mCustomExitResId; + } + } + + /** + * Returns the created options as a Bundle, which can be passed to + * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle) + * Context.startActivity(Intent, Bundle)} and related methods. + * Note that the returned Bundle is still owned by the ActivityOptions + * object; you must not modify it, but can supply it to the startActivity + * methods that take an options Bundle. + */ + public Bundle toBundle() { + Bundle b = new Bundle(); + if (mPackageName != null) { + b.putString(KEY_PACKAGE_NAME, mPackageName); + } + if (mIsCustomAnimation) { + b.putInt(KEY_ANIM_ENTER_RES_ID, mCustomEnterResId); + b.putInt(KEY_ANIM_EXIT_RES_ID, mCustomExitResId); + } + return b; + } +} diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index dadc4e5..c493f0f 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -965,6 +965,8 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene /** * Call {@link Activity#startActivity(Intent)} on the fragment's * containing Activity. + * + * @param intent The intent to start. */ public void startActivity(Intent intent) { startActivity(intent, null); @@ -973,6 +975,11 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene /** * Call {@link Activity#startActivity(Intent, Bundle)} on the fragment's * containing Activity. + * + * @param intent The intent to start. + * @param options Additional options for how the Activity should be started. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. */ public void startActivity(Intent intent, Bundle options) { if (mActivity == null) { diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 9306bd2..31066b5 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -169,7 +169,7 @@ public interface IActivityManager extends IInterface { public IIntentSender getIntentSender(int type, String packageName, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, - int flags) throws RemoteException; + int flags, Bundle options) throws RemoteException; public void cancelIntentSender(IIntentSender sender) throws RemoteException; public boolean clearApplicationUserData(final String packageName, final IPackageDataObserver observer, int userId) throws RemoteException; diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java index 57192c3..aa366b6 100644 --- a/core/java/android/app/PendingIntent.java +++ b/core/java/android/app/PendingIntent.java @@ -188,6 +188,35 @@ public final class PendingIntent implements Parcelable { */ public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags) { + return getActivity(context, requestCode, intent, flags, null); + } + + /** + * Retrieve a PendingIntent that will start a new activity, like calling + * {@link Context#startActivity(Intent) Context.startActivity(Intent)}. + * Note that the activity will be started outside of the context of an + * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK + * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. + * + * @param context The Context in which this PendingIntent should start + * the activity. + * @param requestCode Private request code for the sender (currently + * not used). + * @param intent Intent of the activity to be launched. + * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, + * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, + * or any of the flags as supported by + * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts + * of the intent that can be supplied when the actual send happens. + * @param options Additional options for how the Activity should be started. + * May be null if there are no options. + * + * @return Returns an existing or new PendingIntent matching the given + * parameters. May return null only if {@link #FLAG_NO_CREATE} has been + * supplied. + */ + public static PendingIntent getActivity(Context context, int requestCode, + Intent intent, int flags, Bundle options) { String packageName = context.getPackageName(); String resolvedType = intent != null ? intent.resolveTypeIfNeeded( context.getContentResolver()) : null; @@ -197,7 +226,8 @@ public final class PendingIntent implements Parcelable { ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, null, null, requestCode, new Intent[] { intent }, - resolvedType != null ? new String[] { resolvedType } : null, flags); + resolvedType != null ? new String[] { resolvedType } : null, + flags, options); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } @@ -247,6 +277,52 @@ public final class PendingIntent implements Parcelable { */ public static PendingIntent getActivities(Context context, int requestCode, Intent[] intents, int flags) { + return getActivities(context, requestCode, intents, flags, null); + } + + /** + * Like {@link #getActivity(Context, int, Intent, int)}, but allows an + * array of Intents to be supplied. The first Intent in the array is + * taken as the primary key for the PendingIntent, like the single Intent + * given to {@link #getActivity(Context, int, Intent, int)}. Upon sending + * the resulting PendingIntent, all of the Intents are started in the same + * way as they would be by passing them to {@link Context#startActivities(Intent[])}. + * + * <p class="note"> + * The <em>first</em> intent in the array will be started outside of the context of an + * existing activity, so you must use the {@link Intent#FLAG_ACTIVITY_NEW_TASK + * Intent.FLAG_ACTIVITY_NEW_TASK} launch flag in the Intent. (Activities after + * the first in the array are started in the context of the previous activity + * in the array, so FLAG_ACTIVITY_NEW_TASK is not needed nor desired for them.) + * </p> + * + * <p class="note"> + * The <em>last</em> intent in the array represents the key for the + * PendingIntent. In other words, it is the significant element for matching + * (as done with the single intent given to {@link #getActivity(Context, int, Intent, int)}, + * its content will be the subject of replacement by + * {@link #send(Context, int, Intent)} and {@link #FLAG_UPDATE_CURRENT}, etc. + * This is because it is the most specific of the supplied intents, and the + * UI the user actually sees when the intents are started. + * </p> + * + * @param context The Context in which this PendingIntent should start + * the activity. + * @param requestCode Private request code for the sender (currently + * not used). + * @param intents Array of Intents of the activities to be launched. + * @param flags May be {@link #FLAG_ONE_SHOT}, {@link #FLAG_NO_CREATE}, + * {@link #FLAG_CANCEL_CURRENT}, {@link #FLAG_UPDATE_CURRENT}, + * or any of the flags as supported by + * {@link Intent#fillIn Intent.fillIn()} to control which unspecified parts + * of the intent that can be supplied when the actual send happens. + * + * @return Returns an existing or new PendingIntent matching the given + * parameters. May return null only if {@link #FLAG_NO_CREATE} has been + * supplied. + */ + public static PendingIntent getActivities(Context context, int requestCode, + Intent[] intents, int flags, Bundle options) { String packageName = context.getPackageName(); String[] resolvedTypes = new String[intents.length]; for (int i=0; i<intents.length; i++) { @@ -257,7 +333,7 @@ public final class PendingIntent implements Parcelable { IIntentSender target = ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_ACTIVITY, packageName, - null, null, requestCode, intents, resolvedTypes, flags); + null, null, requestCode, intents, resolvedTypes, flags, options); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } @@ -294,7 +370,8 @@ public final class PendingIntent implements Parcelable { ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_BROADCAST, packageName, null, null, requestCode, new Intent[] { intent }, - resolvedType != null ? new String[] { resolvedType } : null, flags); + resolvedType != null ? new String[] { resolvedType } : null, + flags, null); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } @@ -332,7 +409,8 @@ public final class PendingIntent implements Parcelable { ActivityManagerNative.getDefault().getIntentSender( ActivityManager.INTENT_SENDER_SERVICE, packageName, null, null, requestCode, new Intent[] { intent }, - resolvedType != null ? new String[] { resolvedType } : null, flags); + resolvedType != null ? new String[] { resolvedType } : null, + flags, null); return target != null ? new PendingIntent(target) : null; } catch (RemoteException e) { } diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index ec67d8c..05ef194 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -270,19 +270,24 @@ public abstract class ContentProvider implements ComponentCallbacks2 { return CancellationSignal.createTransport(); } - private boolean hasReadPermission(Uri uri) { + private void enforceReadPermission(Uri uri) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); + String missingPerm = null; if (uid == mMyUid) { - return true; + return; + } - } else if (mExported) { + if (mExported) { final String componentPerm = getReadPermission(); - if (componentPerm != null - && (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED)) { - return true; + if (componentPerm != null) { + if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) { + return; + } else { + missingPerm = componentPerm; + } } // track if unprotected read is allowed; any denied @@ -296,11 +301,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 { final String pathPerm = pp.getReadPermission(); if (pathPerm != null && pp.match(path)) { if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) { - return true; + return; } else { // any denied <path-permission> means we lose // default <provider> access. allowDefaultRead = false; + missingPerm = pathPerm; } } } @@ -308,44 +314,41 @@ public abstract class ContentProvider implements ComponentCallbacks2 { // if we passed <path-permission> checks above, and no default // <provider> permission, then allow access. - if (allowDefaultRead) return true; + if (allowDefaultRead) return; } // last chance, check against any uri grants if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) == PERMISSION_GRANTED) { - return true; - } - - return false; - } - - private void enforceReadPermission(Uri uri) { - if (hasReadPermission(uri)) { return; } - String msg = "Permission Denial: reading " - + ContentProvider.this.getClass().getName() - + " uri " + uri + " from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid() - + " requires " + getReadPermission(); - throw new SecurityException(msg); + final String failReason = mExported + ? " requires " + missingPerm + ", or grantUriPermission()" + : " requires the provider be exported, or grantUriPermission()"; + throw new SecurityException("Permission Denial: reading " + + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid + + ", uid=" + uid + failReason); } - private boolean hasWritePermission(Uri uri) { + private void enforceWritePermission(Uri uri) throws SecurityException { final Context context = getContext(); final int pid = Binder.getCallingPid(); final int uid = Binder.getCallingUid(); + String missingPerm = null; if (uid == mMyUid) { - return true; + return; + } - } else if (mExported) { + if (mExported) { final String componentPerm = getWritePermission(); - if (componentPerm != null - && (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED)) { - return true; + if (componentPerm != null) { + if (context.checkPermission(componentPerm, pid, uid) == PERMISSION_GRANTED) { + return; + } else { + missingPerm = componentPerm; + } } // track if unprotected write is allowed; any denied @@ -359,11 +362,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 { final String pathPerm = pp.getWritePermission(); if (pathPerm != null && pp.match(path)) { if (context.checkPermission(pathPerm, pid, uid) == PERMISSION_GRANTED) { - return true; + return; } else { // any denied <path-permission> means we lose // default <provider> access. allowDefaultWrite = false; + missingPerm = pathPerm; } } } @@ -371,33 +375,24 @@ public abstract class ContentProvider implements ComponentCallbacks2 { // if we passed <path-permission> checks above, and no default // <provider> permission, then allow access. - if (allowDefaultWrite) return true; + if (allowDefaultWrite) return; } // last chance, check against any uri grants if (context.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == PERMISSION_GRANTED) { - return true; - } - - return false; - } - - private void enforceWritePermission(Uri uri) { - if (hasWritePermission(uri)) { return; } - - String msg = "Permission Denial: writing " - + ContentProvider.this.getClass().getName() - + " uri " + uri + " from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingUid() - + " requires " + getWritePermission(); - throw new SecurityException(msg); + + final String failReason = mExported + ? " requires " + missingPerm + ", or grantUriPermission()" + : " requires the provider be exported, or grantUriPermission()"; + throw new SecurityException("Permission Denial: writing " + + ContentProvider.this.getClass().getName() + " uri " + uri + " from pid=" + pid + + ", uid=" + uid + failReason); } } - /** * Retrieves the Context this provider is running in. Only available once * {@link #onCreate} has been called -- this will return null in the diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 19a5bc0..741a6e9 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -846,7 +846,9 @@ public abstract class Context { * * @param intent The description of the activity to start. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * May be null if there are no options. See {@link android.app.ActivityOptions} + * for how to build the Bundle supplied here; there are no supported definitions + * for building it manually. * * @throws ActivityNotFoundException * @@ -884,7 +886,8 @@ public abstract class Context { * * @param intents An array of Intents to be started. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. * * @throws ActivityNotFoundException * @@ -930,7 +933,10 @@ public abstract class Context { * <var>flagsMask</var> * @param extraFlags Always set to 0. * @param options Additional options for how the Activity should be started. - * May be null if there are no options. + * See {@link android.content.Context#startActivity(Intent, Bundle) + * Context.startActivity(Intent, Bundle)} for more details. If options + * have also been supplied by the IntentSender, options given here will + * override any that conflict with those given by the IntentSender. * * @see #startActivity(Intent, Bundle) * @see #startIntentSender(IntentSender, Intent, int, int, int) diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 95b6fee..9bd1940 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -370,4 +370,7 @@ interface IPackageManager { boolean isFirstBoot(); List<UserInfo> getUsers(); + + void setPermissionEnforcement(String permission, int enforcement); + int getPermissionEnforcement(String permission); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 544bd9c..55426b8 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1090,6 +1090,11 @@ public abstract class PackageManager { public static final String EXTRA_VERIFICATION_INSTALL_FLAGS = "android.content.pm.extra.VERIFICATION_INSTALL_FLAGS"; + /** {@hide} */ + public static final int ENFORCEMENT_DEFAULT = 0; + /** {@hide} */ + public static final int ENFORCEMENT_YES = 1; + /** * Retrieve overall information about an application package that is * installed on the system. diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 6139296..770bf1c 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -98,6 +98,12 @@ public class Process { public static final int SDCARD_RW_GID = 1015; /** + * Defines the UID/GID for the group that controls VPN services. + * @hide + */ + public static final int VPN_UID = 1016; + + /** * Defines the UID/GID for the NFC service process. * @hide */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6d1f207..fdf3a814 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -1503,7 +1503,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal * apps. * @hide */ - public static final boolean USE_DISPLAY_LIST_PROPERTIES = false; + public static final boolean USE_DISPLAY_LIST_PROPERTIES = true; /** * Map used to store views' tags. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 04ad649..4eb70ab 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -841,7 +841,9 @@ public final class ViewRootImpl implements ViewParent, localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom); // Intersect with the bounds of the window to skip // updates that lie outside of the visible region - localDirty.intersect(0, 0, mWidth, mHeight); + final float appScale = mAttachInfo.mApplicationScale; + localDirty.intersect(0, 0, + (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f)); if (!mWillDrawSoon) { scheduleTraversals(); diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java index 1644b06..40c3778 100644 --- a/core/java/android/webkit/HTML5VideoViewProxy.java +++ b/core/java/android/webkit/HTML5VideoViewProxy.java @@ -146,6 +146,12 @@ class HTML5VideoViewProxy extends Handler // Save the inline video info and inherit it in the full screen int savePosition = 0; if (mHTML5VideoView != null) { + // We don't allow enter full screen mode while the previous + // full screen video hasn't finished yet. + if (!mHTML5VideoView.fullScreenExited() && mHTML5VideoView.isFullScreenMode()) { + Log.w(LOGTAG, "Try to reenter the full screen mode"); + return; + } // If we are playing the same video, then it is better to // save the current position. if (layerId == mHTML5VideoView.getVideoLayerId()) { |
